diff options
| author | 1-rafael-1 <[email protected]> | 2025-09-15 20:07:18 +0200 |
|---|---|---|
| committer | 1-rafael-1 <[email protected]> | 2025-09-15 20:07:18 +0200 |
| commit | 6bb3d2c0720fa082f27d3cdb70f516058497ec87 (patch) | |
| tree | 5a1e255cff999b00800f203b91a759c720c973e5 /examples | |
| parent | eb685574601d98c44faed9a3534d056199b46e20 (diff) | |
| parent | 92a6fd2946f2cbb15359290f68aa360953da2ff7 (diff) | |
Merge branch 'main' into rp2040-rtc-alarm
Diffstat (limited to 'examples')
363 files changed, 7983 insertions, 1485 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 4ae0e6a77..b0cc63a6c 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml | |||
| @@ -3,18 +3,19 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-nrf-examples" | 3 | name = "embassy-boot-nrf-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } |
| 11 | embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } | 12 | embassy-nrf = { version = "0.7.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } |
| 12 | embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } | 13 | embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } |
| 13 | embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } | 14 | embassy-boot-nrf = { version = "0.8.0", path = "../../../../embassy-boot-nrf", features = [] } |
| 14 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 15 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 15 | 16 | ||
| 16 | defmt = { version = "0.3", optional = true } | 17 | defmt = { version = "1.0.1", optional = true } |
| 17 | defmt-rtt = { version = "0.4", optional = true } | 18 | defmt-rtt = { version = "1.0.0", optional = true } |
| 18 | panic-reset = { version = "0.1.1" } | 19 | panic-reset = { version = "0.1.1" } |
| 19 | embedded-hal = { version = "0.2.6" } | 20 | embedded-hal = { version = "0.2.6" } |
| 20 | 21 | ||
| @@ -32,3 +33,12 @@ defmt = [ | |||
| 32 | "embassy-boot-nrf/defmt", | 33 | "embassy-boot-nrf/defmt", |
| 33 | "embassy-sync/defmt", | 34 | "embassy-sync/defmt", |
| 34 | ] | 35 | ] |
| 36 | |||
| 37 | [package.metadata.embassy] | ||
| 38 | build = [ | ||
| 39 | { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" }, | ||
| 40 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" }, | ||
| 41 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" }, | ||
| 42 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" }, | ||
| 43 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" } | ||
| 44 | ] | ||
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 3c0d207d1..d86386b00 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml | |||
| @@ -3,18 +3,19 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-rp-examples" | 3 | name = "embassy-boot-rp-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } |
| 11 | embassy-rp = { version = "0.4.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } | 12 | embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } |
| 12 | embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } | 13 | embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"], optional = true } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true } |
| 18 | panic-reset = { version = "0.1.1", optional = true } | 19 | panic-reset = { version = "0.1.1", optional = true } |
| 19 | embedded-hal = { version = "0.2.6" } | 20 | embedded-hal = { version = "0.2.6" } |
| 20 | 21 | ||
| @@ -34,3 +35,8 @@ skip-include = [] | |||
| 34 | 35 | ||
| 35 | [profile.release] | 36 | [profile.release] |
| 36 | debug = true | 37 | debug = true |
| 38 | |||
| 39 | [package.metadata.embassy] | ||
| 40 | build = [ | ||
| 41 | { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/rp" } | ||
| 42 | ] | ||
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index ede0c07da..e6d7b3d4f 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs | |||
| @@ -54,7 +54,7 @@ async fn main(_s: Spawner) { | |||
| 54 | for chunk in APP_B.chunks(4096) { | 54 | for chunk in APP_B.chunks(4096) { |
| 55 | buf.0[..chunk.len()].copy_from_slice(chunk); | 55 | buf.0[..chunk.len()].copy_from_slice(chunk); |
| 56 | defmt::info!("writing block at offset {}", offset); | 56 | defmt::info!("writing block at offset {}", offset); |
| 57 | writer.write(offset, &buf.0[..]).unwrap(); | 57 | writer.write(offset, &buf.0[..chunk.len()]).unwrap(); |
| 58 | offset += chunk.len() as u32; | 58 | offset += chunk.len() as u32; |
| 59 | } | 59 | } |
| 60 | watchdog.feed(); | 60 | watchdog.feed(); |
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index f32727ea8..cd5f422fc 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32f3-examples" | 3 | name = "embassy-boot-stm32f3-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32" } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | 20 | ||
| @@ -29,3 +30,8 @@ defmt = [ | |||
| 29 | "embassy-sync/defmt", | 30 | "embassy-sync/defmt", |
| 30 | ] | 31 | ] |
| 31 | skip-include = [] | 32 | skip-include = [] |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f3" } | ||
| 37 | ] | ||
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index d62c67742..c3921a166 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32f7-examples" | 3 | name = "embassy-boot-stm32f7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | embedded-storage = "0.3.1" | 20 | embedded-storage = "0.3.1" |
| @@ -30,3 +31,8 @@ defmt = [ | |||
| 30 | "embassy-sync/defmt", | 31 | "embassy-sync/defmt", |
| 31 | ] | 32 | ] |
| 32 | skip-include = [] | 33 | skip-include = [] |
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f7" } | ||
| 38 | ] | ||
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index dd3a32e45..ca186d4d9 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32h7-examples" | 3 | name = "embassy-boot-stm32h7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | embedded-storage = "0.3.1" | 20 | embedded-storage = "0.3.1" |
| @@ -30,3 +31,8 @@ defmt = [ | |||
| 30 | "embassy-sync/defmt", | 31 | "embassy-sync/defmt", |
| 31 | ] | 32 | ] |
| 32 | skip-include = [] | 33 | skip-include = [] |
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32h7" } | ||
| 38 | ] | ||
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 0b9e9b96a..be08956f1 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32l0-examples" | 3 | name = "embassy-boot-stm32l0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | 20 | ||
| @@ -29,3 +30,8 @@ defmt = [ | |||
| 29 | "embassy-sync/defmt", | 30 | "embassy-sync/defmt", |
| 30 | ] | 31 | ] |
| 31 | skip-include = [] | 32 | skip-include = [] |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l0" } | ||
| 37 | ] | ||
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 490541a2e..207eed733 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32l1-examples" | 3 | name = "embassy-boot-stm32l1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | 20 | ||
| @@ -29,3 +30,8 @@ defmt = [ | |||
| 29 | "embassy-sync/defmt", | 30 | "embassy-sync/defmt", |
| 30 | ] | 31 | ] |
| 31 | skip-include = [] | 32 | skip-include = [] |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv7m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l1" } | ||
| 37 | ] | ||
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index c3aa31161..22b9642d8 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32l4-examples" | 3 | name = "embassy-boot-stm32l4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | 20 | ||
| @@ -29,3 +30,8 @@ defmt = [ | |||
| 29 | "embassy-sync/defmt", | 30 | "embassy-sync/defmt", |
| 30 | ] | 31 | ] |
| 31 | skip-include = [] | 32 | skip-include = [] |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l4" } | ||
| 37 | ] | ||
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index a89e2bb6e..e2be4f470 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml | |||
| @@ -3,19 +3,20 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32wb-dfu-examples" | 3 | name = "embassy-boot-stm32wb-dfu-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } | 15 | embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } |
| 15 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } | 16 | embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } |
| 16 | 17 | ||
| 17 | defmt = { version = "0.3", optional = true } | 18 | defmt = { version = "1.0.1", optional = true } |
| 18 | defmt-rtt = { version = "0.4", optional = true } | 19 | defmt-rtt = { version = "1.0.0", optional = true } |
| 19 | panic-reset = { version = "0.1.1" } | 20 | panic-reset = { version = "0.1.1" } |
| 20 | embedded-hal = { version = "0.2.6" } | 21 | embedded-hal = { version = "0.2.6" } |
| 21 | 22 | ||
| @@ -30,3 +31,8 @@ defmt = [ | |||
| 30 | "embassy-boot-stm32/defmt", | 31 | "embassy-boot-stm32/defmt", |
| 31 | "embassy-sync/defmt", | 32 | "embassy-sync/defmt", |
| 32 | ] | 33 | ] |
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/boot/stm32wb-dfu" } | ||
| 38 | ] | ||
diff --git a/examples/boot/application/stm32wb-dfu/memory.x b/examples/boot/application/stm32wb-dfu/memory.x index ff1b800d2..f1e6b053c 100644 --- a/examples/boot/application/stm32wb-dfu/memory.x +++ b/examples/boot/application/stm32wb-dfu/memory.x | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ |
| 4 | BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 24K | 4 | BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 48K |
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K |
| 6 | FLASH : ORIGIN = 0x08008000, LENGTH = 128K | 6 | FLASH : ORIGIN = 0x0800D000, LENGTH = 120K |
| 7 | DFU : ORIGIN = 0x08028000, LENGTH = 132K | 7 | DFU : ORIGIN = 0x0802B000, LENGTH = 120K |
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K | 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K |
| 9 | } | 9 | } |
| 10 | 10 | ||
diff --git a/examples/boot/application/stm32wb-dfu/secrets/key.sec b/examples/boot/application/stm32wb-dfu/secrets/key.sec new file mode 100644 index 000000000..52e7f125b --- /dev/null +++ b/examples/boot/application/stm32wb-dfu/secrets/key.sec | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | untrusted comment: signify secret key | ||
| 2 | RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI= | ||
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index dda2b795b..5e7b71f5a 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs | |||
| @@ -13,7 +13,7 @@ use embassy_stm32::usb::{self, Driver}; | |||
| 13 | use embassy_stm32::{bind_interrupts, peripherals}; | 13 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 14 | use embassy_sync::blocking_mutex::Mutex; | 14 | use embassy_sync::blocking_mutex::Mutex; |
| 15 | use embassy_time::Duration; | 15 | use embassy_time::Duration; |
| 16 | use embassy_usb::Builder; | 16 | use embassy_usb::{msos, Builder}; |
| 17 | use embassy_usb_dfu::consts::DfuAttributes; | 17 | use embassy_usb_dfu::consts::DfuAttributes; |
| 18 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | 18 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; |
| 19 | use panic_reset as _; | 19 | use panic_reset as _; |
| @@ -22,6 +22,11 @@ bind_interrupts!(struct Irqs { | |||
| 22 | USB_LP => usb::InterruptHandler<peripherals::USB>; | 22 | USB_LP => usb::InterruptHandler<peripherals::USB>; |
| 23 | }); | 23 | }); |
| 24 | 24 | ||
| 25 | // This is a randomly generated GUID to allow clients on Windows to find your device. | ||
| 26 | // | ||
| 27 | // N.B. update to a custom GUID for your own device! | ||
| 28 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | ||
| 29 | |||
| 25 | #[embassy_executor::main] | 30 | #[embassy_executor::main] |
| 26 | async fn main(_spawner: Spawner) { | 31 | async fn main(_spawner: Spawner) { |
| 27 | let mut config = embassy_stm32::Config::default(); | 32 | let mut config = embassy_stm32::Config::default(); |
| @@ -54,7 +59,28 @@ async fn main(_spawner: Spawner) { | |||
| 54 | &mut control_buf, | 59 | &mut control_buf, |
| 55 | ); | 60 | ); |
| 56 | 61 | ||
| 57 | usb_dfu(&mut builder, &mut state, Duration::from_millis(2500)); | 62 | // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. |
| 63 | // Otherwise users need to do this manually using a tool like Zadig. | ||
| 64 | // | ||
| 65 | // It seems these always need to be at added at the device level for this to work and for | ||
| 66 | // composite devices they also need to be added on the function level (as shown later). | ||
| 67 | // | ||
| 68 | builder.msos_descriptor(msos::windows_version::WIN8_1, 2); | ||
| 69 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 70 | builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 71 | "DeviceInterfaceGUIDs", | ||
| 72 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 73 | )); | ||
| 74 | |||
| 75 | usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), |func| { | ||
| 76 | // You likely don't have to add these function level headers if your USB device is not composite | ||
| 77 | // (i.e. if your device does not expose another interface in addition to DFU) | ||
| 78 | func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 79 | func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 80 | "DeviceInterfaceGUIDs", | ||
| 81 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 82 | )); | ||
| 83 | }); | ||
| 58 | 84 | ||
| 59 | let mut dev = builder.build(); | 85 | let mut dev = builder.build(); |
| 60 | dev.run().await | 86 | dev.run().await |
diff --git a/examples/boot/application/stm32wba-dfu/.cargo/config.toml b/examples/boot/application/stm32wba-dfu/.cargo/config.toml new file mode 100644 index 000000000..a18ec3944 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/.cargo/config.toml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace your chip as listed in `probe-rs chip list` | ||
| 3 | runner = "probe-rs run --chip STM32WBA65RI" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv8m.main-none-eabihf" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "trace" | ||
diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml new file mode 100644 index 000000000..6f4213b2c --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-boot-stm32wba-dfu-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } | ||
| 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | ||
| 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | ||
| 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } | ||
| 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } | ||
| 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } | ||
| 15 | embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } | ||
| 16 | embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } | ||
| 17 | |||
| 18 | defmt = { version = "1.0.1", optional = true } | ||
| 19 | defmt-rtt = { version = "1.0.0", optional = true } | ||
| 20 | panic-reset = { version = "0.1.1" } | ||
| 21 | embedded-hal = { version = "0.2.6" } | ||
| 22 | |||
| 23 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 24 | cortex-m-rt = "0.7.0" | ||
| 25 | |||
| 26 | [features] | ||
| 27 | defmt = [ | ||
| 28 | "dep:defmt", | ||
| 29 | "dep:defmt-rtt", | ||
| 30 | "embassy-stm32/defmt", | ||
| 31 | "embassy-boot-stm32/defmt", | ||
| 32 | "embassy-sync/defmt", | ||
| 33 | ] | ||
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/boot/stm32wba-dfu" } | ||
| 38 | ] | ||
diff --git a/examples/boot/application/stm32wba-dfu/README.md b/examples/boot/application/stm32wba-dfu/README.md new file mode 100644 index 000000000..30692034c --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/README.md | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | # Examples using bootloader | ||
| 2 | |||
| 3 | Example for STM32WBA demonstrating the USB DFU application. | ||
| 4 | |||
| 5 | ## Usage | ||
| 6 | |||
| 7 | ``` | ||
| 8 | cargo flash --release --chip STM32WBA65RI | ||
| 9 | ``` | ||
diff --git a/examples/boot/application/stm32wba-dfu/build.rs b/examples/boot/application/stm32wba-dfu/build.rs new file mode 100644 index 000000000..e1da69328 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/build.rs | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | //! This build script copies the `memory.x` file from the crate root into | ||
| 2 | //! a directory where the linker can always find it at build time. | ||
| 3 | //! For many projects this is optional, as the linker always searches the | ||
| 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you | ||
| 5 | //! are using a workspace or have a more complicated build setup, this | ||
| 6 | //! build script becomes required. Additionally, by requesting that | ||
| 7 | //! Cargo re-run the build script whenever `memory.x` is changed, | ||
| 8 | //! updating `memory.x` ensures a rebuild of the application with the | ||
| 9 | //! new memory settings. | ||
| 10 | |||
| 11 | use std::env; | ||
| 12 | use std::fs::File; | ||
| 13 | use std::io::Write; | ||
| 14 | use std::path::PathBuf; | ||
| 15 | |||
| 16 | fn main() { | ||
| 17 | // Put `memory.x` in our output directory and ensure it's | ||
| 18 | // on the linker search path. | ||
| 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 20 | File::create(out.join("memory.x")) | ||
| 21 | .unwrap() | ||
| 22 | .write_all(include_bytes!("memory.x")) | ||
| 23 | .unwrap(); | ||
| 24 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 25 | |||
| 26 | // By default, Cargo will re-run a build script whenever | ||
| 27 | // any file in the project changes. By specifying `memory.x` | ||
| 28 | // here, we ensure the build script is only re-run when | ||
| 29 | // `memory.x` is changed. | ||
| 30 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 31 | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 34 | if env::var("CARGO_FEATURE_DEFMT").is_ok() { | ||
| 35 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/examples/boot/application/stm32wba-dfu/memory.x b/examples/boot/application/stm32wba-dfu/memory.x new file mode 100644 index 000000000..fcdb6b6d2 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/memory.x | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 80K | ||
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K | ||
| 6 | FLASH : ORIGIN = 0x08016000, LENGTH = 120K | ||
| 7 | DFU : ORIGIN = 0x0803C000, LENGTH = 160K | ||
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K | ||
| 9 | } | ||
| 10 | |||
| 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); | ||
| 12 | __bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); | ||
| 13 | |||
| 14 | __bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER); | ||
| 15 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER); | ||
diff --git a/examples/boot/application/stm32wba-dfu/secrets/key.sec b/examples/boot/application/stm32wba-dfu/secrets/key.sec new file mode 100644 index 000000000..52e7f125b --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/secrets/key.sec | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | untrusted comment: signify secret key | ||
| 2 | RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI= | ||
diff --git a/examples/boot/application/stm32wba-dfu/src/main.rs b/examples/boot/application/stm32wba-dfu/src/main.rs new file mode 100644 index 000000000..bf17a7150 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/src/main.rs | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::cell::RefCell; | ||
| 5 | |||
| 6 | #[cfg(feature = "defmt")] | ||
| 7 | use defmt_rtt as _; | ||
| 8 | use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareState, FirmwareUpdaterConfig}; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | ||
| 11 | use embassy_stm32::usb::{self, Driver}; | ||
| 12 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 13 | use embassy_sync::blocking_mutex::Mutex; | ||
| 14 | use embassy_time::Duration; | ||
| 15 | use embassy_usb::{msos, Builder}; | ||
| 16 | use embassy_usb_dfu::consts::DfuAttributes; | ||
| 17 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | ||
| 18 | use panic_reset as _; | ||
| 19 | |||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; | ||
| 22 | }); | ||
| 23 | |||
| 24 | // This is a randomly generated GUID to allow clients on Windows to find your device. | ||
| 25 | // | ||
| 26 | // N.B. update to a custom GUID for your own device! | ||
| 27 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | let mut config = embassy_stm32::Config::default(); | ||
| 32 | |||
| 33 | { | ||
| 34 | use embassy_stm32::rcc::*; | ||
| 35 | config.rcc.pll1 = Some(Pll { | ||
| 36 | source: PllSource::HSI, | ||
| 37 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 38 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 39 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 40 | divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz | ||
| 41 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) | ||
| 42 | frac: Some(0), // Fractional part (disabled) | ||
| 43 | }); | ||
| 44 | |||
| 45 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 46 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 47 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 48 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 49 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 50 | |||
| 51 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 52 | config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; | ||
| 53 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 54 | } | ||
| 55 | |||
| 56 | let p = embassy_stm32::init(config); | ||
| 57 | let flash = Flash::new_blocking(p.FLASH); | ||
| 58 | let flash = Mutex::new(RefCell::new(flash)); | ||
| 59 | |||
| 60 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash); | ||
| 61 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | ||
| 62 | let mut firmware_state = BlockingFirmwareState::from_config(config, &mut magic.0); | ||
| 63 | firmware_state.mark_booted().expect("Failed to mark booted"); | ||
| 64 | |||
| 65 | // Create the driver, from the HAL. | ||
| 66 | let mut ep_out_buffer = [0u8; 256]; | ||
| 67 | let mut config = embassy_stm32::usb::Config::default(); | ||
| 68 | config.vbus_detection = false; | ||
| 69 | |||
| 70 | let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); | ||
| 71 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); | ||
| 72 | config.manufacturer = Some("Embassy"); | ||
| 73 | config.product = Some("USB-DFU Runtime example"); | ||
| 74 | config.serial_number = Some("1235678"); | ||
| 75 | |||
| 76 | let mut config_descriptor = [0; 256]; | ||
| 77 | let mut bos_descriptor = [0; 256]; | ||
| 78 | let mut control_buf = [0; 64]; | ||
| 79 | let mut state = Control::new(firmware_state, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); | ||
| 80 | let mut builder = Builder::new( | ||
| 81 | driver, | ||
| 82 | config, | ||
| 83 | &mut config_descriptor, | ||
| 84 | &mut bos_descriptor, | ||
| 85 | &mut [], | ||
| 86 | &mut control_buf, | ||
| 87 | ); | ||
| 88 | |||
| 89 | // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. | ||
| 90 | // Otherwise users need to do this manually using a tool like Zadig. | ||
| 91 | // | ||
| 92 | // It seems these always need to be at added at the device level for this to work and for | ||
| 93 | // composite devices they also need to be added on the function level (as shown later). | ||
| 94 | |||
| 95 | builder.msos_descriptor(msos::windows_version::WIN8_1, 2); | ||
| 96 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 97 | builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 98 | "DeviceInterfaceGUIDs", | ||
| 99 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 100 | )); | ||
| 101 | |||
| 102 | usb_dfu(&mut builder, &mut state, Duration::from_millis(1000), |func| { | ||
| 103 | // You likely don't have to add these function level headers if your USB device is not composite | ||
| 104 | // (i.e. if your device does not expose another interface in addition to DFU) | ||
| 105 | func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 106 | func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 107 | "DeviceInterfaceGUIDs", | ||
| 108 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 109 | )); | ||
| 110 | }); | ||
| 111 | |||
| 112 | let mut dev = builder.build(); | ||
| 113 | dev.run().await | ||
| 114 | } | ||
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index f4d7ae712..8d1446ba9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-boot-stm32wl-examples" | 3 | name = "embassy-boot-stm32wl-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 13 | embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "1.0.1", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "1.0.0", optional = true } |
| 17 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 18 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 19 | 20 | ||
| @@ -29,3 +30,8 @@ defmt = [ | |||
| 29 | "embassy-sync/defmt", | 30 | "embassy-sync/defmt", |
| 30 | ] | 31 | ] |
| 31 | skip-include = [] | 32 | skip-include = [] |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32wl" } | ||
| 37 | ] | ||
diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 34a0553e3..72b7114d4 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml | |||
| @@ -4,15 +4,16 @@ name = "nrf-bootloader-example" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Bootloader for nRF chips" | 5 | description = "Bootloader for nRF chips" |
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | defmt = { version = "0.3", optional = true } | 10 | defmt = { version = "1.0.1", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 11 | defmt-rtt = { version = "1.0.0", optional = true } |
| 11 | 12 | ||
| 12 | embassy-nrf = { path = "../../../../embassy-nrf", features = [] } | 13 | embassy-nrf = { path = "../../../../embassy-nrf", features = [] } |
| 13 | embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } | 14 | embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } |
| 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 15 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 16 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 16 | cortex-m-rt = { version = "0.7" } | 17 | cortex-m-rt = { version = "0.7" } |
| 17 | cfg-if = "1.0.0" | 18 | cfg-if = "1.0.0" |
| 18 | 19 | ||
| @@ -57,3 +58,12 @@ debug = false | |||
| 57 | debug-assertions = false | 58 | debug-assertions = false |
| 58 | opt-level = 0 | 59 | opt-level = 0 |
| 59 | overflow-checks = false | 60 | overflow-checks = false |
| 61 | |||
| 62 | [package.metadata.embassy] | ||
| 63 | build = [ | ||
| 64 | { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840"] }, | ||
| 65 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] }, | ||
| 66 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] }, | ||
| 67 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] }, | ||
| 68 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] } | ||
| 69 | ] | ||
diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 7c9c3c779..93a1c4edf 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml | |||
| @@ -4,14 +4,15 @@ name = "rp-bootloader-example" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for RP2040 chips" | 5 | description = "Example bootloader for RP2040 chips" |
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | defmt = { version = "0.3", optional = true } | 10 | defmt = { version = "1.0.1", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 11 | defmt-rtt = { version = "1.0.0", optional = true } |
| 11 | 12 | ||
| 12 | embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } | 13 | embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } |
| 13 | embassy-boot-rp = { path = "../../../../embassy-boot-rp" } | 14 | embassy-boot-rp = { path = "../../../../embassy-boot-rp" } |
| 14 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 15 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 15 | embassy-time = { path = "../../../../embassy-time", features = [] } | 16 | embassy-time = { path = "../../../../embassy-time", features = [] } |
| 16 | 17 | ||
| 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| @@ -31,3 +32,8 @@ defmt = [ | |||
| 31 | [profile.release] | 32 | [profile.release] |
| 32 | debug = true | 33 | debug = true |
| 33 | opt-level = 's' | 34 | opt-level = 's' |
| 35 | |||
| 36 | [package.metadata.embassy] | ||
| 37 | build = [ | ||
| 38 | { target = "thumbv6m-none-eabi" } | ||
| 39 | ] | ||
diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 4beb9c61c..95ca20a59 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml | |||
| @@ -4,10 +4,11 @@ name = "stm32-bootloader-dual-bank-flash-example" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for dual-bank flash STM32 chips" | 5 | description = "Example bootloader for dual-bank flash STM32 chips" |
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | defmt = { version = "0.3", optional = true } | 10 | defmt = { version = "1.0.1", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 11 | defmt-rtt = { version = "1.0.0", optional = true } |
| 11 | 12 | ||
| 12 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } | 13 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } |
| 13 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } | 14 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } |
| @@ -15,7 +16,7 @@ cortex-m = { version = "0.7.6", features = [ | |||
| 15 | "inline-asm", | 16 | "inline-asm", |
| 16 | "critical-section-single-core", | 17 | "critical-section-single-core", |
| 17 | ] } | 18 | ] } |
| 18 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 19 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 19 | cortex-m-rt = { version = "0.7" } | 20 | cortex-m-rt = { version = "0.7" } |
| 20 | embedded-storage = "0.3.1" | 21 | embedded-storage = "0.3.1" |
| 21 | embedded-storage-async = "0.4.0" | 22 | embedded-storage-async = "0.4.0" |
| @@ -54,3 +55,8 @@ debug = false | |||
| 54 | debug-assertions = false | 55 | debug-assertions = false |
| 55 | opt-level = 0 | 56 | opt-level = 0 |
| 56 | overflow-checks = false | 57 | overflow-checks = false |
| 58 | |||
| 59 | [package.metadata.embassy] | ||
| 60 | build = [ | ||
| 61 | { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32h743zi"] } | ||
| 62 | ] | ||
diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index 9abad8636..526637f37 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml | |||
| @@ -4,15 +4,16 @@ name = "stm32-bootloader-example" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for STM32 chips" | 5 | description = "Example bootloader for STM32 chips" |
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | defmt = { version = "0.3", optional = true } | 10 | defmt = { version = "1.0.1", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 11 | defmt-rtt = { version = "1.0.0", optional = true } |
| 11 | 12 | ||
| 12 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } | 13 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } |
| 13 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } | 14 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } |
| 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 15 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 16 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 16 | cortex-m-rt = { version = "0.7" } | 17 | cortex-m-rt = { version = "0.7" } |
| 17 | embedded-storage = "0.3.1" | 18 | embedded-storage = "0.3.1" |
| 18 | embedded-storage-async = "0.4.0" | 19 | embedded-storage-async = "0.4.0" |
| @@ -56,3 +57,8 @@ debug = false | |||
| 56 | debug-assertions = false | 57 | debug-assertions = false |
| 57 | opt-level = 0 | 58 | opt-level = 0 |
| 58 | overflow-checks = false | 59 | overflow-checks = false |
| 60 | |||
| 61 | [package.metadata.embassy] | ||
| 62 | build = [ | ||
| 63 | { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32l496zg"] } | ||
| 64 | ] | ||
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 01343b86b..ef10aeabf 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml | |||
| @@ -4,22 +4,23 @@ name = "stm32wb-dfu-bootloader-example" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example USB DFUbootloader for the STM32WB series of chips" | 5 | description = "Example USB DFUbootloader for the STM32WB series of chips" |
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | defmt = { version = "0.3", optional = true } | 10 | defmt = { version = "1.0.1", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 11 | defmt-rtt = { version = "1.0.0", optional = true } |
| 11 | 12 | ||
| 12 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } | 13 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } |
| 13 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } | 14 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } |
| 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 15 | embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } | 16 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 16 | cortex-m-rt = { version = "0.7" } | 17 | cortex-m-rt = { version = "0.7" } |
| 17 | embedded-storage = "0.3.1" | 18 | embedded-storage = "0.3.1" |
| 18 | embedded-storage-async = "0.4.0" | 19 | embedded-storage-async = "0.4.0" |
| 19 | cfg-if = "1.0.0" | 20 | cfg-if = "1.0.0" |
| 20 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } | 21 | embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } |
| 21 | embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb", default-features = false } | 22 | embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } |
| 22 | embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } | 23 | embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } |
| 23 | 24 | ||
| 24 | [features] | 25 | [features] |
| 25 | defmt = [ | 26 | defmt = [ |
| @@ -30,6 +31,7 @@ defmt = [ | |||
| 30 | "embassy-usb/defmt", | 31 | "embassy-usb/defmt", |
| 31 | "embassy-usb-dfu/defmt" | 32 | "embassy-usb-dfu/defmt" |
| 32 | ] | 33 | ] |
| 34 | verify = ["embassy-usb-dfu/ed25519-salty"] | ||
| 33 | 35 | ||
| 34 | [profile.dev] | 36 | [profile.dev] |
| 35 | debug = 2 | 37 | debug = 2 |
| @@ -61,3 +63,9 @@ debug = false | |||
| 61 | debug-assertions = false | 63 | debug-assertions = false |
| 62 | opt-level = 0 | 64 | opt-level = 0 |
| 63 | overflow-checks = false | 65 | overflow-checks = false |
| 66 | |||
| 67 | [package.metadata.embassy] | ||
| 68 | build = [ | ||
| 69 | { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg"] }, | ||
| 70 | { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg", "verify"] } | ||
| 71 | ] | ||
diff --git a/examples/boot/bootloader/stm32wb-dfu/README.md b/examples/boot/bootloader/stm32wb-dfu/README.md index 3c5f268a0..99a7002c4 100644 --- a/examples/boot/bootloader/stm32wb-dfu/README.md +++ b/examples/boot/bootloader/stm32wb-dfu/README.md | |||
| @@ -28,6 +28,32 @@ cargo objcopy --release -- -O binary fw.bin | |||
| 28 | dfu-util -d c0de:cafe -w -D fw.bin | 28 | dfu-util -d c0de:cafe -w -D fw.bin |
| 29 | ``` | 29 | ``` |
| 30 | 30 | ||
| 31 | ### 3. Sign Updates Before Flashing (Optional) | ||
| 32 | |||
| 33 | Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu. | ||
| 34 | |||
| 35 | To sign (and then verify) application updates, you will first need to generate a key pair: | ||
| 36 | |||
| 37 | ``` | ||
| 38 | signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec | ||
| 39 | tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short | ||
| 40 | ``` | ||
| 41 | |||
| 42 | Then you will need to sign all you binaries with the private key: | ||
| 43 | |||
| 44 | ``` | ||
| 45 | cargo objcopy --release -- -O binary fw.bin | ||
| 46 | shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt | ||
| 47 | signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig | ||
| 48 | cp fw.bin fw-signed.bin | ||
| 49 | tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin | ||
| 50 | dfu-util -d c0de:cafe -w -D fw-signed.bin | ||
| 51 | ``` | ||
| 52 | |||
| 53 | Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures. | ||
| 54 | |||
| 55 | N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system. | ||
| 56 | |||
| 31 | ## Troubleshooting | 57 | ## Troubleshooting |
| 32 | 58 | ||
| 33 | - Make sure your device is in DFU mode before flashing | 59 | - Make sure your device is in DFU mode before flashing |
diff --git a/examples/boot/bootloader/stm32wb-dfu/memory.x b/examples/boot/bootloader/stm32wb-dfu/memory.x index 858062631..77c4d2ee2 100644 --- a/examples/boot/bootloader/stm32wb-dfu/memory.x +++ b/examples/boot/bootloader/stm32wb-dfu/memory.x | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ |
| 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 24K | 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 48K |
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K |
| 6 | ACTIVE : ORIGIN = 0x08008000, LENGTH = 128K | 6 | ACTIVE : ORIGIN = 0x0800D000, LENGTH = 120K |
| 7 | DFU : ORIGIN = 0x08028000, LENGTH = 132K | 7 | DFU : ORIGIN = 0x0802B000, LENGTH = 120K |
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K | 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K |
| 9 | } | 9 | } |
| 10 | 10 | ||
diff --git a/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short new file mode 100644 index 000000000..7a4de8585 --- /dev/null +++ b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short | |||
| @@ -0,0 +1 @@ | |||
| gB��p�M�S��z��Kg��!�F���!4�r \ No newline at end of file | |||
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 28216806e..107f243fd 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs | |||
| @@ -20,9 +20,17 @@ bind_interrupts!(struct Irqs { | |||
| 20 | USB_LP => usb::InterruptHandler<peripherals::USB>; | 20 | USB_LP => usb::InterruptHandler<peripherals::USB>; |
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | // This is a randomly generated GUID to allow clients on Windows to find our device | 23 | // This is a randomly generated GUID to allow clients on Windows to find your device. |
| 24 | // | ||
| 25 | // N.B. update to a custom GUID for your own device! | ||
| 24 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | 26 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; |
| 25 | 27 | ||
| 28 | // This is a randomly generated example key. | ||
| 29 | // | ||
| 30 | // N.B. Please replace with your own! | ||
| 31 | #[cfg(feature = "verify")] | ||
| 32 | static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short"); | ||
| 33 | |||
| 26 | #[entry] | 34 | #[entry] |
| 27 | fn main() -> ! { | 35 | fn main() -> ! { |
| 28 | let mut config = embassy_stm32::Config::default(); | 36 | let mut config = embassy_stm32::Config::default(); |
| @@ -55,7 +63,13 @@ fn main() -> ! { | |||
| 55 | let mut config_descriptor = [0; 256]; | 63 | let mut config_descriptor = [0; 256]; |
| 56 | let mut bos_descriptor = [0; 256]; | 64 | let mut bos_descriptor = [0; 256]; |
| 57 | let mut control_buf = [0; 4096]; | 65 | let mut control_buf = [0; 4096]; |
| 66 | |||
| 67 | #[cfg(not(feature = "verify"))] | ||
| 58 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); | 68 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); |
| 69 | |||
| 70 | #[cfg(feature = "verify")] | ||
| 71 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY); | ||
| 72 | |||
| 59 | let mut builder = Builder::new( | 73 | let mut builder = Builder::new( |
| 60 | driver, | 74 | driver, |
| 61 | config, | 75 | config, |
| @@ -68,7 +82,8 @@ fn main() -> ! { | |||
| 68 | // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. | 82 | // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. |
| 69 | // Otherwise users need to do this manually using a tool like Zadig. | 83 | // Otherwise users need to do this manually using a tool like Zadig. |
| 70 | // | 84 | // |
| 71 | // It seems it is important for the DFU class that these headers be on the Device level. | 85 | // It seems these always need to be at added at the device level for this to work and for |
| 86 | // composite devices they also need to be added on the function level (as shown later). | ||
| 72 | // | 87 | // |
| 73 | builder.msos_descriptor(msos::windows_version::WIN8_1, 2); | 88 | builder.msos_descriptor(msos::windows_version::WIN8_1, 2); |
| 74 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | 89 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); |
| @@ -77,7 +92,15 @@ fn main() -> ! { | |||
| 77 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | 92 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), |
| 78 | )); | 93 | )); |
| 79 | 94 | ||
| 80 | usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state); | 95 | usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| { |
| 96 | // You likely don't have to add these function level headers if your USB device is not composite | ||
| 97 | // (i.e. if your device does not expose another interface in addition to DFU) | ||
| 98 | func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 99 | func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 100 | "DeviceInterfaceGUIDs", | ||
| 101 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 102 | )); | ||
| 103 | }); | ||
| 81 | 104 | ||
| 82 | let mut dev = builder.build(); | 105 | let mut dev = builder.build(); |
| 83 | embassy_futures::block_on(dev.run()); | 106 | embassy_futures::block_on(dev.run()); |
diff --git a/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml new file mode 100644 index 000000000..1896068d8 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | runner = "probe-rs run --chip STM32WBA65RI" | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv8m.main-none-eabihf" | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml new file mode 100644 index 000000000..16de7684e --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "stm32wba6-dfu-bootloader-example" | ||
| 4 | version = "0.1.0" | ||
| 5 | description = "Example USB DFUbootloader for the STM32WBA series of chips" | ||
| 6 | license = "MIT OR Apache-2.0" | ||
| 7 | publish = false | ||
| 8 | |||
| 9 | [dependencies] | ||
| 10 | defmt = { version = "1.0.1", optional = true } | ||
| 11 | defmt-rtt = { version = "1.0.0", optional = true } | ||
| 12 | |||
| 13 | embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } | ||
| 14 | embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } | ||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 16 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } | ||
| 17 | cortex-m-rt = { version = "0.7" } | ||
| 18 | embedded-storage = "0.3.1" | ||
| 19 | embedded-storage-async = "0.4.0" | ||
| 20 | cfg-if = "1.0.0" | ||
| 21 | embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } | ||
| 22 | embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } | ||
| 23 | embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } | ||
| 24 | |||
| 25 | [features] | ||
| 26 | defmt = [ | ||
| 27 | "dep:defmt", | ||
| 28 | "dep:defmt-rtt", | ||
| 29 | "embassy-boot-stm32/defmt", | ||
| 30 | "embassy-stm32/defmt", | ||
| 31 | "embassy-usb/defmt", | ||
| 32 | "embassy-usb-dfu/defmt" | ||
| 33 | ] | ||
| 34 | verify = ["embassy-usb-dfu/ed25519-salty"] | ||
| 35 | |||
| 36 | [profile.dev] | ||
| 37 | debug = 2 | ||
| 38 | debug-assertions = true | ||
| 39 | incremental = false | ||
| 40 | opt-level = 'z' | ||
| 41 | overflow-checks = true | ||
| 42 | |||
| 43 | [profile.release] | ||
| 44 | codegen-units = 1 | ||
| 45 | debug = 2 | ||
| 46 | debug-assertions = false | ||
| 47 | incremental = false | ||
| 48 | lto = 'fat' | ||
| 49 | opt-level = 'z' | ||
| 50 | overflow-checks = false | ||
| 51 | |||
| 52 | # do not optimize proc-macro crates = faster builds from scratch | ||
| 53 | [profile.dev.build-override] | ||
| 54 | codegen-units = 8 | ||
| 55 | debug = false | ||
| 56 | debug-assertions = false | ||
| 57 | opt-level = 0 | ||
| 58 | overflow-checks = false | ||
| 59 | |||
| 60 | [profile.release.build-override] | ||
| 61 | codegen-units = 8 | ||
| 62 | debug = false | ||
| 63 | debug-assertions = false | ||
| 64 | opt-level = 0 | ||
| 65 | overflow-checks = false | ||
| 66 | |||
| 67 | [package.metadata.embassy] | ||
| 68 | build = [ | ||
| 69 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-stm32/stm32wba65ri", "verify"] } | ||
| 70 | ] | ||
diff --git a/examples/boot/bootloader/stm32wba-dfu/README.md b/examples/boot/bootloader/stm32wba-dfu/README.md new file mode 100644 index 000000000..d50164255 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/README.md | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | # Bootloader for STM32 | ||
| 2 | |||
| 3 | This bootloader implementation uses `embassy-boot` and `embassy-usb-dfu` to manage firmware updates and interact with the flash memory on STM32WB55 devices. | ||
| 4 | |||
| 5 | ## Prerequisites | ||
| 6 | |||
| 7 | - Rust toolchain with `cargo` installed | ||
| 8 | - `cargo-flash` for flashing the bootloader | ||
| 9 | - `dfu-util` for firmware updates | ||
| 10 | - `cargo-binutils` for binary generation | ||
| 11 | |||
| 12 | ## Usage | ||
| 13 | |||
| 14 | ### 1. Flash the Bootloader | ||
| 15 | |||
| 16 | First, flash the bootloader to your device: | ||
| 17 | |||
| 18 | ``` | ||
| 19 | cargo flash --features embassy-stm32/stm32wba65ri --release --chip STM32WBA65RI | ||
| 20 | ``` | ||
| 21 | |||
| 22 | ### 2. Build and Flash Application | ||
| 23 | |||
| 24 | Generate your application binary and flash it using DFU: | ||
| 25 | |||
| 26 | ``` | ||
| 27 | cargo objcopy --release -- -O binary fw.bin | ||
| 28 | dfu-util -d c0de:cafe -w -D fw.bin | ||
| 29 | ``` | ||
| 30 | |||
| 31 | ### 3. Sign Updates Before Flashing (Optional) | ||
| 32 | |||
| 33 | Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu. | ||
| 34 | |||
| 35 | To sign (and then verify) application updates, you will first need to generate a key pair: | ||
| 36 | |||
| 37 | ``` | ||
| 38 | signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec | ||
| 39 | tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short | ||
| 40 | ``` | ||
| 41 | |||
| 42 | Then you will need to sign all you binaries with the private key: | ||
| 43 | |||
| 44 | ``` | ||
| 45 | cargo objcopy --release -- -O binary fw.bin | ||
| 46 | shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt | ||
| 47 | signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig | ||
| 48 | cp fw.bin fw-signed.bin | ||
| 49 | tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin | ||
| 50 | dfu-util -d c0de:cafe -w -D fw-signed.bin | ||
| 51 | ``` | ||
| 52 | |||
| 53 | Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures. | ||
| 54 | |||
| 55 | N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system. | ||
| 56 | |||
| 57 | ## Troubleshooting | ||
| 58 | |||
| 59 | - Make sure your device is in DFU mode before flashing | ||
| 60 | - Verify the USB VID:PID matches your device (c0de:cafe) | ||
| 61 | - Check USB connections if the device is not detected | ||
| 62 | - Make sure the transfer size option of `dfu-util` matches the bootloader configuration. By default, `dfu-util` will use the transfer size reported by the device, but you can override it with the `-t` option if needed. | ||
| 63 | - Make sure `control_buf` size is larger than or equal to the `usb_dfu` `BLOCK_SIZE` parameter (in this example, both are set to 4096 bytes). | ||
diff --git a/examples/boot/bootloader/stm32wba-dfu/build.rs b/examples/boot/bootloader/stm32wba-dfu/build.rs new file mode 100644 index 000000000..fd605991f --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/build.rs | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | use std::env; | ||
| 2 | use std::fs::File; | ||
| 3 | use std::io::Write; | ||
| 4 | use std::path::PathBuf; | ||
| 5 | |||
| 6 | fn main() { | ||
| 7 | // Put `memory.x` in our output directory and ensure it's | ||
| 8 | // on the linker search path. | ||
| 9 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 10 | File::create(out.join("memory.x")) | ||
| 11 | .unwrap() | ||
| 12 | .write_all(include_bytes!("memory.x")) | ||
| 13 | .unwrap(); | ||
| 14 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 15 | |||
| 16 | // By default, Cargo will re-run a build script whenever | ||
| 17 | // any file in the project changes. By specifying `memory.x` | ||
| 18 | // here, we ensure the build script is only re-run when | ||
| 19 | // `memory.x` is changed. | ||
| 20 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 21 | |||
| 22 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 23 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 24 | if env::var("CARGO_FEATURE_DEFMT").is_ok() { | ||
| 25 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 26 | } | ||
| 27 | } | ||
diff --git a/examples/boot/bootloader/stm32wba-dfu/memory.x b/examples/boot/bootloader/stm32wba-dfu/memory.x new file mode 100644 index 000000000..105c9e960 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/memory.x | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 80K | ||
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K | ||
| 6 | ACTIVE : ORIGIN = 0x08016000, LENGTH = 120K | ||
| 7 | DFU : ORIGIN = 0x0803C000, LENGTH = 160K | ||
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K | ||
| 9 | } | ||
| 10 | |||
| 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(FLASH); | ||
| 12 | __bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(FLASH); | ||
| 13 | |||
| 14 | __bootloader_active_start = ORIGIN(ACTIVE) - ORIGIN(FLASH); | ||
| 15 | __bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE) - ORIGIN(FLASH); | ||
| 16 | |||
| 17 | __bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(FLASH); | ||
| 18 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(FLASH); \ No newline at end of file | ||
diff --git a/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short new file mode 100644 index 000000000..7a4de8585 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short | |||
| @@ -0,0 +1 @@ | |||
| gB��p�M�S��z��Kg��!�F���!4�r \ No newline at end of file | |||
diff --git a/examples/boot/bootloader/stm32wba-dfu/src/main.rs b/examples/boot/bootloader/stm32wba-dfu/src/main.rs new file mode 100644 index 000000000..75d8d4199 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/src/main.rs | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::cell::RefCell; | ||
| 5 | |||
| 6 | use cortex_m_rt::{entry, exception}; | ||
| 7 | #[cfg(feature = "defmt")] | ||
| 8 | use defmt_rtt as _; | ||
| 9 | use embassy_boot_stm32::*; | ||
| 10 | use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; | ||
| 11 | use embassy_stm32::usb::Driver; | ||
| 12 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | ||
| 13 | use embassy_sync::blocking_mutex::Mutex; | ||
| 14 | use embassy_usb::{msos, Builder}; | ||
| 15 | use embassy_usb_dfu::consts::DfuAttributes; | ||
| 16 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | // This is a randomly generated GUID to allow clients on Windows to find your device. | ||
| 23 | // | ||
| 24 | // N.B. update to a custom GUID for your own device! | ||
| 25 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | ||
| 26 | |||
| 27 | // This is a randomly generated example key. | ||
| 28 | // | ||
| 29 | // N.B. Please replace with your own! | ||
| 30 | #[cfg(feature = "verify")] | ||
| 31 | static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short"); | ||
| 32 | |||
| 33 | #[entry] | ||
| 34 | fn main() -> ! { | ||
| 35 | let mut config = Config::default(); | ||
| 36 | |||
| 37 | { | ||
| 38 | use embassy_stm32::rcc::*; | ||
| 39 | config.rcc.pll1 = Some(Pll { | ||
| 40 | source: PllSource::HSI, | ||
| 41 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 42 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 43 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 44 | divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz | ||
| 45 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) | ||
| 46 | frac: Some(0), // Fractional part (disabled) | ||
| 47 | }); | ||
| 48 | |||
| 49 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 50 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 51 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 52 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 53 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 54 | |||
| 55 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 56 | config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; | ||
| 57 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 58 | } | ||
| 59 | |||
| 60 | let p = embassy_stm32::init(config); | ||
| 61 | |||
| 62 | // Prevent a hard fault when accessing flash 'too early' after boot. | ||
| 63 | #[cfg(feature = "defmt")] | ||
| 64 | for _ in 0..10000000 { | ||
| 65 | cortex_m::asm::nop(); | ||
| 66 | } | ||
| 67 | |||
| 68 | let layout = Flash::new_blocking(p.FLASH).into_blocking_regions(); | ||
| 69 | let flash = Mutex::new(RefCell::new(layout.bank1_region)); | ||
| 70 | |||
| 71 | let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash); | ||
| 72 | let active_offset = config.active.offset(); | ||
| 73 | let bl = BootLoader::prepare::<_, _, _, 2048>(config); | ||
| 74 | |||
| 75 | // Create the driver, from the HAL. | ||
| 76 | let mut ep_out_buffer = [0u8; 256]; | ||
| 77 | let mut config = embassy_stm32::usb::Config::default(); | ||
| 78 | |||
| 79 | config.vbus_detection = false; | ||
| 80 | |||
| 81 | if bl.state == State::DfuDetach { | ||
| 82 | let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); | ||
| 83 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); | ||
| 84 | config.manufacturer = Some("Embassy"); | ||
| 85 | config.product = Some("USB-DFU Bootloader example"); | ||
| 86 | config.serial_number = Some("1235678"); | ||
| 87 | |||
| 88 | let fw_config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash); | ||
| 89 | let mut buffer = AlignedBuffer([0; WRITE_SIZE]); | ||
| 90 | let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]); | ||
| 91 | |||
| 92 | let mut config_descriptor = [0; 256]; | ||
| 93 | let mut bos_descriptor = [0; 256]; | ||
| 94 | let mut control_buf = [0; 4096]; | ||
| 95 | |||
| 96 | #[cfg(not(feature = "verify"))] | ||
| 97 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); | ||
| 98 | |||
| 99 | #[cfg(feature = "verify")] | ||
| 100 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY); | ||
| 101 | |||
| 102 | let mut builder = Builder::new( | ||
| 103 | driver, | ||
| 104 | config, | ||
| 105 | &mut config_descriptor, | ||
| 106 | &mut bos_descriptor, | ||
| 107 | &mut [], | ||
| 108 | &mut control_buf, | ||
| 109 | ); | ||
| 110 | |||
| 111 | // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. | ||
| 112 | // Otherwise users need to do this manually using a tool like Zadig. | ||
| 113 | // | ||
| 114 | // It seems these always need to be at added at the device level for this to work and for | ||
| 115 | // composite devices they also need to be added on the function level (as shown later). | ||
| 116 | |||
| 117 | builder.msos_descriptor(msos::windows_version::WIN8_1, 2); | ||
| 118 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 119 | builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 120 | "DeviceInterfaceGUIDs", | ||
| 121 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 122 | )); | ||
| 123 | |||
| 124 | usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| { | ||
| 125 | // You likely don't have to add these function level headers if your USB device is not composite | ||
| 126 | // (i.e. if your device does not expose another interface in addition to DFU) | ||
| 127 | func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 128 | func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 129 | "DeviceInterfaceGUIDs", | ||
| 130 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 131 | )); | ||
| 132 | }); | ||
| 133 | |||
| 134 | let mut dev = builder.build(); | ||
| 135 | embassy_futures::block_on(dev.run()); | ||
| 136 | } | ||
| 137 | |||
| 138 | unsafe { bl.load(BANK1_REGION.base + active_offset) } | ||
| 139 | } | ||
| 140 | |||
| 141 | #[no_mangle] | ||
| 142 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | ||
| 143 | unsafe extern "C" fn HardFault() { | ||
| 144 | cortex_m::peripheral::SCB::sys_reset(); | ||
| 145 | } | ||
| 146 | |||
| 147 | #[exception] | ||
| 148 | unsafe fn DefaultHandler(_: i16) -> ! { | ||
| 149 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | ||
| 150 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | ||
| 151 | |||
| 152 | panic!("DefaultHandler #{:?}", irqn); | ||
| 153 | } | ||
| 154 | |||
| 155 | #[panic_handler] | ||
| 156 | fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
| 157 | cortex_m::asm::udf(); | ||
| 158 | } | ||
diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index f5a6e6995..579748595 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml | |||
| @@ -4,19 +4,25 @@ name = "embassy-nxp-lpc55s69-examples" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] } | 10 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55-core0", "rt", "defmt", "time-driver-rtc"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 11 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } |
| 13 | panic-halt = "0.2.0" | 14 | panic-halt = "1.0.0" |
| 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 15 | cortex-m-rt = { version = "0.7.0"} | 16 | cortex-m-rt = { version = "0.7.0"} |
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 19 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 19 | panic-semihosting = "0.6.0" | 20 | panic-semihosting = "0.6.0" |
| 20 | 21 | ||
| 21 | [profile.release] | 22 | [profile.release] |
| 22 | debug = 2 | 23 | debug = 2 |
| 24 | |||
| 25 | [package.metadata.embassy] | ||
| 26 | build = [ | ||
| 27 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/lpc55s69" } | ||
| 28 | ] | ||
diff --git a/examples/lpc55s69/README.md b/examples/lpc55s69/README.md new file mode 100644 index 000000000..d200f4f99 --- /dev/null +++ b/examples/lpc55s69/README.md | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # LPC55S69 Examples | ||
| 2 | |||
| 3 | ## Available examples: | ||
| 4 | - blinky_nop: Blink the integrated RED LED using nops as delay. Useful for flashing simple and known-good software on board. | ||
| 5 | - button_executor: Turn on/off an LED by pressing the USER button. Demonstrates how to use the PINT and GPIO drivers. | ||
| 6 | - blinky_embassy_time: Blink the integrated RED LED using `embassy-time`. Demonstrates how to use the time-driver that uses RTC. | ||
| 7 | |||
| 8 | ## Important Notes | ||
| 9 | |||
| 10 | On older version of probe-rs, some examples (such as `blinky_embassy_time`) do not work directly after flashing and the board must be reset after flashing. It is reccomended to update the version of probe-rs to the latest one. | ||
| 11 | |||
| 12 | When developing drivers for this board, probe-rs might not be able to flash the board after entering a fault. Either reset the board to clear the fault, or use NXP's proprietary software `LinkServer`/`LinkFlash` to bring the board back to a known-good state. \ No newline at end of file | ||
diff --git a/examples/lpc55s69/src/bin/blinky_embassy_time.rs b/examples/lpc55s69/src/bin/blinky_embassy_time.rs new file mode 100644 index 000000000..adc3d8bd3 --- /dev/null +++ b/examples/lpc55s69/src/bin/blinky_embassy_time.rs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nxp::gpio::{Level, Output}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nxp::init(Default::default()); | ||
| 13 | info!("Initialization complete"); | ||
| 14 | let mut led = Output::new(p.PIO1_6, Level::Low); | ||
| 15 | |||
| 16 | info!("Entering main loop"); | ||
| 17 | loop { | ||
| 18 | info!("led off!"); | ||
| 19 | led.set_high(); | ||
| 20 | Timer::after_millis(500).await; | ||
| 21 | |||
| 22 | info!("led on!"); | ||
| 23 | led.set_low(); | ||
| 24 | Timer::after_millis(500).await; | ||
| 25 | } | ||
| 26 | } | ||
diff --git a/examples/lpc55s69/src/bin/usart_blocking.rs b/examples/lpc55s69/src/bin/usart_blocking.rs new file mode 100644 index 000000000..a38ec0c5b --- /dev/null +++ b/examples/lpc55s69/src/bin/usart_blocking.rs | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::str::from_utf8_mut; | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_nxp::usart::{Config, Usart}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_halt as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let p = embassy_nxp::init(Default::default()); | ||
| 15 | let mut usart = Usart::new_blocking(p.USART2, p.PIO0_27, p.PIO1_24, Config::default()); | ||
| 16 | let tx_buf = b"Hello, Ferris!"; | ||
| 17 | let mut rx_buf = [0u8; 14]; | ||
| 18 | |||
| 19 | loop { | ||
| 20 | info!("Write a message"); | ||
| 21 | usart.blocking_write(tx_buf).unwrap(); | ||
| 22 | usart.blocking_flush().unwrap(); | ||
| 23 | |||
| 24 | Timer::after_millis(500).await; | ||
| 25 | |||
| 26 | info!("Read a message"); | ||
| 27 | usart.blocking_read(&mut rx_buf).unwrap(); | ||
| 28 | |||
| 29 | match from_utf8_mut(&mut rx_buf) { | ||
| 30 | Ok(str) => { | ||
| 31 | info!("The message is: {}", str); | ||
| 32 | } | ||
| 33 | Err(_) => { | ||
| 34 | error!("Error in converting to UTF8"); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | Timer::after_millis(500).await; | ||
| 39 | } | ||
| 40 | } | ||
diff --git a/examples/mimxrt1011/.cargo/config.toml b/examples/mimxrt1011/.cargo/config.toml new file mode 100644 index 000000000..12f4b27b2 --- /dev/null +++ b/examples/mimxrt1011/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv7em-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip MIMXRT1010' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv7em-none-eabihf" # Cortex-M7 | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml new file mode 100644 index 000000000..488f3167b --- /dev/null +++ b/examples/mimxrt1011/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-imxrt1011-examples" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | license = "MIT or Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } | ||
| 10 | cortex-m-rt = "0.7.3" | ||
| 11 | defmt = "1.0.1" | ||
| 12 | defmt-rtt = "1.0.0" | ||
| 13 | |||
| 14 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | ||
| 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 16 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] } | ||
| 17 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. | ||
| 18 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 20 | embedded-hal-async = "1.0.0" | ||
| 21 | |||
| 22 | imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1010"] } | ||
| 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 24 | panic-semihosting = "0.6.0" | ||
| 25 | |||
| 26 | [build-dependencies] | ||
| 27 | imxrt-rt = { version = "0.1.7", features = ["device"] } | ||
| 28 | |||
| 29 | [profile.release] | ||
| 30 | debug = 2 | ||
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1011" } | ||
| 35 | ] | ||
diff --git a/examples/mimxrt1011/build.rs b/examples/mimxrt1011/build.rs new file mode 100644 index 000000000..99e172aba --- /dev/null +++ b/examples/mimxrt1011/build.rs | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | use imxrt_rt::{Family, RuntimeBuilder}; | ||
| 2 | |||
| 3 | fn main() { | ||
| 4 | // The IMXRT1010-EVK technically has 128M of flash, but we only ever use 8MB so that the examples | ||
| 5 | // will build fine on the Adafruit Metro M7 boards. | ||
| 6 | RuntimeBuilder::from_flexspi(Family::Imxrt1010, 8 * 1024 * 1024) | ||
| 7 | .build() | ||
| 8 | .unwrap(); | ||
| 9 | |||
| 10 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 11 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 12 | // Not link.x, as imxrt-rt needs to do some special things | ||
| 13 | println!("cargo:rustc-link-arg-bins=-Timxrt-link.x"); | ||
| 14 | } | ||
diff --git a/examples/mimxrt1011/src/bin/blinky.rs b/examples/mimxrt1011/src/bin/blinky.rs new file mode 100644 index 000000000..a5d5de6b3 --- /dev/null +++ b/examples/mimxrt1011/src/bin/blinky.rs | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | //! This example works on the following boards: | ||
| 2 | //! - IMXRT1010-EVK | ||
| 3 | //! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button | ||
| 4 | //! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this) | ||
| 5 | //! | ||
| 6 | //! Although beware you will need to change the GPIO pins being used (scroll down). | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use defmt::info; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_nxp::gpio::{Level, Output}; | ||
| 14 | use embassy_time::Timer; | ||
| 15 | // Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked. | ||
| 16 | use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _}; | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) -> ! { | ||
| 20 | let p = embassy_nxp::init(Default::default()); | ||
| 21 | info!("Hello world!"); | ||
| 22 | |||
| 23 | /* Pick the pins to use depending on your board. */ | ||
| 24 | |||
| 25 | // IMXRT1010-EVK | ||
| 26 | // | ||
| 27 | // LED (D25) | ||
| 28 | let led = p.GPIO_11; | ||
| 29 | |||
| 30 | // Adafruit Metro M7 (both microSD and AirLift variants) | ||
| 31 | // | ||
| 32 | // The LED is connected to D13 on the board. | ||
| 33 | // let led = p.GPIO_03; | ||
| 34 | |||
| 35 | // Makerdiary iMX RT1011 Nano Kit | ||
| 36 | // | ||
| 37 | // LED0 | ||
| 38 | // let led = p.GPIO_SD_04; | ||
| 39 | |||
| 40 | let mut led = Output::new(led, Level::Low); | ||
| 41 | |||
| 42 | loop { | ||
| 43 | Timer::after_millis(500).await; | ||
| 44 | |||
| 45 | info!("Toggle"); | ||
| 46 | led.toggle(); | ||
| 47 | } | ||
| 48 | } | ||
diff --git a/examples/mimxrt1011/src/bin/button.rs b/examples/mimxrt1011/src/bin/button.rs new file mode 100644 index 000000000..e63d7171d --- /dev/null +++ b/examples/mimxrt1011/src/bin/button.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | //! This example works on the following boards: | ||
| 2 | //! - IMXRT1010-EVK | ||
| 3 | //! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button | ||
| 4 | //! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this) | ||
| 5 | //! | ||
| 6 | //! Although beware you will need to change the GPIO pins being used (scroll down). | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use defmt::info; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_nxp::gpio::{Input, Level, Output, Pull}; | ||
| 14 | // Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked. | ||
| 15 | use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _}; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) -> ! { | ||
| 19 | let p = embassy_nxp::init(Default::default()); | ||
| 20 | info!("Hello world!"); | ||
| 21 | |||
| 22 | /* Pick the pins to use depending on your board. */ | ||
| 23 | |||
| 24 | // IMXRT1010-EVK | ||
| 25 | // | ||
| 26 | // LED (D25) and user button (SW4) | ||
| 27 | let (led, button) = (p.GPIO_11, p.GPIO_SD_05); | ||
| 28 | |||
| 29 | // Adafruit Metro M7 (both microSD and AirLift variants) | ||
| 30 | // | ||
| 31 | // The LED is connected to D13 on the board. | ||
| 32 | // | ||
| 33 | // In particular the Metro M7 has no board user buttons, so you will need to connect a button. | ||
| 34 | // Any other GPIO pin can be used. GPIO_04 is used for example since it is on pin D12. | ||
| 35 | // let (led, button) = (p.GPIO_03, p.GPIO_04); | ||
| 36 | |||
| 37 | // Makerdiary iMX RT1011 Nano Kit | ||
| 38 | // | ||
| 39 | // LED0 and user button. | ||
| 40 | // let (led, button) = (p.GPIO_SD_04, p.GPIO_SD_03); | ||
| 41 | |||
| 42 | let mut button = Input::new(button, Pull::Up100K); | ||
| 43 | let mut led = Output::new(led, Level::Low); | ||
| 44 | led.set_high(); | ||
| 45 | |||
| 46 | loop { | ||
| 47 | button.wait_for_falling_edge().await; | ||
| 48 | |||
| 49 | info!("Toggled"); | ||
| 50 | led.toggle(); | ||
| 51 | |||
| 52 | // The RT1010EVK has a 100 nF debouncing capacitor which results in false positive events | ||
| 53 | // when listening for a falling edge in a loop, wait for the rising edge and then wait for | ||
| 54 | // stabilization. | ||
| 55 | button.wait_for_rising_edge().await; | ||
| 56 | |||
| 57 | // Stabilization. | ||
| 58 | for _ in 0..100_000 { | ||
| 59 | cortex_m::asm::nop(); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/mimxrt1011/src/lib.rs b/examples/mimxrt1011/src/lib.rs new file mode 100644 index 000000000..f0391ef57 --- /dev/null +++ b/examples/mimxrt1011/src/lib.rs | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | //! FlexSPI configuration block (FCB) for iMXRT1011 boards. | ||
| 2 | //! | ||
| 3 | //! This is a generic FCB that should work with most QSPI flash. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | |||
| 7 | use imxrt_boot_gen::flexspi; | ||
| 8 | use imxrt_boot_gen::flexspi::opcodes::sdr::*; | ||
| 9 | use imxrt_boot_gen::flexspi::{ | ||
| 10 | ColumnAddressWidth, Command, DeviceModeConfiguration, FlashPadType, Instr, LookupTable, Pads, | ||
| 11 | ReadSampleClockSource, Sequence, SequenceBuilder, SerialClockFrequency, SerialFlashRegion, | ||
| 12 | WaitTimeConfigurationCommands, | ||
| 13 | }; | ||
| 14 | use imxrt_boot_gen::serial_flash::nor; | ||
| 15 | |||
| 16 | /// While the IMXRT1010-EVK and Makerdiary iMX RT1011 Nano Kit have 128MBit of flash we limit to 64Mbit | ||
| 17 | /// to allow the Metro M7 boards to use the same FCB configuration. | ||
| 18 | const DENSITY_BITS: u32 = 64 * 1024 * 1024; | ||
| 19 | const DENSITY_BYTES: u32 = DENSITY_BITS / 8; | ||
| 20 | |||
| 21 | const SEQ_READ: Sequence = SequenceBuilder::new() | ||
| 22 | .instr(Instr::new(CMD, Pads::One, 0xEB)) | ||
| 23 | .instr(Instr::new(RADDR, Pads::Four, 0x18)) | ||
| 24 | .instr(Instr::new(DUMMY, Pads::Four, 0x06)) | ||
| 25 | .instr(Instr::new(READ, Pads::Four, 0x04)) | ||
| 26 | .build(); | ||
| 27 | |||
| 28 | const SEQ_READ_STATUS: Sequence = SequenceBuilder::new() | ||
| 29 | .instr(Instr::new(CMD, Pads::One, 0x05)) | ||
| 30 | .instr(Instr::new(READ, Pads::One, 0x01)) | ||
| 31 | .build(); | ||
| 32 | |||
| 33 | const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build(); | ||
| 34 | |||
| 35 | const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new() | ||
| 36 | .instr(Instr::new(CMD, Pads::One, 0x20)) | ||
| 37 | .instr(Instr::new(RADDR, Pads::One, 0x18)) | ||
| 38 | .build(); | ||
| 39 | |||
| 40 | const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new() | ||
| 41 | .instr(Instr::new(CMD, Pads::One, 0x02)) | ||
| 42 | .instr(Instr::new(RADDR, Pads::One, 0x18)) | ||
| 43 | .instr(Instr::new(WRITE, Pads::One, 0x04)) | ||
| 44 | .build(); | ||
| 45 | |||
| 46 | const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build(); | ||
| 47 | |||
| 48 | const LUT: LookupTable = LookupTable::new() | ||
| 49 | .command(Command::Read, SEQ_READ) | ||
| 50 | .command(Command::ReadStatus, SEQ_READ_STATUS) | ||
| 51 | .command(Command::WriteEnable, SEQ_WRITE_ENABLE) | ||
| 52 | .command(Command::EraseSector, SEQ_ERASE_SECTOR) | ||
| 53 | .command(Command::PageProgram, SEQ_PAGE_PROGRAM) | ||
| 54 | .command(Command::ChipErase, SEQ_CHIP_ERASE); | ||
| 55 | |||
| 56 | const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT) | ||
| 57 | .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad) | ||
| 58 | .cs_hold_time(0x03) | ||
| 59 | .cs_setup_time(0x03) | ||
| 60 | .column_address_width(ColumnAddressWidth::OtherDevices) | ||
| 61 | .device_mode_configuration(DeviceModeConfiguration::Disabled) | ||
| 62 | .wait_time_cfg_commands(WaitTimeConfigurationCommands::disable()) | ||
| 63 | .flash_size(SerialFlashRegion::A1, DENSITY_BYTES) | ||
| 64 | .serial_clk_freq(SerialClockFrequency::MHz120) | ||
| 65 | .serial_flash_pad_type(FlashPadType::Quad); | ||
| 66 | |||
| 67 | pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = | ||
| 68 | nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK) | ||
| 69 | .page_size(256) | ||
| 70 | .sector_size(4096) | ||
| 71 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); | ||
| 72 | |||
| 73 | #[unsafe(no_mangle)] | ||
| 74 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] | ||
| 75 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; | ||
diff --git a/examples/mimxrt1062-evk/.cargo/config.toml b/examples/mimxrt1062-evk/.cargo/config.toml new file mode 100644 index 000000000..ca4c606dc --- /dev/null +++ b/examples/mimxrt1062-evk/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv7em-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip MIMXRT1060' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv7em-none-eabihf" # Cortex-M7 | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml new file mode 100644 index 000000000..ec6c5c872 --- /dev/null +++ b/examples/mimxrt1062-evk/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-imxrt1062-evk-examples" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | license = "MIT or Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } | ||
| 10 | cortex-m-rt = "0.7.3" | ||
| 11 | defmt = "1.0.1" | ||
| 12 | defmt-rtt = "1.0.0" | ||
| 13 | |||
| 14 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | ||
| 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 16 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] } | ||
| 17 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" | ||
| 18 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 20 | embedded-hal-async = "1.0.0" | ||
| 21 | |||
| 22 | imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1060"] } | ||
| 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 24 | panic-semihosting = "0.6.0" | ||
| 25 | |||
| 26 | [build-dependencies] | ||
| 27 | imxrt-rt = { version = "0.1.7", features = ["device"] } | ||
| 28 | |||
| 29 | [profile.release] | ||
| 30 | debug = 2 | ||
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1062-evk" } | ||
| 35 | ] | ||
diff --git a/examples/mimxrt1062-evk/build.rs b/examples/mimxrt1062-evk/build.rs new file mode 100644 index 000000000..e0e0d547e --- /dev/null +++ b/examples/mimxrt1062-evk/build.rs | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | use imxrt_rt::{Family, RuntimeBuilder}; | ||
| 2 | |||
| 3 | fn main() { | ||
| 4 | RuntimeBuilder::from_flexspi(Family::Imxrt1060, 8 * 1024 * 1024) | ||
| 5 | .build() | ||
| 6 | .unwrap(); | ||
| 7 | |||
| 8 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 9 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 10 | // Not link.x, as imxrt-rt needs to do some special things | ||
| 11 | println!("cargo:rustc-link-arg-bins=-Timxrt-link.x"); | ||
| 12 | } | ||
diff --git a/examples/mimxrt1062-evk/src/bin/blinky.rs b/examples/mimxrt1062-evk/src/bin/blinky.rs new file mode 100644 index 000000000..b6d90d94d --- /dev/null +++ b/examples/mimxrt1062-evk/src/bin/blinky.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nxp::gpio::{Level, Output}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | // Must include `embassy_imxrt1062_evk_examples` to ensure the FCB gets linked. | ||
| 9 | use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) -> ! { | ||
| 13 | let p = embassy_nxp::init(Default::default()); | ||
| 14 | info!("Hello world!"); | ||
| 15 | |||
| 16 | let led = p.GPIO_AD_B0_08; | ||
| 17 | let mut led = Output::new(led, Level::Low); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | Timer::after_millis(500).await; | ||
| 21 | |||
| 22 | info!("Toggle"); | ||
| 23 | led.toggle(); | ||
| 24 | } | ||
| 25 | } | ||
diff --git a/examples/mimxrt1062-evk/src/bin/button.rs b/examples/mimxrt1062-evk/src/bin/button.rs new file mode 100644 index 000000000..d60fa3dac --- /dev/null +++ b/examples/mimxrt1062-evk/src/bin/button.rs | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nxp::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) -> ! { | ||
| 11 | let p = embassy_nxp::init(Default::default()); | ||
| 12 | info!("Hello world!"); | ||
| 13 | |||
| 14 | // User LED (D8) | ||
| 15 | let led = p.GPIO_AD_B0_08; | ||
| 16 | // User button (SW5) | ||
| 17 | let button = p.WAKEUP; | ||
| 18 | let mut button = Input::new(button, Pull::Up100K); | ||
| 19 | let mut led = Output::new(led, Level::Low); | ||
| 20 | led.set_high(); | ||
| 21 | |||
| 22 | loop { | ||
| 23 | button.wait_for_falling_edge().await; | ||
| 24 | |||
| 25 | info!("Toggled"); | ||
| 26 | led.toggle(); | ||
| 27 | |||
| 28 | // Software debounce. | ||
| 29 | button.wait_for_rising_edge().await; | ||
| 30 | |||
| 31 | // Stabilization. | ||
| 32 | for _ in 0..100_000 { | ||
| 33 | cortex_m::asm::nop(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
diff --git a/examples/mimxrt1062-evk/src/lib.rs b/examples/mimxrt1062-evk/src/lib.rs new file mode 100644 index 000000000..3f99f9db3 --- /dev/null +++ b/examples/mimxrt1062-evk/src/lib.rs | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | //! FlexSPI configuration block (FCB) for the iMXRT1060-EVK | ||
| 2 | //! | ||
| 3 | //! This uses IS25WP QuadSPI flash. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | |||
| 7 | use imxrt_boot_gen::flexspi::opcodes::sdr::*; | ||
| 8 | use imxrt_boot_gen::flexspi::{self, FlashPadType, ReadSampleClockSource, SerialClockFrequency, SerialFlashRegion, *}; | ||
| 9 | use imxrt_boot_gen::serial_flash::*; | ||
| 10 | pub use nor::ConfigurationBlock; | ||
| 11 | |||
| 12 | const SEQ_READ: Sequence = SequenceBuilder::new() | ||
| 13 | .instr(Instr::new(CMD, Pads::One, 0xEB)) | ||
| 14 | .instr(Instr::new(RADDR, Pads::Four, 0x18)) | ||
| 15 | .instr(Instr::new(DUMMY, Pads::Four, 0x06)) | ||
| 16 | .instr(Instr::new(READ, Pads::Four, 0x04)) | ||
| 17 | .build(); | ||
| 18 | const SEQ_READ_STATUS: Sequence = SequenceBuilder::new() | ||
| 19 | .instr(Instr::new(CMD, Pads::One, 0x05)) | ||
| 20 | .instr(Instr::new(READ, Pads::One, 0x04)) | ||
| 21 | .build(); | ||
| 22 | const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build(); | ||
| 23 | const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new() | ||
| 24 | .instr(Instr::new(CMD, Pads::One, 0x20)) | ||
| 25 | .instr(Instr::new(RADDR, Pads::One, 0x18)) | ||
| 26 | .build(); | ||
| 27 | const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new() | ||
| 28 | .instr(Instr::new(CMD, Pads::One, 0x02)) | ||
| 29 | .instr(Instr::new(RADDR, Pads::One, 0x18)) | ||
| 30 | .instr(Instr::new(WRITE, Pads::One, 0x04)) | ||
| 31 | .build(); | ||
| 32 | const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build(); | ||
| 33 | |||
| 34 | const LUT: LookupTable = LookupTable::new() | ||
| 35 | .command(Command::Read, SEQ_READ) | ||
| 36 | .command(Command::ReadStatus, SEQ_READ_STATUS) | ||
| 37 | .command(Command::WriteEnable, SEQ_WRITE_ENABLE) | ||
| 38 | .command(Command::EraseSector, SEQ_ERASE_SECTOR) | ||
| 39 | .command(Command::PageProgram, SEQ_PAGE_PROGRAM) | ||
| 40 | .command(Command::ChipErase, SEQ_CHIP_ERASE); | ||
| 41 | |||
| 42 | const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT) | ||
| 43 | .version(Version::new(1, 4, 0)) | ||
| 44 | .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad) | ||
| 45 | .cs_hold_time(3) | ||
| 46 | .cs_setup_time(3) | ||
| 47 | .controller_misc_options(0x10) | ||
| 48 | .serial_flash_pad_type(FlashPadType::Quad) | ||
| 49 | .serial_clk_freq(SerialClockFrequency::MHz133) | ||
| 50 | .flash_size(SerialFlashRegion::A1, 8 * 1024 * 1024); | ||
| 51 | |||
| 52 | pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = | ||
| 53 | nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK) | ||
| 54 | .page_size(256) | ||
| 55 | .sector_size(4096) | ||
| 56 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); | ||
| 57 | |||
| 58 | #[no_mangle] | ||
| 59 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] | ||
| 60 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; | ||
diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index b0c56f003..28de9d273 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml | |||
| @@ -3,24 +3,24 @@ name = "embassy-imxrt-examples" | |||
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | license = "MIT or Apache-2.0" | 5 | license = "MIT or Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } | 9 | cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } |
| 9 | cortex-m-rt = "0.7.3" | 10 | cortex-m-rt = "0.7.3" |
| 10 | defmt = "1.0" | 11 | defmt = "1.0.1" |
| 11 | defmt-rtt = "1.0" | 12 | defmt-rtt = "1.0.0" |
| 12 | 13 | ||
| 13 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 14 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 14 | embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } | 16 | embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } |
| 16 | embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 17 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 17 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 18 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 18 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 19 | embedded-hal-async = "1.0.0" | 20 | embedded-hal-async = "1.0.0" |
| 20 | 21 | ||
| 21 | mimxrt600-fcb = "0.2.2" | 22 | mimxrt600-fcb = "0.2.2" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | rand = { version = "0.8.5", default-features = false } | ||
| 24 | 24 | ||
| 25 | # cargo build/run | 25 | # cargo build/run |
| 26 | [profile.dev] | 26 | [profile.dev] |
| @@ -59,3 +59,8 @@ incremental = false | |||
| 59 | lto = 'fat' | 59 | lto = 'fat' |
| 60 | opt-level = 3 # <- | 60 | opt-level = 3 # <- |
| 61 | overflow-checks = false # <- | 61 | overflow-checks = false # <- |
| 62 | |||
| 63 | [package.metadata.embassy] | ||
| 64 | build = [ | ||
| 65 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/mimxrt6" } | ||
| 66 | ] | ||
diff --git a/examples/mimxrt6/src/bin/button.rs b/examples/mimxrt6/src/bin/button.rs new file mode 100644 index 000000000..efb7f14af --- /dev/null +++ b/examples/mimxrt6/src/bin/button.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_futures::select::{select, Either}; | ||
| 7 | use embassy_imxrt::gpio; | ||
| 8 | use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_imxrt::init(Default::default()); | ||
| 13 | |||
| 14 | let mut user1 = gpio::Input::new(p.PIO1_1, gpio::Pull::None, gpio::Inverter::Disabled); | ||
| 15 | let mut user2 = gpio::Input::new(p.PIO0_10, gpio::Pull::None, gpio::Inverter::Disabled); | ||
| 16 | |||
| 17 | loop { | ||
| 18 | let res = select(user1.wait_for_falling_edge(), user2.wait_for_falling_edge()).await; | ||
| 19 | |||
| 20 | match res { | ||
| 21 | Either::First(()) => { | ||
| 22 | info!("Button `USER1' pressed"); | ||
| 23 | } | ||
| 24 | Either::Second(()) => { | ||
| 25 | info!("Button `USER2' pressed"); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/examples/mimxrt6/src/bin/crc.rs b/examples/mimxrt6/src/bin/crc.rs new file mode 100644 index 000000000..005a250e5 --- /dev/null +++ b/examples/mimxrt6/src/bin/crc.rs | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | extern crate embassy_imxrt_examples; | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_imxrt::crc::{Config, Crc, Polynomial}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) { | ||
| 13 | let mut p = embassy_imxrt::init(Default::default()); | ||
| 14 | let data = b"123456789"; | ||
| 15 | |||
| 16 | info!("Initializing CRC"); | ||
| 17 | |||
| 18 | // CRC-CCITT | ||
| 19 | let mut crc = Crc::new(p.CRC.reborrow(), Default::default()); | ||
| 20 | let output = crc.feed_bytes(data); | ||
| 21 | defmt::assert_eq!(output, 0x29b1); | ||
| 22 | |||
| 23 | // CRC16-ARC | ||
| 24 | let mut crc = Crc::new( | ||
| 25 | p.CRC.reborrow(), | ||
| 26 | Config { | ||
| 27 | polynomial: Polynomial::Crc16, | ||
| 28 | reverse_in: true, | ||
| 29 | reverse_out: true, | ||
| 30 | complement_out: false, | ||
| 31 | seed: 0, | ||
| 32 | ..Default::default() | ||
| 33 | }, | ||
| 34 | ); | ||
| 35 | let output = crc.feed_bytes(data); | ||
| 36 | defmt::assert_eq!(output, 0xbb3d); | ||
| 37 | |||
| 38 | // CRC16-CMS | ||
| 39 | let mut crc = Crc::new( | ||
| 40 | p.CRC.reborrow(), | ||
| 41 | Config { | ||
| 42 | polynomial: Polynomial::Crc16, | ||
| 43 | reverse_in: false, | ||
| 44 | reverse_out: false, | ||
| 45 | complement_out: false, | ||
| 46 | seed: 0xffff, | ||
| 47 | ..Default::default() | ||
| 48 | }, | ||
| 49 | ); | ||
| 50 | let output = crc.feed_bytes(data); | ||
| 51 | defmt::assert_eq!(output, 0xaee7); | ||
| 52 | |||
| 53 | // CRC16-DDS-110 | ||
| 54 | let mut crc = Crc::new( | ||
| 55 | p.CRC.reborrow(), | ||
| 56 | Config { | ||
| 57 | polynomial: Polynomial::Crc16, | ||
| 58 | reverse_in: false, | ||
| 59 | reverse_out: false, | ||
| 60 | complement_out: false, | ||
| 61 | seed: 0x800d, | ||
| 62 | ..Default::default() | ||
| 63 | }, | ||
| 64 | ); | ||
| 65 | let output = crc.feed_bytes(data); | ||
| 66 | defmt::assert_eq!(output, 0x9ecf); | ||
| 67 | |||
| 68 | // CRC16-MAXIM-DOW | ||
| 69 | let mut crc = Crc::new( | ||
| 70 | p.CRC.reborrow(), | ||
| 71 | Config { | ||
| 72 | polynomial: Polynomial::Crc16, | ||
| 73 | reverse_in: true, | ||
| 74 | reverse_out: true, | ||
| 75 | complement_out: true, | ||
| 76 | seed: 0, | ||
| 77 | ..Default::default() | ||
| 78 | }, | ||
| 79 | ); | ||
| 80 | let output = crc.feed_bytes(data); | ||
| 81 | defmt::assert_eq!(output, 0x44c2); | ||
| 82 | |||
| 83 | // CRC16-MODBUS | ||
| 84 | let mut crc = Crc::new( | ||
| 85 | p.CRC.reborrow(), | ||
| 86 | Config { | ||
| 87 | polynomial: Polynomial::Crc16, | ||
| 88 | reverse_in: true, | ||
| 89 | reverse_out: true, | ||
| 90 | complement_out: false, | ||
| 91 | seed: 0xffff, | ||
| 92 | ..Default::default() | ||
| 93 | }, | ||
| 94 | ); | ||
| 95 | let output = crc.feed_bytes(data); | ||
| 96 | defmt::assert_eq!(output, 0x4b37); | ||
| 97 | |||
| 98 | // CRC32-BZIP2 | ||
| 99 | let mut crc = Crc::new( | ||
| 100 | p.CRC.reborrow(), | ||
| 101 | Config { | ||
| 102 | polynomial: Polynomial::Crc32, | ||
| 103 | reverse_in: false, | ||
| 104 | reverse_out: false, | ||
| 105 | complement_out: true, | ||
| 106 | seed: 0xffff_ffff, | ||
| 107 | ..Default::default() | ||
| 108 | }, | ||
| 109 | ); | ||
| 110 | let output = crc.feed_bytes(data); | ||
| 111 | defmt::assert_eq!(output, 0xfc89_1918); | ||
| 112 | |||
| 113 | // CRC32-CKSUM | ||
| 114 | let mut crc = Crc::new( | ||
| 115 | p.CRC.reborrow(), | ||
| 116 | Config { | ||
| 117 | polynomial: Polynomial::Crc32, | ||
| 118 | reverse_in: false, | ||
| 119 | reverse_out: false, | ||
| 120 | complement_out: true, | ||
| 121 | seed: 0, | ||
| 122 | ..Default::default() | ||
| 123 | }, | ||
| 124 | ); | ||
| 125 | let output = crc.feed_bytes(data); | ||
| 126 | defmt::assert_eq!(output, 0x765e_7680); | ||
| 127 | |||
| 128 | // CRC32-ISO-HDLC | ||
| 129 | let mut crc = Crc::new( | ||
| 130 | p.CRC.reborrow(), | ||
| 131 | Config { | ||
| 132 | polynomial: Polynomial::Crc32, | ||
| 133 | reverse_in: true, | ||
| 134 | reverse_out: true, | ||
| 135 | complement_out: true, | ||
| 136 | seed: 0xffff_ffff, | ||
| 137 | ..Default::default() | ||
| 138 | }, | ||
| 139 | ); | ||
| 140 | let output = crc.feed_bytes(data); | ||
| 141 | defmt::assert_eq!(output, 0xcbf4_3926); | ||
| 142 | |||
| 143 | // CRC32-JAMCRC | ||
| 144 | let mut crc = Crc::new( | ||
| 145 | p.CRC.reborrow(), | ||
| 146 | Config { | ||
| 147 | polynomial: Polynomial::Crc32, | ||
| 148 | reverse_in: true, | ||
| 149 | reverse_out: true, | ||
| 150 | complement_out: false, | ||
| 151 | seed: 0xffff_ffff, | ||
| 152 | ..Default::default() | ||
| 153 | }, | ||
| 154 | ); | ||
| 155 | let output = crc.feed_bytes(data); | ||
| 156 | defmt::assert_eq!(output, 0x340b_c6d9); | ||
| 157 | |||
| 158 | // CRC32-MPEG-2 | ||
| 159 | let mut crc = Crc::new( | ||
| 160 | p.CRC.reborrow(), | ||
| 161 | Config { | ||
| 162 | polynomial: Polynomial::Crc32, | ||
| 163 | reverse_in: false, | ||
| 164 | reverse_out: false, | ||
| 165 | complement_out: false, | ||
| 166 | seed: 0xffff_ffff, | ||
| 167 | ..Default::default() | ||
| 168 | }, | ||
| 169 | ); | ||
| 170 | let output = crc.feed_bytes(data); | ||
| 171 | defmt::assert_eq!(output, 0x0376_e6e7); | ||
| 172 | |||
| 173 | info!("end program"); | ||
| 174 | cortex_m::asm::bkpt(); | ||
| 175 | } | ||
diff --git a/examples/mimxrt6/src/bin/rng.rs b/examples/mimxrt6/src/bin/rng.rs new file mode 100644 index 000000000..9468dd109 --- /dev/null +++ b/examples/mimxrt6/src/bin/rng.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | extern crate embassy_imxrt_examples; | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_imxrt::rng::Rng; | ||
| 9 | use embassy_imxrt::{bind_interrupts, peripherals, rng}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let p = embassy_imxrt::init(Default::default()); | ||
| 19 | |||
| 20 | info!("Initializing RNG"); | ||
| 21 | let mut rng = Rng::new(p.RNG, Irqs); | ||
| 22 | let mut buf = [0u8; 65]; | ||
| 23 | |||
| 24 | // Async interface | ||
| 25 | unwrap!(rng.async_fill_bytes(&mut buf).await); | ||
| 26 | info!("random bytes: {:02x}", buf); | ||
| 27 | |||
| 28 | // RngCore interface | ||
| 29 | let mut random_bytes = [0; 16]; | ||
| 30 | |||
| 31 | let random_u32 = rng.blocking_next_u32(); | ||
| 32 | let random_u64 = rng.blocking_next_u64(); | ||
| 33 | |||
| 34 | rng.blocking_fill_bytes(&mut random_bytes); | ||
| 35 | |||
| 36 | info!("random_u32 {}", random_u32); | ||
| 37 | info!("random_u64 {}", random_u64); | ||
| 38 | info!("random_bytes {}", random_bytes); | ||
| 39 | } | ||
diff --git a/examples/mimxrt6/src/bin/uart-async.rs b/examples/mimxrt6/src/bin/uart-async.rs new file mode 100644 index 000000000..d808d755c --- /dev/null +++ b/examples/mimxrt6/src/bin/uart-async.rs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | extern crate embassy_imxrt_examples; | ||
| 5 | |||
| 6 | use defmt::info; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_imxrt::flexcomm::uart::{self, Async, Uart}; | ||
| 9 | use embassy_imxrt::{bind_interrupts, peripherals}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | FLEXCOMM2 => uart::InterruptHandler<peripherals::FLEXCOMM2>; | ||
| 15 | FLEXCOMM4 => uart::InterruptHandler<peripherals::FLEXCOMM4>; | ||
| 16 | }); | ||
| 17 | |||
| 18 | const BUFLEN: usize = 16; | ||
| 19 | |||
| 20 | #[embassy_executor::task] | ||
| 21 | async fn usart4_task(mut uart: Uart<'static, Async>) { | ||
| 22 | info!("RX Task"); | ||
| 23 | |||
| 24 | loop { | ||
| 25 | let mut rx_buf = [0; BUFLEN]; | ||
| 26 | uart.read(&mut rx_buf).await.unwrap(); | ||
| 27 | info!("usart4: rx_buf {:02x}", rx_buf); | ||
| 28 | |||
| 29 | Timer::after_millis(10).await; | ||
| 30 | |||
| 31 | let tx_buf = [0xaa; BUFLEN]; | ||
| 32 | uart.write(&tx_buf).await.unwrap(); | ||
| 33 | info!("usart4: tx_buf {:02x}", tx_buf); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | #[embassy_executor::task] | ||
| 38 | async fn usart2_task(mut uart: Uart<'static, Async>) { | ||
| 39 | info!("TX Task"); | ||
| 40 | |||
| 41 | loop { | ||
| 42 | let tx_buf = [0x55; BUFLEN]; | ||
| 43 | uart.write(&tx_buf).await.unwrap(); | ||
| 44 | info!("usart2: tx_buf {:02x}", tx_buf); | ||
| 45 | |||
| 46 | Timer::after_millis(10).await; | ||
| 47 | |||
| 48 | let mut rx_buf = [0x00; BUFLEN]; | ||
| 49 | uart.read(&mut rx_buf).await.unwrap(); | ||
| 50 | info!("usart2: rx_buf {:02x}", rx_buf); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | #[embassy_executor::main] | ||
| 55 | async fn main(spawner: Spawner) { | ||
| 56 | let p = embassy_imxrt::init(Default::default()); | ||
| 57 | |||
| 58 | info!("UART test start"); | ||
| 59 | |||
| 60 | let usart4 = Uart::new_with_rtscts( | ||
| 61 | p.FLEXCOMM4, | ||
| 62 | p.PIO0_29, | ||
| 63 | p.PIO0_30, | ||
| 64 | p.PIO1_0, | ||
| 65 | p.PIO0_31, | ||
| 66 | Irqs, | ||
| 67 | p.DMA0_CH9, | ||
| 68 | p.DMA0_CH8, | ||
| 69 | Default::default(), | ||
| 70 | ) | ||
| 71 | .unwrap(); | ||
| 72 | spawner.spawn(usart4_task(usart4).unwrap()); | ||
| 73 | |||
| 74 | let usart2 = Uart::new_with_rtscts( | ||
| 75 | p.FLEXCOMM2, | ||
| 76 | p.PIO0_15, | ||
| 77 | p.PIO0_16, | ||
| 78 | p.PIO0_18, | ||
| 79 | p.PIO0_17, | ||
| 80 | Irqs, | ||
| 81 | p.DMA0_CH5, | ||
| 82 | p.DMA0_CH4, | ||
| 83 | Default::default(), | ||
| 84 | ) | ||
| 85 | .unwrap(); | ||
| 86 | spawner.spawn(usart2_task(usart2).unwrap()); | ||
| 87 | } | ||
diff --git a/examples/mimxrt6/src/bin/uart.rs b/examples/mimxrt6/src/bin/uart.rs new file mode 100644 index 000000000..1636c958f --- /dev/null +++ b/examples/mimxrt6/src/bin/uart.rs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | extern crate embassy_imxrt_examples; | ||
| 5 | |||
| 6 | use defmt::info; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_imxrt::flexcomm::uart::{Blocking, Uart, UartRx, UartTx}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::task] | ||
| 13 | async fn usart4_task(mut uart: UartRx<'static, Blocking>) { | ||
| 14 | info!("RX Task"); | ||
| 15 | |||
| 16 | loop { | ||
| 17 | let mut buf = [0; 8]; | ||
| 18 | |||
| 19 | Timer::after_millis(10).await; | ||
| 20 | |||
| 21 | uart.blocking_read(&mut buf).unwrap(); | ||
| 22 | |||
| 23 | let s = core::str::from_utf8(&buf).unwrap(); | ||
| 24 | |||
| 25 | info!("Received '{}'", s); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | #[embassy_executor::task] | ||
| 30 | async fn usart2_task(mut uart: UartTx<'static, Blocking>) { | ||
| 31 | info!("TX Task"); | ||
| 32 | |||
| 33 | loop { | ||
| 34 | let buf = "Testing\0".as_bytes(); | ||
| 35 | |||
| 36 | uart.blocking_write(buf).unwrap(); | ||
| 37 | |||
| 38 | Timer::after_millis(10).await; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | #[embassy_executor::main] | ||
| 43 | async fn main(spawner: Spawner) { | ||
| 44 | let p = embassy_imxrt::init(Default::default()); | ||
| 45 | |||
| 46 | info!("UART test start"); | ||
| 47 | |||
| 48 | let usart4 = Uart::new_blocking(p.FLEXCOMM4, p.PIO0_29, p.PIO0_30, Default::default()).unwrap(); | ||
| 49 | |||
| 50 | let (_, usart4) = usart4.split(); | ||
| 51 | spawner.spawn(usart4_task(usart4).unwrap()); | ||
| 52 | |||
| 53 | let usart2 = UartTx::new_blocking(p.FLEXCOMM2, p.PIO0_15, Default::default()).unwrap(); | ||
| 54 | spawner.spawn(usart2_task(usart2).unwrap()); | ||
| 55 | } | ||
diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index ba64a578d..21434106a 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml | |||
| @@ -3,18 +3,19 @@ edition = "2021" | |||
| 3 | name = "embassy-mspm0-c1104-examples" | 3 | name = "embassy-mspm0-c1104-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c110x", "defmt", "rt", "time-driver-any"] } | 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } |
| 12 | panic-halt = "0.2.0" | 13 | panic-halt = "1.0.0" |
| 13 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 14 | cortex-m-rt = { version = "0.7.0"} | 15 | cortex-m-rt = { version = "0.7.0"} |
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | panic-semihosting = "0.6.0" | 19 | panic-semihosting = "0.6.0" |
| 19 | 20 | ||
| 20 | # The chip only has 1KB of ram, so we must optimize binaries regardless | 21 | # The chip only has 1KB of ram, so we must optimize binaries regardless |
| @@ -30,3 +31,8 @@ debug = 0 | |||
| 30 | opt-level = "z" | 31 | opt-level = "z" |
| 31 | lto = true | 32 | lto = true |
| 32 | codegen-units = 1 | 33 | codegen-units = 1 |
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0c1104", env = { DEFMT_RTT_BUFFER_SIZE = "72" }} | ||
| 38 | ] | ||
diff --git a/examples/mspm0c1104/README.md b/examples/mspm0c1104/README.md index e5c9f961d..86b6c3918 100644 --- a/examples/mspm0c1104/README.md +++ b/examples/mspm0c1104/README.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Examples for MSPM0C110x family | 1 | # Examples for MSPM0C1104 |
| 2 | 2 | ||
| 3 | Run individual examples with | 3 | Run individual examples with |
| 4 | ``` | 4 | ``` |
| @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0C1104](https://www.t | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. |
| 16 | 16 | ||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip) | 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip) |
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for C1104 it should be `mspm0c1104`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0C1104 it should be `mspm0c1104dgs20`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. |
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. |
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic |
| 21 | 21 | ||
diff --git a/examples/mspm0c1104/build.rs b/examples/mspm0c1104/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0c1104/build.rs +++ b/examples/mspm0c1104/build.rs | |||
| @@ -32,4 +32,6 @@ fn main() { | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); |
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 35 | } | 37 | } |
diff --git a/examples/mspm0c1104/src/bin/wwdt.rs b/examples/mspm0c1104/src/bin/wwdt.rs new file mode 100644 index 000000000..2859ccd5e --- /dev/null +++ b/examples/mspm0c1104/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0C1104 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/mspm0g3507/.cargo/config.toml b/examples/mspm0g3507/.cargo/config.toml index 34c720cdd..e711afaf2 100644 --- a/examples/mspm0g3507/.cargo/config.toml +++ b/examples/mspm0g3507/.cargo/config.toml | |||
| @@ -6,4 +6,4 @@ runner = "probe-rs run --chip MSPM0G3507 --protocol=swd" | |||
| 6 | target = "thumbv6m-none-eabi" | 6 | target = "thumbv6m-none-eabi" |
| 7 | 7 | ||
| 8 | [env] | 8 | [env] |
| 9 | DEFMT_LOG = "debug" | 9 | DEFMT_LOG = "trace" |
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index f6fed091d..616b82adb 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml | |||
| @@ -3,19 +3,27 @@ edition = "2021" | |||
| 3 | name = "embassy-mspm0-g3507-examples" | 3 | name = "embassy-mspm0-g3507-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g350x", "defmt", "rt", "time-driver-any"] } | 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } |
| 12 | panic-halt = "0.2.0" | 13 | panic-halt = "1.0.0" |
| 13 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 14 | cortex-m-rt = { version = "0.7.0"} | 15 | cortex-m-rt = { version = "0.7.0"} |
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | panic-semihosting = "0.6.0" | 19 | panic-semihosting = "0.6.0" |
| 19 | 20 | ||
| 21 | embedded-io-async = "0.6.1" | ||
| 22 | |||
| 20 | [profile.release] | 23 | [profile.release] |
| 21 | debug = 2 | 24 | debug = 2 |
| 25 | |||
| 26 | [package.metadata.embassy] | ||
| 27 | build = [ | ||
| 28 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3507" } | ||
| 29 | ] | ||
diff --git a/examples/mspm0g3507/README.md b/examples/mspm0g3507/README.md index 5e8a83212..be91dc5a0 100644 --- a/examples/mspm0g3507/README.md +++ b/examples/mspm0g3507/README.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Examples for MSPM0C350x family | 1 | # Examples for MSPM0M3507 |
| 2 | 2 | ||
| 3 | Run individual examples with | 3 | Run individual examples with |
| 4 | ``` | 4 | ``` |
| @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3507](https://www.t | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. |
| 16 | 16 | ||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip) | 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip) |
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3507 it should be `mspm0g3507`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3507 it should be `mspm0g3507pm`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. |
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. |
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic |
| 21 | 21 | ||
diff --git a/examples/mspm0g3507/build.rs b/examples/mspm0g3507/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3507/build.rs +++ b/examples/mspm0g3507/build.rs | |||
| @@ -32,4 +32,6 @@ fn main() { | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); |
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 35 | } | 37 | } |
diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs new file mode 100644 index 000000000..8d1ed1726 --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c.rs | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | //! This example uses FIFO with polling, and the maximum FIFO size is 8. | ||
| 2 | //! Refer to async example to handle larger packets. | ||
| 3 | //! | ||
| 4 | //! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_mspm0::i2c::{Config, I2c}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | const ADDRESS: u8 = 0x6a; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) -> ! { | ||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | |||
| 21 | let instance = p.I2C1; | ||
| 22 | let scl = p.PB2; | ||
| 23 | let sda = p.PB3; | ||
| 24 | |||
| 25 | let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); | ||
| 26 | |||
| 27 | let mut pot_value: u8 = 0; | ||
| 28 | |||
| 29 | loop { | ||
| 30 | let to_write = [0u8, pot_value]; | ||
| 31 | |||
| 32 | match i2c.blocking_write(ADDRESS, &to_write) { | ||
| 33 | Ok(()) => info!("New potentioemter value: {}", pot_value), | ||
| 34 | Err(e) => error!("I2c Error: {:?}", e), | ||
| 35 | } | ||
| 36 | |||
| 37 | pot_value += 1; | ||
| 38 | // if reached 64th position (max) | ||
| 39 | // start over from lowest value | ||
| 40 | if pot_value == 64 { | ||
| 41 | pot_value = 0; | ||
| 42 | } | ||
| 43 | Timer::after_millis(500).await; | ||
| 44 | } | ||
| 45 | } | ||
diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs new file mode 100644 index 000000000..d486e2a03 --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c_async.rs | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | //! The example uses FIFO and interrupts, wrapped in async API. | ||
| 2 | //! | ||
| 3 | //! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::bind_interrupts; | ||
| 11 | use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; | ||
| 12 | use embassy_mspm0::peripherals::I2C1; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use {defmt_rtt as _, panic_halt as _}; | ||
| 15 | |||
| 16 | const ADDRESS: u8 = 0x6a; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | I2C1 => InterruptHandler<I2C1>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) -> ! { | ||
| 24 | let p = embassy_mspm0::init(Default::default()); | ||
| 25 | |||
| 26 | let instance = p.I2C1; | ||
| 27 | let scl = p.PB2; | ||
| 28 | let sda = p.PB3; | ||
| 29 | |||
| 30 | let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); | ||
| 31 | |||
| 32 | let mut pot_value: u8 = 0; | ||
| 33 | |||
| 34 | loop { | ||
| 35 | let to_write = [0u8, pot_value]; | ||
| 36 | |||
| 37 | match i2c.async_write(ADDRESS, &to_write).await { | ||
| 38 | Ok(()) => info!("New potentioemter value: {}", pot_value), | ||
| 39 | Err(e) => error!("I2c Error: {:?}", e), | ||
| 40 | } | ||
| 41 | |||
| 42 | pot_value += 1; | ||
| 43 | // if reached 64th position (max) | ||
| 44 | // start over from lowest value | ||
| 45 | if pot_value == 64 { | ||
| 46 | pot_value = 0; | ||
| 47 | } | ||
| 48 | Timer::after_millis(500).await; | ||
| 49 | } | ||
| 50 | } | ||
diff --git a/examples/mspm0g3507/src/bin/wwdt.rs b/examples/mspm0g3507/src/bin/wwdt.rs new file mode 100644 index 000000000..d10451448 --- /dev/null +++ b/examples/mspm0g3507/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0G3507 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index 1662e1f8d..ae699d6f4 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml | |||
| @@ -3,19 +3,25 @@ edition = "2021" | |||
| 3 | name = "embassy-mspm0-g3519-examples" | 3 | name = "embassy-mspm0-g3519-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g351x", "defmt", "rt", "time-driver-any"] } | 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } |
| 12 | panic-halt = "0.2.0" | 13 | panic-halt = "1.0.0" |
| 13 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 14 | cortex-m-rt = { version = "0.7.0"} | 15 | cortex-m-rt = { version = "0.7.0"} |
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | panic-semihosting = "0.6.0" | 19 | panic-semihosting = "0.6.0" |
| 19 | 20 | ||
| 20 | [profile.release] | 21 | [profile.release] |
| 21 | debug = 2 | 22 | debug = 2 |
| 23 | |||
| 24 | [package.metadata.embassy] | ||
| 25 | build = [ | ||
| 26 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3519" } | ||
| 27 | ] | ||
diff --git a/examples/mspm0g3519/README.md b/examples/mspm0g3519/README.md index 5034b1913..c392c9e25 100644 --- a/examples/mspm0g3519/README.md +++ b/examples/mspm0g3519/README.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Examples for MSPM0G351x family | 1 | # Examples for MSPM0G3519 |
| 2 | 2 | ||
| 3 | Run individual examples with | 3 | Run individual examples with |
| 4 | ``` | 4 | ``` |
| @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3519](https://www.t | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. |
| 16 | 16 | ||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip) | 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip) |
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3519 it should be `mspm0g3519`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3519 it should be `mspm0g3519pz`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. |
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. |
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic |
| 21 | 21 | ||
diff --git a/examples/mspm0g3519/build.rs b/examples/mspm0g3519/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3519/build.rs +++ b/examples/mspm0g3519/build.rs | |||
| @@ -32,4 +32,6 @@ fn main() { | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); |
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 35 | } | 37 | } |
diff --git a/examples/mspm0g3519/src/bin/wwdt.rs b/examples/mspm0g3519/src/bin/wwdt.rs new file mode 100644 index 000000000..fede95fa2 --- /dev/null +++ b/examples/mspm0g3519/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0G3519 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 609b3f205..8100e11da 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml | |||
| @@ -3,19 +3,29 @@ edition = "2021" | |||
| 3 | name = "embassy-mspm0-l1306-examples" | 3 | name = "embassy-mspm0-l1306-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l130x", "defmt", "rt", "time-driver-any"] } | 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } |
| 12 | panic-halt = "0.2.0" | 13 | panic-halt = "1.0.0" |
| 13 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 14 | cortex-m-rt = { version = "0.7.0"} | 15 | cortex-m-rt = { version = "0.7.0"} |
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | panic-semihosting = "0.6.0" | 19 | panic-semihosting = "0.6.0" |
| 19 | 20 | ||
| 20 | [profile.release] | 21 | [profile.release] |
| 21 | debug = 2 | 22 | debug = 2 |
| 23 | |||
| 24 | [profile.dev] | ||
| 25 | debug = 2 | ||
| 26 | opt-level = 2 | ||
| 27 | |||
| 28 | [package.metadata.embassy] | ||
| 29 | build = [ | ||
| 30 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l1306" } | ||
| 31 | ] | ||
diff --git a/examples/mspm0l1306/README.md b/examples/mspm0l1306/README.md index 5a55d721e..4d698e0fa 100644 --- a/examples/mspm0l1306/README.md +++ b/examples/mspm0l1306/README.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Examples for MSPM0L130x family | 1 | # Examples for MSPM0L1306 |
| 2 | 2 | ||
| 3 | Run individual examples with | 3 | Run individual examples with |
| 4 | ``` | 4 | ``` |
| @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L1306](https://www.t | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. |
| 16 | 16 | ||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip) | 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip) |
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L1306 it should be `mspm0l1306`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0L1306 it should be `mspm0l1306rhb`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. |
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. |
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic |
| 21 | 21 | ||
diff --git a/examples/mspm0l1306/build.rs b/examples/mspm0l1306/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l1306/build.rs +++ b/examples/mspm0l1306/build.rs | |||
| @@ -32,4 +32,6 @@ fn main() { | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); |
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 35 | } | 37 | } |
diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs new file mode 100644 index 000000000..e8801c485 --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c.rs | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | //! This example uses FIFO with polling, and the maximum FIFO size is 8. | ||
| 2 | //! Refer to async example to handle larger packets. | ||
| 3 | //! | ||
| 4 | //! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_mspm0::i2c::{Config, I2c}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | const ADDRESS: u8 = 0x2c; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) -> ! { | ||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | |||
| 21 | let instance = p.I2C0; | ||
| 22 | let scl = p.PA1; | ||
| 23 | let sda = p.PA0; | ||
| 24 | |||
| 25 | let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); | ||
| 26 | |||
| 27 | let mut pot_value: u8 = 0; | ||
| 28 | |||
| 29 | loop { | ||
| 30 | let to_write = [0u8, pot_value]; | ||
| 31 | |||
| 32 | match i2c.blocking_write(ADDRESS, &to_write) { | ||
| 33 | Ok(()) => info!("New potentioemter value: {}", pot_value), | ||
| 34 | Err(e) => error!("I2c Error: {:?}", e), | ||
| 35 | } | ||
| 36 | |||
| 37 | pot_value += 1; | ||
| 38 | // if reached 64th position (max) | ||
| 39 | // start over from lowest value | ||
| 40 | if pot_value == 64 { | ||
| 41 | pot_value = 0; | ||
| 42 | } | ||
| 43 | Timer::after_millis(500).await; | ||
| 44 | } | ||
| 45 | } | ||
diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs new file mode 100644 index 000000000..c4a6938ff --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c_async.rs | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | //! The example uses FIFO and interrupts, wrapped in async API. | ||
| 2 | //! | ||
| 3 | //! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::bind_interrupts; | ||
| 11 | use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; | ||
| 12 | use embassy_mspm0::peripherals::I2C0; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use {defmt_rtt as _, panic_halt as _}; | ||
| 15 | |||
| 16 | const ADDRESS: u8 = 0x6a; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | I2C0 => InterruptHandler<I2C0>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) -> ! { | ||
| 24 | let p = embassy_mspm0::init(Default::default()); | ||
| 25 | |||
| 26 | let instance = p.I2C0; | ||
| 27 | let scl = p.PA1; | ||
| 28 | let sda = p.PA0; | ||
| 29 | |||
| 30 | let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); | ||
| 31 | |||
| 32 | let mut pot_value: u8 = 0; | ||
| 33 | |||
| 34 | loop { | ||
| 35 | let to_write = [0u8, pot_value]; | ||
| 36 | |||
| 37 | match i2c.async_write(ADDRESS, &to_write).await { | ||
| 38 | Ok(()) => info!("New potentioemter value: {}", pot_value), | ||
| 39 | Err(e) => error!("I2c Error: {:?}", e), | ||
| 40 | } | ||
| 41 | |||
| 42 | pot_value += 1; | ||
| 43 | // if reached 64th position (max) | ||
| 44 | // start over from lowest value | ||
| 45 | if pot_value == 64 { | ||
| 46 | pot_value = 0; | ||
| 47 | } | ||
| 48 | Timer::after_millis(500).await; | ||
| 49 | } | ||
| 50 | } | ||
diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs new file mode 100644 index 000000000..b8fb1a1cd --- /dev/null +++ b/examples/mspm0l1306/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0L1306 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index bbca011a1..3add7b8e8 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml | |||
| @@ -3,19 +3,25 @@ edition = "2021" | |||
| 3 | name = "embassy-mspm0-l2228-examples" | 3 | name = "embassy-mspm0-l2228-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l222x", "defmt", "rt", "time-driver-any"] } | 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } |
| 12 | panic-halt = "0.2.0" | 13 | panic-halt = "1.0.0" |
| 13 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 14 | cortex-m-rt = { version = "0.7.0"} | 15 | cortex-m-rt = { version = "0.7.0"} |
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | panic-probe = { version = "0.3.2", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | panic-semihosting = "0.6.0" | 19 | panic-semihosting = "0.6.0" |
| 19 | 20 | ||
| 20 | [profile.release] | 21 | [profile.release] |
| 21 | debug = 2 | 22 | debug = 2 |
| 23 | |||
| 24 | [package.metadata.embassy] | ||
| 25 | build = [ | ||
| 26 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l2228" } | ||
| 27 | ] | ||
diff --git a/examples/mspm0l2228/README.md b/examples/mspm0l2228/README.md index c73fa13b6..191022258 100644 --- a/examples/mspm0l2228/README.md +++ b/examples/mspm0l2228/README.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Examples for MSPM0L222x family | 1 | # Examples for MSPM0L2228 |
| 2 | 2 | ||
| 3 | Run individual examples with | 3 | Run individual examples with |
| 4 | ``` | 4 | ``` |
| @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L2228](https://www.t | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. |
| 16 | 16 | ||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip) | 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip) |
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L2228 it should be `mspm0l2228`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for LP-MSPM0L2228 it should be `mspm0l2228pn`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. |
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. |
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic |
| 21 | 21 | ||
diff --git a/examples/mspm0l2228/build.rs b/examples/mspm0l2228/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l2228/build.rs +++ b/examples/mspm0l2228/build.rs | |||
| @@ -32,4 +32,6 @@ fn main() { | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); |
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 35 | } | 37 | } |
diff --git a/examples/mspm0l2228/src/bin/wwdt.rs b/examples/mspm0l2228/src/bin/wwdt.rs new file mode 100644 index 000000000..487d09820 --- /dev/null +++ b/examples/mspm0l2228/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0L2228 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index af12212cd..c9eeaaac7 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml | |||
| @@ -3,6 +3,7 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf-rtos-trace-examples" | 3 | name = "embassy-nrf-rtos-trace-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [features] | 8 | [features] |
| 8 | default = ["log"] | 9 | default = ["log"] |
| @@ -15,18 +16,17 @@ log = [ | |||
| 15 | ] | 16 | ] |
| 16 | 17 | ||
| 17 | [dependencies] | 18 | [dependencies] |
| 18 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync" } | 19 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } |
| 19 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } | 20 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } |
| 20 | embassy-time = { version = "0.4.0", path = "../../embassy-time" } | 21 | embassy-time = { version = "0.5.0", path = "../../embassy-time" } |
| 21 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 22 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 22 | 23 | ||
| 23 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 24 | cortex-m-rt = "0.7.0" | 25 | cortex-m-rt = "0.7.0" |
| 25 | panic-probe = { version = "0.3" } | 26 | panic-probe = "1.0.0" |
| 26 | rand = { version = "0.8.4", default-features = false } | ||
| 27 | serde = { version = "1.0.136", default-features = false } | 27 | serde = { version = "1.0.136", default-features = false } |
| 28 | rtos-trace = "0.1.3" | 28 | rtos-trace = "0.2" |
| 29 | systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } | 29 | systemview-target = { version = "0.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } |
| 30 | log = { version = "0.4.17", optional = true } | 30 | log = { version = "0.4.17", optional = true } |
| 31 | 31 | ||
| 32 | [[bin]] | 32 | [[bin]] |
| @@ -35,3 +35,8 @@ name = "rtos_trace" | |||
| 35 | 35 | ||
| 36 | [profile.release] | 36 | [profile.release] |
| 37 | debug = 2 | 37 | debug = 2 |
| 38 | |||
| 39 | [package.metadata.embassy] | ||
| 40 | build = [ | ||
| 41 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf-rtos-trace" } | ||
| 42 | ] | ||
diff --git a/examples/nrf-rtos-trace/build.rs b/examples/nrf-rtos-trace/build.rs index 36cdb65a8..cd1a264c4 100644 --- a/examples/nrf-rtos-trace/build.rs +++ b/examples/nrf-rtos-trace/build.rs | |||
| @@ -31,6 +31,4 @@ fn main() { | |||
| 31 | 31 | ||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); |
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); |
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 36 | } | 34 | } |
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs index 41cc06417..c1e7f8f58 100644 --- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs +++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs | |||
| @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { | |||
| 63 | ::log::set_max_level(::log::LevelFilter::Trace); | 63 | ::log::set_max_level(::log::LevelFilter::Trace); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | spawner.spawn(run1()).unwrap(); | 66 | spawner.spawn(run1().unwrap()); |
| 67 | spawner.spawn(run2()).unwrap(); | 67 | spawner.spawn(run2().unwrap()); |
| 68 | spawner.spawn(run3()).unwrap(); | 68 | spawner.spawn(run3().unwrap()); |
| 69 | } | 69 | } |
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 97b5b924a..dded6de59 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml | |||
| @@ -3,18 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf51-examples" | 3 | name = "embassy-nrf51-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 9 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } | 11 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } |
| 11 | 12 | ||
| 12 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.4" | 14 | defmt-rtt = "1.0.0" |
| 14 | 15 | ||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 16 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 16 | cortex-m-rt = "0.7" | 17 | cortex-m-rt = "0.7" |
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | 19 | ||
| 19 | [profile.release] | 20 | [profile.release] |
| 20 | debug = 2 | 21 | debug = 2 |
| 22 | |||
| 23 | [package.metadata.embassy] | ||
| 24 | build = [ | ||
| 25 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/nrf51" } | ||
| 26 | ] | ||
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index cd59b86c3..aa1a4bf73 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml | |||
| @@ -3,22 +3,28 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf52810-examples" | 3 | name = "embassy-nrf52810-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 9 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 13 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "1.0.0" |
| 16 | 17 | ||
| 17 | fixed = "1.10.0" | 18 | fixed = "1.10.0" |
| 18 | static_cell = { version = "2" } | 19 | static_cell = { version = "2" } |
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 22 | 23 | ||
| 23 | [profile.release] | 24 | [profile.release] |
| 24 | debug = 2 | 25 | debug = 2 |
| 26 | |||
| 27 | [package.metadata.embassy] | ||
| 28 | build = [ | ||
| 29 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52810" } | ||
| 30 | ] | ||
diff --git a/examples/nrf52840-edf/.cargo/config.toml b/examples/nrf52840-edf/.cargo/config.toml new file mode 100644 index 000000000..e0b9ce59e --- /dev/null +++ b/examples/nrf52840-edf/.cargo/config.toml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` | ||
| 3 | runner = "probe-rs run --chip nRF52840_xxAA" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv7em-none-eabi" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "debug" | ||
diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml new file mode 100644 index 000000000..1e8803233 --- /dev/null +++ b/examples/nrf52840-edf/Cargo.toml | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-nrf52840-edf-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | # NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled | ||
| 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] } | ||
| 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||
| 12 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | ||
| 13 | |||
| 14 | defmt = "1.0.1" | ||
| 15 | defmt-rtt = "1.0.0" | ||
| 16 | |||
| 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 18 | cortex-m-rt = "0.7.0" | ||
| 19 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 20 | |||
| 21 | [profile.release] | ||
| 22 | debug = 2 | ||
| 23 | |||
| 24 | [package.metadata.embassy] | ||
| 25 | build = [ | ||
| 26 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-edf" } | ||
| 27 | ] | ||
diff --git a/examples/nrf52840-edf/build.rs b/examples/nrf52840-edf/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf52840-edf/build.rs | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | //! This build script copies the `memory.x` file from the crate root into | ||
| 2 | //! a directory where the linker can always find it at build time. | ||
| 3 | //! For many projects this is optional, as the linker always searches the | ||
| 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you | ||
| 5 | //! are using a workspace or have a more complicated build setup, this | ||
| 6 | //! build script becomes required. Additionally, by requesting that | ||
| 7 | //! Cargo re-run the build script whenever `memory.x` is changed, | ||
| 8 | //! updating `memory.x` ensures a rebuild of the application with the | ||
| 9 | //! new memory settings. | ||
| 10 | |||
| 11 | use std::env; | ||
| 12 | use std::fs::File; | ||
| 13 | use std::io::Write; | ||
| 14 | use std::path::PathBuf; | ||
| 15 | |||
| 16 | fn main() { | ||
| 17 | // Put `memory.x` in our output directory and ensure it's | ||
| 18 | // on the linker search path. | ||
| 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 20 | File::create(out.join("memory.x")) | ||
| 21 | .unwrap() | ||
| 22 | .write_all(include_bytes!("memory.x")) | ||
| 23 | .unwrap(); | ||
| 24 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 25 | |||
| 26 | // By default, Cargo will re-run a build script whenever | ||
| 27 | // any file in the project changes. By specifying `memory.x` | ||
| 28 | // here, we ensure the build script is only re-run when | ||
| 29 | // `memory.x` is changed. | ||
| 30 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 31 | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 35 | } | ||
diff --git a/examples/nrf52840-edf/memory.x b/examples/nrf52840-edf/memory.x new file mode 100644 index 000000000..15b492bce --- /dev/null +++ b/examples/nrf52840-edf/memory.x | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K | ||
| 5 | RAM : ORIGIN = 0x20000000, LENGTH = 256K | ||
| 6 | |||
| 7 | /* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */ | ||
| 8 | /* | ||
| 9 | FLASH : ORIGIN = 0x00027000, LENGTH = 868K | ||
| 10 | RAM : ORIGIN = 0x20020000, LENGTH = 128K | ||
| 11 | */ | ||
| 12 | } | ||
diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs new file mode 100644 index 000000000..d888e17d1 --- /dev/null +++ b/examples/nrf52840-edf/src/bin/basic.rs | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | //! Basic side-by-side example of the Earliest Deadline First scheduler | ||
| 2 | //! | ||
| 3 | //! This test spawns a number of background "ambient system load" workers | ||
| 4 | //! that are constantly working, and runs two sets of trials. | ||
| 5 | //! | ||
| 6 | //! The first trial runs with no deadline set, so our trial task is at the | ||
| 7 | //! same prioritization level as the background worker tasks. | ||
| 8 | //! | ||
| 9 | //! The second trial sets a deadline, meaning that it will be given higher | ||
| 10 | //! scheduling priority than background tasks, that have no deadline set | ||
| 11 | |||
| 12 | #![no_std] | ||
| 13 | #![no_main] | ||
| 14 | |||
| 15 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 16 | |||
| 17 | use defmt::unwrap; | ||
| 18 | use embassy_executor::Spawner; | ||
| 19 | use embassy_time::{Duration, Instant, Timer}; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(spawner: Spawner) { | ||
| 24 | embassy_nrf::init(Default::default()); | ||
| 25 | |||
| 26 | // Enable flash cache to remove some flash latency jitter | ||
| 27 | compiler_fence(Ordering::SeqCst); | ||
| 28 | embassy_nrf::pac::NVMC.icachecnf().write(|w| { | ||
| 29 | w.set_cacheen(true); | ||
| 30 | }); | ||
| 31 | compiler_fence(Ordering::SeqCst); | ||
| 32 | |||
| 33 | // | ||
| 34 | // Baseline system load tunables | ||
| 35 | // | ||
| 36 | |||
| 37 | // how many load tasks? More load tasks means more tasks contending | ||
| 38 | // for the runqueue | ||
| 39 | let tasks = 32; | ||
| 40 | // how long should each task work for? The longer the working time, | ||
| 41 | // the longer the max jitter possible, even when a task is prioritized, | ||
| 42 | // as EDF is still cooperative and not pre-emptive | ||
| 43 | // | ||
| 44 | // 33 ticks ~= 1ms | ||
| 45 | let work_time_ticks = 33; | ||
| 46 | // what fraction, 1/denominator, should the system be busy? | ||
| 47 | // bigger number means **less** busy | ||
| 48 | // | ||
| 49 | // 2 => 50% | ||
| 50 | // 4 => 25% | ||
| 51 | // 10 => 10% | ||
| 52 | let denominator = 2; | ||
| 53 | |||
| 54 | // Total time window, so each worker is working 1/denominator | ||
| 55 | // amount of the total time | ||
| 56 | let time_window = work_time_ticks * u64::from(tasks) * denominator; | ||
| 57 | |||
| 58 | // Spawn all of our load workers! | ||
| 59 | for i in 0..tasks { | ||
| 60 | spawner.spawn(unwrap!(load_task(i, work_time_ticks, time_window))); | ||
| 61 | } | ||
| 62 | |||
| 63 | // Let all the tasks spin up | ||
| 64 | defmt::println!("Spinning up load tasks..."); | ||
| 65 | Timer::after_secs(1).await; | ||
| 66 | |||
| 67 | // | ||
| 68 | // Trial task worker tunables | ||
| 69 | // | ||
| 70 | |||
| 71 | // How many steps should the workers under test run? | ||
| 72 | // More steps means more chances to have to wait for other tasks | ||
| 73 | // in line ahead of us. | ||
| 74 | let num_steps = 100; | ||
| 75 | |||
| 76 | // How many ticks should the worker take working on each step? | ||
| 77 | // | ||
| 78 | // 33 ticks ~= 1ms | ||
| 79 | let work_ticks = 33; | ||
| 80 | // How many ticks should the worker wait on each step? | ||
| 81 | // | ||
| 82 | // 66 ticks ~= 2ms | ||
| 83 | let idle_ticks = 66; | ||
| 84 | |||
| 85 | // How many times to repeat each trial? | ||
| 86 | let trials = 3; | ||
| 87 | |||
| 88 | // The total time a trial would take, in a perfect unloaded system | ||
| 89 | let theoretical = (num_steps * work_ticks) + (num_steps * idle_ticks); | ||
| 90 | |||
| 91 | defmt::println!(""); | ||
| 92 | defmt::println!("Starting UNPRIORITIZED worker trials"); | ||
| 93 | for _ in 0..trials { | ||
| 94 | // | ||
| 95 | // UNPRIORITIZED worker | ||
| 96 | // | ||
| 97 | defmt::println!(""); | ||
| 98 | defmt::println!("Starting unprioritized worker"); | ||
| 99 | let start = Instant::now(); | ||
| 100 | for _ in 0..num_steps { | ||
| 101 | let now = Instant::now(); | ||
| 102 | while now.elapsed().as_ticks() < work_ticks {} | ||
| 103 | Timer::after_ticks(idle_ticks).await; | ||
| 104 | } | ||
| 105 | let elapsed = start.elapsed().as_ticks(); | ||
| 106 | defmt::println!( | ||
| 107 | "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}", | ||
| 108 | theoretical, | ||
| 109 | elapsed | ||
| 110 | ); | ||
| 111 | let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0; | ||
| 112 | defmt::println!("Took {=f32}% of ideal time", ratio); | ||
| 113 | Timer::after_millis(500).await; | ||
| 114 | } | ||
| 115 | |||
| 116 | Timer::after_secs(1).await; | ||
| 117 | |||
| 118 | defmt::println!(""); | ||
| 119 | defmt::println!("Starting PRIORITIZED worker trials"); | ||
| 120 | for _ in 0..trials { | ||
| 121 | // | ||
| 122 | // PRIORITIZED worker | ||
| 123 | // | ||
| 124 | defmt::println!(""); | ||
| 125 | defmt::println!("Starting prioritized worker"); | ||
| 126 | let start = Instant::now(); | ||
| 127 | // Set the deadline to ~2x the theoretical time. In practice, setting any deadline | ||
| 128 | // here elevates the current task above all other worker tasks. | ||
| 129 | let meta = embassy_executor::Metadata::for_current_task().await; | ||
| 130 | meta.set_deadline_after(theoretical * 2); | ||
| 131 | |||
| 132 | // Perform the trial | ||
| 133 | for _ in 0..num_steps { | ||
| 134 | let now = Instant::now(); | ||
| 135 | while now.elapsed().as_ticks() < work_ticks {} | ||
| 136 | Timer::after_ticks(idle_ticks).await; | ||
| 137 | } | ||
| 138 | |||
| 139 | let elapsed = start.elapsed().as_ticks(); | ||
| 140 | defmt::println!( | ||
| 141 | "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}", | ||
| 142 | theoretical, | ||
| 143 | elapsed | ||
| 144 | ); | ||
| 145 | let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0; | ||
| 146 | defmt::println!("Took {=f32}% of ideal time", ratio); | ||
| 147 | |||
| 148 | // Unset the deadline, deadlines are not automatically cleared, and if our | ||
| 149 | // deadline is in the past, then we get very high priority! | ||
| 150 | meta.unset_deadline(); | ||
| 151 | |||
| 152 | Timer::after_millis(500).await; | ||
| 153 | } | ||
| 154 | |||
| 155 | defmt::println!(""); | ||
| 156 | defmt::println!("Trials Complete."); | ||
| 157 | } | ||
| 158 | |||
| 159 | #[embassy_executor::task(pool_size = 32)] | ||
| 160 | async fn load_task(id: u32, ticks_on: u64, ttl_ticks: u64) { | ||
| 161 | let mut last_print = Instant::now(); | ||
| 162 | let mut last_tick = last_print; | ||
| 163 | let mut variance = 0; | ||
| 164 | let mut max_variance = 0; | ||
| 165 | loop { | ||
| 166 | let tgt = last_tick + Duration::from_ticks(ttl_ticks); | ||
| 167 | assert!(tgt > Instant::now(), "fell too behind!"); | ||
| 168 | |||
| 169 | Timer::at(tgt).await; | ||
| 170 | let now = Instant::now(); | ||
| 171 | // How late are we from the target? | ||
| 172 | let var = now.duration_since(tgt).as_ticks(); | ||
| 173 | max_variance = max_variance.max(var); | ||
| 174 | variance += var; | ||
| 175 | |||
| 176 | // blocking work | ||
| 177 | while now.elapsed().as_ticks() < ticks_on {} | ||
| 178 | |||
| 179 | if last_print.elapsed() >= Duration::from_secs(1) { | ||
| 180 | defmt::trace!( | ||
| 181 | "Task {=u32} variance ticks (1s): {=u64}, max: {=u64}, act: {=u64}", | ||
| 182 | id, | ||
| 183 | variance, | ||
| 184 | max_variance, | ||
| 185 | ticks_on, | ||
| 186 | ); | ||
| 187 | max_variance = 0; | ||
| 188 | variance = 0; | ||
| 189 | last_print = Instant::now(); | ||
| 190 | } | ||
| 191 | |||
| 192 | last_tick = tgt; | ||
| 193 | } | ||
| 194 | } | ||
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index ac3d2006c..f6937c263 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml | |||
| @@ -3,22 +3,28 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf52840-rtic-examples" | 3 | name = "embassy-nrf52840-rtic-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | rtic = { version = "2", features = ["thumbv7-backend"] } | 9 | rtic = { version = "2", features = ["thumbv7-backend"] } |
| 9 | 10 | ||
| 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 11 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 11 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } | 14 | embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } |
| 14 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 15 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 22 | 23 | ||
| 23 | [profile.release] | 24 | [profile.release] |
| 24 | debug = 2 | 25 | debug = 2 |
| 26 | |||
| 27 | [package.metadata.embassy] | ||
| 28 | build = [ | ||
| 29 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-rtic" } | ||
| 30 | ] | ||
diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs index 719e22729..2adac7e0a 100644 --- a/examples/nrf52840-rtic/src/bin/blinky.rs +++ b/examples/nrf52840-rtic/src/bin/blinky.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use {defmt_rtt as _, panic_probe as _}; | 4 | use {defmt_rtt as _, panic_probe as _}; |
| 6 | 5 | ||
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 902193f3a..452e83b7e 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml | |||
| @@ -3,29 +3,30 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf52840-examples" | 3 | name = "embassy-nrf52840-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 9 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 13 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | 16 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } |
| 16 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | 17 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } |
| 17 | embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } | 18 | embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] } |
| 18 | embassy-net-enc28j60 = { version = "0.2.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } | 19 | embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] } |
| 19 | 20 | ||
| 20 | defmt = "0.3" | 21 | defmt = "1.0.1" |
| 21 | defmt-rtt = "0.4" | 22 | defmt-rtt = "1.0.0" |
| 22 | 23 | ||
| 23 | fixed = "1.10.0" | 24 | fixed = "1.10.0" |
| 24 | static_cell = { version = "2" } | 25 | static_cell = { version = "2" } |
| 25 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 26 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 26 | cortex-m-rt = "0.7.0" | 27 | cortex-m-rt = "0.7.0" |
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 28 | rand = { version = "0.8.4", default-features = false } | 29 | rand = { version = "0.9.0", default-features = false } |
| 29 | embedded-storage = "0.3.1" | 30 | embedded-storage = "0.3.1" |
| 30 | usbd-hid = "0.8.1" | 31 | usbd-hid = "0.8.1" |
| 31 | serde = { version = "1.0.136", default-features = false } | 32 | serde = { version = "1.0.136", default-features = false } |
| @@ -37,3 +38,8 @@ microfft = "0.5.0" | |||
| 37 | 38 | ||
| 38 | [profile.release] | 39 | [profile.release] |
| 39 | debug = 2 | 40 | debug = 2 |
| 41 | |||
| 42 | [package.metadata.embassy] | ||
| 43 | build = [ | ||
| 44 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840" } | ||
| 45 | ] | ||
diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs index e06ba1c73..ffa539808 100644 --- a/examples/nrf52840/src/bin/channel.rs +++ b/examples/nrf52840/src/bin/channel.rs | |||
| @@ -31,7 +31,7 @@ async fn main(spawner: Spawner) { | |||
| 31 | let p = embassy_nrf::init(Default::default()); | 31 | let p = embassy_nrf::init(Default::default()); |
| 32 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); | 32 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); |
| 33 | 33 | ||
| 34 | unwrap!(spawner.spawn(my_task())); | 34 | spawner.spawn(unwrap!(my_task())); |
| 35 | 35 | ||
| 36 | loop { | 36 | loop { |
| 37 | match CHANNEL.receive().await { | 37 | match CHANNEL.receive().await { |
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs index 74c62ca20..09050db68 100644 --- a/examples/nrf52840/src/bin/channel_sender_receiver.rs +++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs | |||
| @@ -45,6 +45,6 @@ async fn main(spawner: Spawner) { | |||
| 45 | let p = embassy_nrf::init(Default::default()); | 45 | let p = embassy_nrf::init(Default::default()); |
| 46 | let channel = CHANNEL.init(Channel::new()); | 46 | let channel = CHANNEL.init(Channel::new()); |
| 47 | 47 | ||
| 48 | unwrap!(spawner.spawn(send_task(channel.sender()))); | 48 | spawner.spawn(unwrap!(send_task(channel.sender()))); |
| 49 | unwrap!(spawner.spawn(recv_task(p.P0_13.into(), channel.receiver()))); | 49 | spawner.spawn(unwrap!(recv_task(p.P0_13.into(), channel.receiver()))); |
| 50 | } | 50 | } |
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs index 0946492fe..3bb255a72 100644 --- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs +++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs | |||
| @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { | |||
| 70 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 70 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 71 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 71 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 72 | 72 | ||
| 73 | unwrap!(spawner.spawn(net_task(runner))); | 73 | spawner.spawn(unwrap!(net_task(runner))); |
| 74 | 74 | ||
| 75 | // And now we can use it! | 75 | // And now we can use it! |
| 76 | 76 | ||
diff --git a/examples/nrf52840/src/bin/executor_fairness_test.rs b/examples/nrf52840/src/bin/executor_fairness_test.rs index df6e7af3f..70c9405f0 100644 --- a/examples/nrf52840/src/bin/executor_fairness_test.rs +++ b/examples/nrf52840/src/bin/executor_fairness_test.rs | |||
| @@ -36,7 +36,7 @@ async fn run3() { | |||
| 36 | #[embassy_executor::main] | 36 | #[embassy_executor::main] |
| 37 | async fn main(spawner: Spawner) { | 37 | async fn main(spawner: Spawner) { |
| 38 | let _p = embassy_nrf::init(Default::default()); | 38 | let _p = embassy_nrf::init(Default::default()); |
| 39 | unwrap!(spawner.spawn(run1())); | 39 | spawner.spawn(unwrap!(run1())); |
| 40 | unwrap!(spawner.spawn(run2())); | 40 | spawner.spawn(unwrap!(run2())); |
| 41 | unwrap!(spawner.spawn(run3())); | 41 | spawner.spawn(unwrap!(run3())); |
| 42 | } | 42 | } |
diff --git a/examples/nrf52840/src/bin/gpiote_port.rs b/examples/nrf52840/src/bin/gpiote_port.rs index 0dddb1a97..66dbd32dc 100644 --- a/examples/nrf52840/src/bin/gpiote_port.rs +++ b/examples/nrf52840/src/bin/gpiote_port.rs | |||
| @@ -26,8 +26,8 @@ async fn main(spawner: Spawner) { | |||
| 26 | let btn3 = Input::new(p.P0_24, Pull::Up); | 26 | let btn3 = Input::new(p.P0_24, Pull::Up); |
| 27 | let btn4 = Input::new(p.P0_25, Pull::Up); | 27 | let btn4 = Input::new(p.P0_25, Pull::Up); |
| 28 | 28 | ||
| 29 | unwrap!(spawner.spawn(button_task(1, btn1))); | 29 | spawner.spawn(unwrap!(button_task(1, btn1))); |
| 30 | unwrap!(spawner.spawn(button_task(2, btn2))); | 30 | spawner.spawn(unwrap!(button_task(2, btn2))); |
| 31 | unwrap!(spawner.spawn(button_task(3, btn3))); | 31 | spawner.spawn(unwrap!(button_task(3, btn3))); |
| 32 | unwrap!(spawner.spawn(button_task(4, btn4))); | 32 | spawner.spawn(unwrap!(button_task(4, btn4))); |
| 33 | } | 33 | } |
diff --git a/examples/nrf52840/src/bin/ieee802154_receive.rs b/examples/nrf52840/src/bin/ieee802154_receive.rs new file mode 100644 index 000000000..ede8fca65 --- /dev/null +++ b/examples/nrf52840/src/bin/ieee802154_receive.rs | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::config::{Config, HfclkSource}; | ||
| 6 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| 7 | use embassy_nrf::radio::ieee802154::{self, Packet}; | ||
| 8 | use embassy_nrf::{peripherals, radio}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | embassy_nrf::bind_interrupts!(struct Irqs { | ||
| 13 | RADIO => radio::InterruptHandler<peripherals::RADIO>; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let mut config = Config::default(); | ||
| 19 | config.hfclk_source = HfclkSource::ExternalXtal; | ||
| 20 | let peripherals = embassy_nrf::init(config); | ||
| 21 | |||
| 22 | // assumes LED on P0_15 with active-high polarity | ||
| 23 | let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard); | ||
| 24 | |||
| 25 | let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs); | ||
| 26 | let mut packet = Packet::new(); | ||
| 27 | |||
| 28 | loop { | ||
| 29 | gpo_led.set_low(); | ||
| 30 | let rv = radio.receive(&mut packet).await; | ||
| 31 | gpo_led.set_high(); | ||
| 32 | match rv { | ||
| 33 | Err(_) => defmt::error!("receive() Err"), | ||
| 34 | Ok(_) => defmt::info!("receive() {:?}", *packet), | ||
| 35 | } | ||
| 36 | Timer::after_millis(100u64).await; | ||
| 37 | } | ||
| 38 | } | ||
diff --git a/examples/nrf52840/src/bin/ieee802154_send.rs b/examples/nrf52840/src/bin/ieee802154_send.rs new file mode 100644 index 000000000..7af9d1d06 --- /dev/null +++ b/examples/nrf52840/src/bin/ieee802154_send.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::config::{Config, HfclkSource}; | ||
| 6 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| 7 | use embassy_nrf::radio::ieee802154::{self, Packet}; | ||
| 8 | use embassy_nrf::{peripherals, radio}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | embassy_nrf::bind_interrupts!(struct Irqs { | ||
| 13 | RADIO => radio::InterruptHandler<peripherals::RADIO>; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let mut config = Config::default(); | ||
| 19 | config.hfclk_source = HfclkSource::ExternalXtal; | ||
| 20 | let peripherals = embassy_nrf::init(config); | ||
| 21 | |||
| 22 | // assumes LED on P0_15 with active-high polarity | ||
| 23 | let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard); | ||
| 24 | |||
| 25 | let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs); | ||
| 26 | let mut packet = Packet::new(); | ||
| 27 | |||
| 28 | loop { | ||
| 29 | packet.copy_from_slice(&[0_u8; 16]); | ||
| 30 | gpo_led.set_high(); | ||
| 31 | let rv = radio.try_send(&mut packet).await; | ||
| 32 | gpo_led.set_low(); | ||
| 33 | match rv { | ||
| 34 | Err(_) => defmt::error!("try_send() Err"), | ||
| 35 | Ok(_) => defmt::info!("try_send() {:?}", *packet), | ||
| 36 | } | ||
| 37 | Timer::after_millis(1000u64).await; | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/examples/nrf52840/src/bin/manually_create_executor.rs b/examples/nrf52840/src/bin/manually_create_executor.rs index 7ca39348e..f0639eb23 100644 --- a/examples/nrf52840/src/bin/manually_create_executor.rs +++ b/examples/nrf52840/src/bin/manually_create_executor.rs | |||
| @@ -42,7 +42,7 @@ fn main() -> ! { | |||
| 42 | // `run` calls the closure then runs the executor forever. It never returns. | 42 | // `run` calls the closure then runs the executor forever. It never returns. |
| 43 | executor.run(|spawner| { | 43 | executor.run(|spawner| { |
| 44 | // Here we get access to a spawner to spawn the initial tasks. | 44 | // Here we get access to a spawner to spawn the initial tasks. |
| 45 | unwrap!(spawner.spawn(run1())); | 45 | spawner.spawn(unwrap!(run1())); |
| 46 | unwrap!(spawner.spawn(run2())); | 46 | spawner.spawn(unwrap!(run2())); |
| 47 | }); | 47 | }); |
| 48 | } | 48 | } |
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs index d58613da4..4d9b986d4 100644 --- a/examples/nrf52840/src/bin/multiprio.rs +++ b/examples/nrf52840/src/bin/multiprio.rs | |||
| @@ -130,16 +130,16 @@ fn main() -> ! { | |||
| 130 | // High-priority executor: EGU1_SWI1, priority level 6 | 130 | // High-priority executor: EGU1_SWI1, priority level 6 |
| 131 | interrupt::EGU1_SWI1.set_priority(Priority::P6); | 131 | interrupt::EGU1_SWI1.set_priority(Priority::P6); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::EGU1_SWI1); | 132 | let spawner = EXECUTOR_HIGH.start(interrupt::EGU1_SWI1); |
| 133 | unwrap!(spawner.spawn(run_high())); | 133 | spawner.spawn(unwrap!(run_high())); |
| 134 | 134 | ||
| 135 | // Medium-priority executor: EGU0_SWI0, priority level 7 | 135 | // Medium-priority executor: EGU0_SWI0, priority level 7 |
| 136 | interrupt::EGU0_SWI0.set_priority(Priority::P7); | 136 | interrupt::EGU0_SWI0.set_priority(Priority::P7); |
| 137 | let spawner = EXECUTOR_MED.start(interrupt::EGU0_SWI0); | 137 | let spawner = EXECUTOR_MED.start(interrupt::EGU0_SWI0); |
| 138 | unwrap!(spawner.spawn(run_med())); | 138 | spawner.spawn(unwrap!(run_med())); |
| 139 | 139 | ||
| 140 | // Low priority executor: runs in thread mode, using WFE/SEV | 140 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 141 | let executor = EXECUTOR_LOW.init(Executor::new()); | 141 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 142 | executor.run(|spawner| { | 142 | executor.run(|spawner| { |
| 143 | unwrap!(spawner.spawn(run_low())); | 143 | spawner.spawn(unwrap!(run_low())); |
| 144 | }); | 144 | }); |
| 145 | } | 145 | } |
diff --git a/examples/nrf52840/src/bin/mutex.rs b/examples/nrf52840/src/bin/mutex.rs index 5c22279b5..a8e9a82cc 100644 --- a/examples/nrf52840/src/bin/mutex.rs +++ b/examples/nrf52840/src/bin/mutex.rs | |||
| @@ -30,7 +30,7 @@ async fn my_task() { | |||
| 30 | #[embassy_executor::main] | 30 | #[embassy_executor::main] |
| 31 | async fn main(spawner: Spawner) { | 31 | async fn main(spawner: Spawner) { |
| 32 | let _p = embassy_nrf::init(Default::default()); | 32 | let _p = embassy_nrf::init(Default::default()); |
| 33 | unwrap!(spawner.spawn(my_task())); | 33 | spawner.spawn(unwrap!(my_task())); |
| 34 | 34 | ||
| 35 | loop { | 35 | loop { |
| 36 | Timer::after_millis(300).await; | 36 | Timer::after_millis(300).await; |
diff --git a/examples/nrf52840/src/bin/nfct.rs b/examples/nrf52840/src/bin/nfct.rs index d559d006a..fafa37f48 100644 --- a/examples/nrf52840/src/bin/nfct.rs +++ b/examples/nrf52840/src/bin/nfct.rs | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::{todo, *}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::config::HfclkSource; | 6 | use embassy_nrf::config::HfclkSource; |
| 7 | use embassy_nrf::nfct::{Config as NfcConfig, NfcId, NfcT}; | 7 | use embassy_nrf::nfct::{Config as NfcConfig, NfcId, NfcT}; |
| 8 | use embassy_nrf::{bind_interrupts, nfct}; | 8 | use embassy_nrf::{bind_interrupts, nfct}; |
| 9 | use iso14443_4::{Card, IsoDep}; | ||
| 9 | use {defmt_rtt as _, embassy_nrf as _, panic_probe as _}; | 10 | use {defmt_rtt as _, embassy_nrf as _, panic_probe as _}; |
| 10 | 11 | ||
| 11 | bind_interrupts!(struct Irqs { | 12 | bind_interrupts!(struct Irqs { |
| @@ -30,12 +31,28 @@ async fn main(_spawner: Spawner) { | |||
| 30 | 31 | ||
| 31 | let mut buf = [0u8; 256]; | 32 | let mut buf = [0u8; 256]; |
| 32 | 33 | ||
| 34 | let cc = &[ | ||
| 35 | 0x00, 0x0f, /* CCEN_HI, CCEN_LOW */ | ||
| 36 | 0x20, /* VERSION */ | ||
| 37 | 0x00, 0x7f, /* MLe_HI, MLe_LOW */ | ||
| 38 | 0x00, 0x7f, /* MLc_HI, MLc_LOW */ | ||
| 39 | /* TLV */ | ||
| 40 | 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00, | ||
| 41 | ]; | ||
| 42 | |||
| 43 | let ndef = &[ | ||
| 44 | 0x00, 0x10, 0xd1, 0x1, 0xc, 0x55, 0x4, 0x65, 0x6d, 0x62, 0x61, 0x73, 0x73, 0x79, 0x2e, 0x64, 0x65, 0x76, | ||
| 45 | ]; | ||
| 46 | let mut selected: &[u8] = cc; | ||
| 47 | |||
| 33 | loop { | 48 | loop { |
| 34 | info!("activating"); | 49 | info!("activating"); |
| 35 | nfc.activate().await; | 50 | nfc.activate().await; |
| 51 | info!("activated!"); | ||
| 52 | |||
| 53 | let mut nfc = IsoDep::new(iso14443_3::Logger(&mut nfc)); | ||
| 36 | 54 | ||
| 37 | loop { | 55 | loop { |
| 38 | info!("rxing"); | ||
| 39 | let n = match nfc.receive(&mut buf).await { | 56 | let n = match nfc.receive(&mut buf).await { |
| 40 | Ok(n) => n, | 57 | Ok(n) => n, |
| 41 | Err(e) => { | 58 | Err(e) => { |
| @@ -44,25 +61,51 @@ async fn main(_spawner: Spawner) { | |||
| 44 | } | 61 | } |
| 45 | }; | 62 | }; |
| 46 | let req = &buf[..n]; | 63 | let req = &buf[..n]; |
| 47 | info!("received frame {:02x}", req); | 64 | info!("iso-dep rx {:02x}", req); |
| 48 | 65 | ||
| 49 | let mut deselect = false; | 66 | let Ok(apdu) = Apdu::parse(req) else { |
| 50 | let resp = match req { | 67 | error!("apdu parse error"); |
| 51 | [0xe0, ..] => { | 68 | break; |
| 52 | info!("Got RATS, tx'ing ATS"); | 69 | }; |
| 53 | &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80][..] | 70 | |
| 71 | info!("apdu: {:?}", apdu); | ||
| 72 | |||
| 73 | let resp = match (apdu.cla, apdu.ins, apdu.p1, apdu.p2) { | ||
| 74 | (0, 0xa4, 4, 0) => { | ||
| 75 | info!("select app"); | ||
| 76 | &[0x90, 0x00][..] | ||
| 54 | } | 77 | } |
| 55 | [0xc2] => { | 78 | (0, 0xa4, 0, 12) => { |
| 56 | info!("Got deselect!"); | 79 | info!("select df"); |
| 57 | deselect = true; | 80 | match apdu.data { |
| 58 | &[0xc2] | 81 | [0xe1, 0x03] => { |
| 82 | selected = cc; | ||
| 83 | &[0x90, 0x00][..] | ||
| 84 | } | ||
| 85 | [0xe1, 0x04] => { | ||
| 86 | selected = ndef; | ||
| 87 | &[0x90, 0x00][..] | ||
| 88 | } | ||
| 89 | _ => todo!(), // return NOT FOUND | ||
| 90 | } | ||
| 91 | } | ||
| 92 | (0, 0xb0, p1, p2) => { | ||
| 93 | info!("read"); | ||
| 94 | let offs = u16::from_be_bytes([p1 & 0x7f, p2]) as usize; | ||
| 95 | let len = if apdu.le == 0 { usize::MAX } else { apdu.le as usize }; | ||
| 96 | let n = len.min(selected.len() - offs); | ||
| 97 | buf[..n].copy_from_slice(&selected[offs..][..n]); | ||
| 98 | buf[n..][..2].copy_from_slice(&[0x90, 0x00]); | ||
| 99 | &buf[..n + 2] | ||
| 59 | } | 100 | } |
| 60 | _ => { | 101 | _ => { |
| 61 | info!("Got unknown command!"); | 102 | info!("Got unknown command!"); |
| 62 | &[0xFF] | 103 | &[0xFF, 0xFF] |
| 63 | } | 104 | } |
| 64 | }; | 105 | }; |
| 65 | 106 | ||
| 107 | info!("iso-dep tx {:02x}", resp); | ||
| 108 | |||
| 66 | match nfc.transmit(resp).await { | 109 | match nfc.transmit(resp).await { |
| 67 | Ok(()) => {} | 110 | Ok(()) => {} |
| 68 | Err(e) => { | 111 | Err(e) => { |
| @@ -70,10 +113,211 @@ async fn main(_spawner: Spawner) { | |||
| 70 | break; | 113 | break; |
| 71 | } | 114 | } |
| 72 | } | 115 | } |
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 73 | 119 | ||
| 74 | if deselect { | 120 | #[derive(Debug, Clone, defmt::Format)] |
| 75 | break; | 121 | struct Apdu<'a> { |
| 122 | pub cla: u8, | ||
| 123 | pub ins: u8, | ||
| 124 | pub p1: u8, | ||
| 125 | pub p2: u8, | ||
| 126 | pub data: &'a [u8], | ||
| 127 | pub le: u16, | ||
| 128 | } | ||
| 129 | |||
| 130 | #[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] | ||
| 131 | struct ApduParseError; | ||
| 132 | |||
| 133 | impl<'a> Apdu<'a> { | ||
| 134 | pub fn parse(apdu: &'a [u8]) -> Result<Self, ApduParseError> { | ||
| 135 | if apdu.len() < 4 { | ||
| 136 | return Err(ApduParseError); | ||
| 137 | } | ||
| 138 | |||
| 139 | let (data, le) = match apdu.len() - 4 { | ||
| 140 | 0 => (&[][..], 0), | ||
| 141 | 1 => (&[][..], apdu[4]), | ||
| 142 | n if n == 1 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], 0), | ||
| 143 | n if n == 2 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], apdu[apdu.len() - 1]), | ||
| 144 | _ => return Err(ApduParseError), | ||
| 145 | }; | ||
| 146 | |||
| 147 | Ok(Apdu { | ||
| 148 | cla: apdu[0], | ||
| 149 | ins: apdu[1], | ||
| 150 | p1: apdu[2], | ||
| 151 | p2: apdu[3], | ||
| 152 | data, | ||
| 153 | le: le as _, | ||
| 154 | }) | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | mod iso14443_3 { | ||
| 159 | use core::future::Future; | ||
| 160 | |||
| 161 | use defmt::info; | ||
| 162 | use embassy_nrf::nfct::{Error, NfcT}; | ||
| 163 | |||
| 164 | pub trait Card { | ||
| 165 | type Error; | ||
| 166 | async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>; | ||
| 167 | async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>; | ||
| 168 | } | ||
| 169 | |||
| 170 | impl<'a, T: Card> Card for &'a mut T { | ||
| 171 | type Error = T::Error; | ||
| 172 | |||
| 173 | fn receive(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> { | ||
| 174 | T::receive(self, buf) | ||
| 175 | } | ||
| 176 | |||
| 177 | fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> { | ||
| 178 | T::transmit(self, buf) | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | impl<'a> Card for NfcT<'a> { | ||
| 183 | type Error = Error; | ||
| 184 | |||
| 185 | fn receive(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> { | ||
| 186 | self.receive(buf) | ||
| 187 | } | ||
| 188 | |||
| 189 | fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> { | ||
| 190 | self.transmit(buf) | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | pub struct Logger<T: Card>(pub T); | ||
| 195 | |||
| 196 | impl<T: Card> Card for Logger<T> { | ||
| 197 | type Error = T::Error; | ||
| 198 | |||
| 199 | async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | ||
| 200 | let n = T::receive(&mut self.0, buf).await?; | ||
| 201 | info!("<- {:02x}", &buf[..n]); | ||
| 202 | Ok(n) | ||
| 203 | } | ||
| 204 | |||
| 205 | fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> { | ||
| 206 | info!("-> {:02x}", buf); | ||
| 207 | T::transmit(&mut self.0, buf) | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | mod iso14443_4 { | ||
| 213 | use defmt::info; | ||
| 214 | |||
| 215 | use crate::iso14443_3; | ||
| 216 | |||
| 217 | #[derive(defmt::Format)] | ||
| 218 | pub enum Error<T> { | ||
| 219 | Deselected, | ||
| 220 | Protocol, | ||
| 221 | Lower(T), | ||
| 222 | } | ||
| 223 | |||
| 224 | pub trait Card { | ||
| 225 | type Error; | ||
| 226 | async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>; | ||
| 227 | async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>; | ||
| 228 | } | ||
| 229 | |||
| 230 | pub struct IsoDep<T: iso14443_3::Card> { | ||
| 231 | nfc: T, | ||
| 232 | |||
| 233 | /// Block count spin bit: 0 or 1 | ||
| 234 | block_num: u8, | ||
| 235 | |||
| 236 | /// true if deselected. This is permanent, you must create another IsoDep | ||
| 237 | /// instance if we get selected again. | ||
| 238 | deselected: bool, | ||
| 239 | |||
| 240 | /// last response, in case we need to retransmit. | ||
| 241 | resp: [u8; 256], | ||
| 242 | resp_len: usize, | ||
| 243 | } | ||
| 244 | |||
| 245 | impl<T: iso14443_3::Card> IsoDep<T> { | ||
| 246 | pub fn new(nfc: T) -> Self { | ||
| 247 | Self { | ||
| 248 | nfc, | ||
| 249 | block_num: 1, | ||
| 250 | deselected: false, | ||
| 251 | resp: [0u8; 256], | ||
| 252 | resp_len: 0, | ||
| 76 | } | 253 | } |
| 77 | } | 254 | } |
| 78 | } | 255 | } |
| 256 | |||
| 257 | impl<T: iso14443_3::Card> Card for IsoDep<T> { | ||
| 258 | type Error = Error<T::Error>; | ||
| 259 | |||
| 260 | async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | ||
| 261 | if self.deselected { | ||
| 262 | return Err(Error::Deselected); | ||
| 263 | } | ||
| 264 | |||
| 265 | let mut temp = [0u8; 256]; | ||
| 266 | |||
| 267 | loop { | ||
| 268 | let n = self.nfc.receive(&mut temp).await.map_err(Error::Lower)?; | ||
| 269 | assert!(n != 0); | ||
| 270 | match temp[0] { | ||
| 271 | 0x02 | 0x03 => { | ||
| 272 | self.block_num ^= 0x01; | ||
| 273 | assert!(temp[0] == 0x02 | self.block_num); | ||
| 274 | buf[..n - 1].copy_from_slice(&temp[1..n]); | ||
| 275 | return Ok(n - 1); | ||
| 276 | } | ||
| 277 | 0xb2 | 0xb3 => { | ||
| 278 | if temp[0] & 0x01 != self.block_num { | ||
| 279 | info!("Got NAK, transmitting ACK."); | ||
| 280 | let resp = &[0xA2 | self.block_num]; | ||
| 281 | self.nfc.transmit(resp).await.map_err(Error::Lower)?; | ||
| 282 | } else { | ||
| 283 | info!("Got NAK, retransmitting."); | ||
| 284 | let resp: &[u8] = &self.resp[..self.resp_len]; | ||
| 285 | self.nfc.transmit(resp).await.map_err(Error::Lower)?; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | 0xe0 => { | ||
| 289 | info!("Got RATS, tx'ing ATS"); | ||
| 290 | let resp = &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80]; | ||
| 291 | self.nfc.transmit(resp).await.map_err(Error::Lower)?; | ||
| 292 | } | ||
| 293 | 0xc2 => { | ||
| 294 | info!("Got deselect!"); | ||
| 295 | self.deselected = true; | ||
| 296 | let resp = &[0xC2]; | ||
| 297 | self.nfc.transmit(resp).await.map_err(Error::Lower)?; | ||
| 298 | return Err(Error::Deselected); | ||
| 299 | } | ||
| 300 | _ => { | ||
| 301 | info!("Got unknown command {:02x}!", temp[0]); | ||
| 302 | return Err(Error::Protocol); | ||
| 303 | } | ||
| 304 | }; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error> { | ||
| 309 | if self.deselected { | ||
| 310 | return Err(Error::Deselected); | ||
| 311 | } | ||
| 312 | |||
| 313 | self.resp[0] = 0x02 | self.block_num; | ||
| 314 | self.resp[1..][..buf.len()].copy_from_slice(buf); | ||
| 315 | self.resp_len = 1 + buf.len(); | ||
| 316 | |||
| 317 | let resp: &[u8] = &self.resp[..self.resp_len]; | ||
| 318 | self.nfc.transmit(resp).await.map_err(Error::Lower)?; | ||
| 319 | |||
| 320 | Ok(()) | ||
| 321 | } | ||
| 322 | } | ||
| 79 | } | 323 | } |
diff --git a/examples/nrf52840/src/bin/pubsub.rs b/examples/nrf52840/src/bin/pubsub.rs index 5ebea9220..c0392b18c 100644 --- a/examples/nrf52840/src/bin/pubsub.rs +++ b/examples/nrf52840/src/bin/pubsub.rs | |||
| @@ -26,9 +26,9 @@ async fn main(spawner: Spawner) { | |||
| 26 | // It's good to set up the subscribers before publishing anything. | 26 | // It's good to set up the subscribers before publishing anything. |
| 27 | // A subscriber will only yield messages that have been published after its creation. | 27 | // A subscriber will only yield messages that have been published after its creation. |
| 28 | 28 | ||
| 29 | spawner.must_spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber()))); | 29 | spawner.spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber())).unwrap()); |
| 30 | spawner.must_spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber()))); | 30 | spawner.spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap()); |
| 31 | spawner.must_spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber()))); | 31 | spawner.spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap()); |
| 32 | 32 | ||
| 33 | // Get a publisher | 33 | // Get a publisher |
| 34 | let message_publisher = unwrap!(MESSAGE_BUS.publisher()); | 34 | let message_publisher = unwrap!(MESSAGE_BUS.publisher()); |
diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs index 717b0faa6..b80954408 100644 --- a/examples/nrf52840/src/bin/raw_spawn.rs +++ b/examples/nrf52840/src/bin/raw_spawn.rs | |||
| @@ -42,8 +42,8 @@ fn main() -> ! { | |||
| 42 | let run2_task = unsafe { make_static(&run2_task) }; | 42 | let run2_task = unsafe { make_static(&run2_task) }; |
| 43 | 43 | ||
| 44 | executor.run(|spawner| { | 44 | executor.run(|spawner| { |
| 45 | unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); | 45 | spawner.spawn(unwrap!(run1_task.spawn(|| run1()))); |
| 46 | unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); | 46 | spawner.spawn(unwrap!(run2_task.spawn(|| run2()))); |
| 47 | }); | 47 | }); |
| 48 | } | 48 | } |
| 49 | 49 | ||
diff --git a/examples/nrf52840/src/bin/rng.rs b/examples/nrf52840/src/bin/rng.rs index 326054c9a..f32d17cd9 100644..100755 --- a/examples/nrf52840/src/bin/rng.rs +++ b/examples/nrf52840/src/bin/rng.rs | |||
| @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 22 | defmt::info!("Some random bytes: {:?}", bytes); | 22 | defmt::info!("Some random bytes: {:?}", bytes); |
| 23 | 23 | ||
| 24 | // Sync API with `rand` | 24 | // Sync API with `rand` |
| 25 | defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); | 25 | defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10)); |
| 26 | 26 | ||
| 27 | let mut bytes = [0; 1024]; | 27 | let mut bytes = [0; 1024]; |
| 28 | rng.fill_bytes(&mut bytes).await; | 28 | rng.fill_bytes(&mut bytes).await; |
diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs index 5bfefc2af..acb44f98b 100644 --- a/examples/nrf52840/src/bin/self_spawn.rs +++ b/examples/nrf52840/src/bin/self_spawn.rs | |||
| @@ -14,12 +14,12 @@ mod config { | |||
| 14 | async fn my_task(spawner: Spawner, n: u32) { | 14 | async fn my_task(spawner: Spawner, n: u32) { |
| 15 | Timer::after_secs(1).await; | 15 | Timer::after_secs(1).await; |
| 16 | info!("Spawning self! {}", n); | 16 | info!("Spawning self! {}", n); |
| 17 | unwrap!(spawner.spawn(my_task(spawner, n + 1))); | 17 | spawner.spawn(unwrap!(my_task(spawner, n + 1))); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 21 | async fn main(spawner: Spawner) { | 21 | async fn main(spawner: Spawner) { |
| 22 | let _p = embassy_nrf::init(Default::default()); | 22 | let _p = embassy_nrf::init(Default::default()); |
| 23 | info!("Hello World!"); | 23 | info!("Hello World!"); |
| 24 | unwrap!(spawner.spawn(my_task(spawner, 0))); | 24 | spawner.spawn(unwrap!(my_task(spawner, 0))); |
| 25 | } | 25 | } |
diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs index ec9569a64..d93067592 100644 --- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs +++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs | |||
| @@ -10,12 +10,13 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 10 | async fn my_task(n: u32) { | 10 | async fn my_task(n: u32) { |
| 11 | Timer::after_secs(1).await; | 11 | Timer::after_secs(1).await; |
| 12 | info!("Spawning self! {}", n); | 12 | info!("Spawning self! {}", n); |
| 13 | unwrap!(Spawner::for_current_executor().await.spawn(my_task(n + 1))); | 13 | let spawner = unsafe { Spawner::for_current_executor().await }; |
| 14 | spawner.spawn(unwrap!(my_task(n + 1))); | ||
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
| 17 | async fn main(spawner: Spawner) { | 18 | async fn main(spawner: Spawner) { |
| 18 | let _p = embassy_nrf::init(Default::default()); | 19 | let _p = embassy_nrf::init(Default::default()); |
| 19 | info!("Hello World!"); | 20 | info!("Hello World!"); |
| 20 | unwrap!(spawner.spawn(my_task(0))); | 21 | spawner.spawn(unwrap!(my_task(0))); |
| 21 | } | 22 | } |
diff --git a/examples/nrf52840/src/bin/sixlowpan.rs b/examples/nrf52840/src/bin/sixlowpan.rs new file mode 100644 index 000000000..00a597366 --- /dev/null +++ b/examples/nrf52840/src/bin/sixlowpan.rs | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::net::Ipv6Addr; | ||
| 5 | |||
| 6 | use defmt::{info, unwrap, warn}; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_net::udp::{PacketMetadata, UdpMetadata, UdpSocket}; | ||
| 9 | use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint, Ipv6Cidr, StackResources, StaticConfigV6}; | ||
| 10 | use embassy_nrf::config::{Config, HfclkSource}; | ||
| 11 | use embassy_nrf::rng::Rng; | ||
| 12 | use embassy_nrf::{bind_interrupts, embassy_net_802154_driver as net, peripherals, radio}; | ||
| 13 | use embassy_time::Delay; | ||
| 14 | use embedded_hal_async::delay::DelayNs; | ||
| 15 | use static_cell::StaticCell; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | RADIO => radio::InterruptHandler<peripherals::RADIO>; | ||
| 20 | RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>; | ||
| 21 | }); | ||
| 22 | |||
| 23 | #[embassy_executor::task] | ||
| 24 | async fn ieee802154_task(runner: net::Runner<'static, peripherals::RADIO>) -> ! { | ||
| 25 | runner.run().await | ||
| 26 | } | ||
| 27 | |||
| 28 | #[embassy_executor::task] | ||
| 29 | async fn net_task(mut runner: embassy_net::Runner<'static, net::Device<'static>>) -> ! { | ||
| 30 | runner.run().await | ||
| 31 | } | ||
| 32 | |||
| 33 | #[embassy_executor::main] | ||
| 34 | async fn main(spawner: Spawner) { | ||
| 35 | let mut config = Config::default(); | ||
| 36 | // Necessary to run the radio nrf52840 v1.11 5.4.1 | ||
| 37 | config.hfclk_source = HfclkSource::ExternalXtal; | ||
| 38 | let p = embassy_nrf::init(config); | ||
| 39 | |||
| 40 | let mac_addr: [u8; 8] = [2, 3, 4, 5, 6, 7, 8, 9]; | ||
| 41 | static NRF802154_STATE: StaticCell<net::State<20, 20>> = StaticCell::new(); | ||
| 42 | let (device, runner) = net::new(mac_addr, p.RADIO, Irqs, NRF802154_STATE.init(net::State::new())) | ||
| 43 | .await | ||
| 44 | .unwrap(); | ||
| 45 | |||
| 46 | spawner.spawn(unwrap!(ieee802154_task(runner))); | ||
| 47 | |||
| 48 | // Swap these when flashing a second board | ||
| 49 | let peer = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a4); | ||
| 50 | let local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a5); | ||
| 51 | |||
| 52 | let config = embassy_net::Config::ipv6_static(StaticConfigV6 { | ||
| 53 | address: Ipv6Cidr::new(local, 64), | ||
| 54 | gateway: None, | ||
| 55 | dns_servers: Default::default(), | ||
| 56 | }); | ||
| 57 | |||
| 58 | // Generate random seed | ||
| 59 | let mut rng = Rng::new(p.RNG, Irqs); | ||
| 60 | let mut seed = [0; 8]; | ||
| 61 | rng.blocking_fill_bytes(&mut seed); | ||
| 62 | let seed = u64::from_le_bytes(seed); | ||
| 63 | |||
| 64 | // Init network stack | ||
| 65 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 66 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | ||
| 67 | |||
| 68 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 69 | |||
| 70 | let mut rx_buffer = [0; 2096]; | ||
| 71 | let mut tx_buffer = [0; 2096]; | ||
| 72 | let mut tx_m_buffer = [PacketMetadata::EMPTY; 5]; | ||
| 73 | let mut rx_m_buffer = [PacketMetadata::EMPTY; 5]; | ||
| 74 | |||
| 75 | let mut delay = Delay; | ||
| 76 | loop { | ||
| 77 | let mut socket = UdpSocket::new( | ||
| 78 | stack, | ||
| 79 | &mut tx_m_buffer, | ||
| 80 | &mut rx_buffer, | ||
| 81 | &mut rx_m_buffer, | ||
| 82 | &mut tx_buffer, | ||
| 83 | ); | ||
| 84 | socket | ||
| 85 | .bind(IpListenEndpoint { | ||
| 86 | addr: Some(IpAddress::Ipv6(local)), | ||
| 87 | port: 1234, | ||
| 88 | }) | ||
| 89 | .unwrap(); | ||
| 90 | let rep = UdpMetadata { | ||
| 91 | endpoint: IpEndpoint { | ||
| 92 | addr: IpAddress::Ipv6(peer), | ||
| 93 | port: 1234, | ||
| 94 | }, | ||
| 95 | local_address: Some(IpAddress::Ipv6(local)), | ||
| 96 | meta: Default::default(), | ||
| 97 | }; | ||
| 98 | |||
| 99 | info!("Listening on {:?} UDP:1234...", local); | ||
| 100 | |||
| 101 | let mut recv_buf = [0; 12]; | ||
| 102 | loop { | ||
| 103 | delay.delay_ms(2000).await; | ||
| 104 | if socket.may_recv() { | ||
| 105 | let n = match socket.recv_from(&mut recv_buf).await { | ||
| 106 | Ok((0, _)) => panic!(), | ||
| 107 | Ok((n, _)) => n, | ||
| 108 | Err(e) => { | ||
| 109 | warn!("read error: {:?}", e); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | info!("Received {:02x}", &recv_buf[..n]); | ||
| 114 | } | ||
| 115 | |||
| 116 | info!("Sending"); | ||
| 117 | socket.send_to(b"Hello World", rep).await.unwrap(); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
diff --git a/examples/nrf52840/src/bin/timer.rs b/examples/nrf52840/src/bin/timer.rs index 365695a20..5331ac246 100644 --- a/examples/nrf52840/src/bin/timer.rs +++ b/examples/nrf52840/src/bin/timer.rs | |||
| @@ -25,6 +25,6 @@ async fn run2() { | |||
| 25 | #[embassy_executor::main] | 25 | #[embassy_executor::main] |
| 26 | async fn main(spawner: Spawner) { | 26 | async fn main(spawner: Spawner) { |
| 27 | let _p = embassy_nrf::init(Default::default()); | 27 | let _p = embassy_nrf::init(Default::default()); |
| 28 | unwrap!(spawner.spawn(run1())); | 28 | spawner.spawn(unwrap!(run1())); |
| 29 | unwrap!(spawner.spawn(run2())); | 29 | spawner.spawn(unwrap!(run2())); |
| 30 | } | 30 | } |
diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs index 46be8f636..51af90727 100644 --- a/examples/nrf52840/src/bin/uart_split.rs +++ b/examples/nrf52840/src/bin/uart_split.rs | |||
| @@ -30,7 +30,7 @@ async fn main(spawner: Spawner) { | |||
| 30 | 30 | ||
| 31 | // Spawn a task responsible purely for reading | 31 | // Spawn a task responsible purely for reading |
| 32 | 32 | ||
| 33 | unwrap!(spawner.spawn(reader(rx))); | 33 | spawner.spawn(unwrap!(reader(rx))); |
| 34 | 34 | ||
| 35 | // Message must be in SRAM | 35 | // Message must be in SRAM |
| 36 | { | 36 | { |
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index 49856012d..87aa4c6c5 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs | |||
| @@ -86,11 +86,11 @@ async fn main(spawner: Spawner) { | |||
| 86 | // Build the builder. | 86 | // Build the builder. |
| 87 | let usb = builder.build(); | 87 | let usb = builder.build(); |
| 88 | 88 | ||
| 89 | unwrap!(spawner.spawn(usb_task(usb))); | 89 | spawner.spawn(unwrap!(usb_task(usb))); |
| 90 | 90 | ||
| 91 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); | 91 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); |
| 92 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); | 92 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); |
| 93 | unwrap!(spawner.spawn(usb_ncm_task(runner))); | 93 | spawner.spawn(unwrap!(usb_ncm_task(runner))); |
| 94 | 94 | ||
| 95 | let config = embassy_net::Config::dhcpv4(Default::default()); | 95 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 96 | // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 96 | // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
| @@ -109,7 +109,7 @@ async fn main(spawner: Spawner) { | |||
| 109 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 109 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 110 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 110 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 111 | 111 | ||
| 112 | unwrap!(spawner.spawn(net_task(runner))); | 112 | spawner.spawn(unwrap!(net_task(runner))); |
| 113 | 113 | ||
| 114 | // And now we can use it! | 114 | // And now we can use it! |
| 115 | 115 | ||
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs index 5e5b4de35..00a91a233 100644 --- a/examples/nrf52840/src/bin/usb_serial_multitask.rs +++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs | |||
| @@ -76,8 +76,8 @@ async fn main(spawner: Spawner) { | |||
| 76 | // Build the builder. | 76 | // Build the builder. |
| 77 | let usb = builder.build(); | 77 | let usb = builder.build(); |
| 78 | 78 | ||
| 79 | unwrap!(spawner.spawn(usb_task(usb))); | 79 | spawner.spawn(unwrap!(usb_task(usb))); |
| 80 | unwrap!(spawner.spawn(echo_task(class))); | 80 | spawner.spawn(unwrap!(echo_task(class))); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | struct Disconnected {} | 83 | struct Disconnected {} |
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 26eaf485e..2dd9abfaa 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs | |||
| @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { | |||
| 70 | ) | 70 | ) |
| 71 | .await; | 71 | .await; |
| 72 | 72 | ||
| 73 | unwrap!(spawner.spawn(wifi_task(runner))); | 73 | spawner.spawn(unwrap!(wifi_task(runner))); |
| 74 | 74 | ||
| 75 | unwrap!(control.init().await); | 75 | unwrap!(control.init().await); |
| 76 | unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await); | 76 | unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await); |
| @@ -92,7 +92,7 @@ async fn main(spawner: Spawner) { | |||
| 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 94 | 94 | ||
| 95 | unwrap!(spawner.spawn(net_task(runner))); | 95 | spawner.spawn(unwrap!(net_task(runner))); |
| 96 | 96 | ||
| 97 | // And now we can use it! | 97 | // And now we can use it! |
| 98 | 98 | ||
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 459c43221..425015667 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml | |||
| @@ -3,28 +3,33 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf5340-examples" | 3 | name = "embassy-nrf5340-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 9 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 13 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embedded-io-async = { version = "0.6.1" } | 16 | embedded-io-async = { version = "0.6.1" } |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "1.0.1" |
| 18 | defmt-rtt = "0.4" | 19 | defmt-rtt = "1.0.0" |
| 19 | 20 | ||
| 20 | static_cell = "2" | 21 | static_cell = "2" |
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 24 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 24 | rand = { version = "0.8.4", default-features = false } | ||
| 25 | embedded-storage = "0.3.1" | 25 | embedded-storage = "0.3.1" |
| 26 | usbd-hid = "0.8.1" | 26 | usbd-hid = "0.8.1" |
| 27 | serde = { version = "1.0.136", default-features = false } | 27 | serde = { version = "1.0.136", default-features = false } |
| 28 | 28 | ||
| 29 | [profile.release] | 29 | [profile.release] |
| 30 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf5340" } | ||
| 35 | ] | ||
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 8848065d8..7f67b41f6 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml | |||
| @@ -3,18 +3,26 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf54l15-examples" | 3 | name = "embassy-nrf54l15-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 9 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 11 | 12 | ||
| 12 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.4" | 14 | defmt-rtt = "1.0.0" |
| 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 15 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 15 | 16 | ||
| 16 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 17 | cortex-m-rt = "0.7.0" | 18 | cortex-m-rt = "0.7.0" |
| 18 | 19 | ||
| 20 | embedded-storage = "0.3.1" | ||
| 21 | |||
| 19 | [profile.release] | 22 | [profile.release] |
| 20 | debug = 2 | 23 | debug = 2 |
| 24 | |||
| 25 | [package.metadata.embassy] | ||
| 26 | build = [ | ||
| 27 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf54l15" } | ||
| 28 | ] | ||
diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/nvmc.rs new file mode 100644 index 000000000..f990604cd --- /dev/null +++ b/examples/nrf54l15/src/bin/nvmc.rs | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE}; | ||
| 7 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | info!("Hello RRAMC NVMC!"); | ||
| 14 | |||
| 15 | let mut f = Nvmc::new(p.RRAMC); | ||
| 16 | |||
| 17 | const ADDR: u32 = 0x80000; | ||
| 18 | let mut buf = [0u8; 4]; | ||
| 19 | |||
| 20 | info!("Reading..."); | ||
| 21 | unwrap!(f.read(ADDR, &mut buf)); | ||
| 22 | info!("Read: {=[u8]:x}", buf); | ||
| 23 | |||
| 24 | info!("Erasing..."); | ||
| 25 | unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32)); | ||
| 26 | |||
| 27 | info!("Reading..."); | ||
| 28 | unwrap!(f.read(ADDR, &mut buf)); | ||
| 29 | info!("Read: {=[u8]:x}", buf); | ||
| 30 | |||
| 31 | info!("Writing..."); | ||
| 32 | // 16 B (128-bit) write minimum | ||
| 33 | let out: [u8; 16] = [ | ||
| 34 | 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, | ||
| 35 | ]; | ||
| 36 | unwrap!(f.write(ADDR, &out)); | ||
| 37 | |||
| 38 | info!("Reading..."); | ||
| 39 | // Can read arbitrary sizes | ||
| 40 | for addr in (ADDR..ADDR + 16).step_by(4) { | ||
| 41 | unwrap!(f.read(addr, &mut buf)); | ||
| 42 | info!("Read: {=[u8]:x}", buf); | ||
| 43 | } | ||
| 44 | } | ||
diff --git a/examples/nrf54l15/src/bin/temp.rs b/examples/nrf54l15/src/bin/temp.rs new file mode 100644 index 000000000..1d28f8ecf --- /dev/null +++ b/examples/nrf54l15/src/bin/temp.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::temp::Temp; | ||
| 7 | use embassy_nrf::{bind_interrupts, temp}; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | TEMP => temp::InterruptHandler; | ||
| 13 | }); | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) { | ||
| 17 | let p = embassy_nrf::init(Default::default()); | ||
| 18 | let mut temp = Temp::new(p.TEMP, Irqs); | ||
| 19 | |||
| 20 | loop { | ||
| 21 | let value = temp.read().await; | ||
| 22 | info!("temperature: {}℃", value.to_num::<u16>()); | ||
| 23 | Timer::after_secs(1).await; | ||
| 24 | } | ||
| 25 | } | ||
diff --git a/examples/nrf54l15/src/bin/wdt.rs b/examples/nrf54l15/src/bin/wdt.rs new file mode 100644 index 000000000..9fe37d080 --- /dev/null +++ b/examples/nrf54l15/src/bin/wdt.rs | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::wdt::{Config, HaltConfig, Watchdog}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | info!("Hello WDT"); | ||
| 14 | |||
| 15 | const TIMEOUT_S: u32 = 5; | ||
| 16 | |||
| 17 | let mut config = Config::default(); | ||
| 18 | config.timeout_ticks = 32768 * TIMEOUT_S; | ||
| 19 | |||
| 20 | // This is needed for `probe-rs run` to be able to catch the panic message | ||
| 21 | // in the WDT interrupt. The core resets 2 ticks after firing the interrupt. | ||
| 22 | config.action_during_debug_halt = HaltConfig::PAUSE; | ||
| 23 | |||
| 24 | // The nrf54l15 has two watchdogs. Only one (WDT) is available in non-secure (ns) mode, as the | ||
| 25 | // other is reserved for the secure (s) environment. In secure mode, both are available as WDT0 | ||
| 26 | // and WDT1. | ||
| 27 | info!("Watchdog launched with {} s timeout", TIMEOUT_S); | ||
| 28 | let (_wdt, [mut handle]) = match Watchdog::try_new(p.WDT1, config) { | ||
| 29 | Ok(x) => x, | ||
| 30 | Err(_) => { | ||
| 31 | info!("Watchdog already active with wrong config, waiting for it to timeout..."); | ||
| 32 | loop {} | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | for wait in 1..=TIMEOUT_S { | ||
| 37 | info!("Waiting {} seconds ...", wait); | ||
| 38 | Timer::after_secs(wait as u64).await; | ||
| 39 | handle.pet(); | ||
| 40 | info!("Pet watchdog"); | ||
| 41 | } | ||
| 42 | } | ||
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 03f38fd63..8e420477f 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml | |||
| @@ -3,18 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf9151-non-secure-examples" | 3 | name = "embassy-nrf9151-non-secure-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 9 | embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 11 | 12 | ||
| 12 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.4" | 14 | defmt-rtt = "1.0.0" |
| 14 | 15 | ||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 16 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 16 | cortex-m-rt = "0.7.0" | 17 | cortex-m-rt = "0.7.0" |
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | 19 | ||
| 19 | [profile.release] | 20 | [profile.release] |
| 20 | debug = 2 | 21 | debug = 2 |
| 22 | |||
| 23 | [package.metadata.embassy] | ||
| 24 | build = [ | ||
| 25 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/ns" } | ||
| 26 | ] | ||
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index ba88f6da3..e4ca85553 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml | |||
| @@ -3,18 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf9151-secure-examples" | 3 | name = "embassy-nrf9151-secure-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 9 | embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 11 | 12 | ||
| 12 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.4" | 14 | defmt-rtt = "1.0.0" |
| 14 | 15 | ||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 16 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 16 | cortex-m-rt = "0.7.0" | 17 | cortex-m-rt = "0.7.0" |
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 18 | 19 | ||
| 19 | [profile.release] | 20 | [profile.release] |
| 20 | debug = 2 | 21 | debug = 2 |
| 22 | |||
| 23 | [package.metadata.embassy] | ||
| 24 | build = [ | ||
| 25 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/s" } | ||
| 26 | ] | ||
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index a720f2d61..d7b63a7ac 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml | |||
| @@ -3,24 +3,30 @@ edition = "2021" | |||
| 3 | name = "embassy-nrf9160-examples" | 3 | name = "embassy-nrf9160-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 9 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 11 | embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } | 12 | embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } |
| 12 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } | 13 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } |
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "1.0.0" |
| 16 | 17 | ||
| 17 | heapless = "0.8" | 18 | heapless = "0.8" |
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | static_cell = { version = "2" } | 22 | static_cell = { version = "2" } |
| 22 | embedded-io = "0.6.1" | 23 | embedded-io = "0.6.1" |
| 23 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | 24 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } |
| 24 | 25 | ||
| 25 | [profile.release] | 26 | [profile.release] |
| 26 | debug = 2 | 27 | debug = 2 |
| 28 | |||
| 29 | [package.metadata.embassy] | ||
| 30 | build = [ | ||
| 31 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9160" } | ||
| 32 | ] | ||
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index a36b14626..7d4815699 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -112,7 +112,7 @@ async fn main(spawner: Spawner) { | |||
| 112 | 112 | ||
| 113 | info!("Hello World!"); | 113 | info!("Hello World!"); |
| 114 | 114 | ||
| 115 | unwrap!(spawner.spawn(blink_task(p.P0_02.into()))); | 115 | spawner.spawn(unwrap!(blink_task(p.P0_02.into()))); |
| 116 | 116 | ||
| 117 | let ipc_mem = unsafe { | 117 | let ipc_mem = unsafe { |
| 118 | let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit<u8>; | 118 | let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit<u8>; |
| @@ -138,8 +138,8 @@ async fn main(spawner: Spawner) { | |||
| 138 | static TRACE: StaticCell<TraceBuffer> = StaticCell::new(); | 138 | static TRACE: StaticCell<TraceBuffer> = StaticCell::new(); |
| 139 | let (device, control, runner, tracer) = | 139 | let (device, control, runner, tracer) = |
| 140 | embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; | 140 | embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; |
| 141 | unwrap!(spawner.spawn(modem_task(runner))); | 141 | spawner.spawn(unwrap!(modem_task(runner))); |
| 142 | unwrap!(spawner.spawn(trace_task(uart, tracer))); | 142 | spawner.spawn(unwrap!(trace_task(uart, tracer))); |
| 143 | 143 | ||
| 144 | let config = embassy_net::Config::default(); | 144 | let config = embassy_net::Config::default(); |
| 145 | 145 | ||
| @@ -150,12 +150,12 @@ async fn main(spawner: Spawner) { | |||
| 150 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 150 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); |
| 151 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed); | 151 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed); |
| 152 | 152 | ||
| 153 | unwrap!(spawner.spawn(net_task(runner))); | 153 | spawner.spawn(unwrap!(net_task(runner))); |
| 154 | 154 | ||
| 155 | static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); | 155 | static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); |
| 156 | let control = CONTROL.init(context::Control::new(control, 0).await); | 156 | let control = CONTROL.init(context::Control::new(control, 0).await); |
| 157 | 157 | ||
| 158 | unwrap!(spawner.spawn(control_task( | 158 | spawner.spawn(unwrap!(control_task( |
| 159 | control, | 159 | control, |
| 160 | context::Config { | 160 | context::Config { |
| 161 | apn: b"iot.nat.es", | 161 | apn: b"iot.nat.es", |
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 45ca30e4c..97e019cdf 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -4,23 +4,24 @@ name = "embassy-rp-examples" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } | 10 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } | 14 | embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } | 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } |
| 16 | embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 18 | embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } | 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } |
| 19 | cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } | 20 | cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } |
| 20 | cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } | 21 | cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } |
| 21 | 22 | ||
| 22 | defmt = "0.3" | 23 | defmt = "1.0.1" |
| 23 | defmt-rtt = "0.4" | 24 | defmt-rtt = "1.0.0" |
| 24 | fixed = "1.23.1" | 25 | fixed = "1.23.1" |
| 25 | fixed-macro = "1.2" | 26 | fixed-macro = "1.2" |
| 26 | 27 | ||
| @@ -36,7 +37,7 @@ assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev | |||
| 36 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | 37 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } |
| 37 | cortex-m-rt = "0.7.0" | 38 | cortex-m-rt = "0.7.0" |
| 38 | critical-section = "1.1" | 39 | critical-section = "1.1" |
| 39 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 40 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 40 | display-interface-spi = "0.5.0" | 41 | display-interface-spi = "0.5.0" |
| 41 | embedded-graphics = "0.8.1" | 42 | embedded-graphics = "0.8.1" |
| 42 | mipidsi = "0.8.0" | 43 | mipidsi = "0.8.0" |
| @@ -45,7 +46,6 @@ byte-slice-cast = { version = "1.2.0", default-features = false } | |||
| 45 | smart-leds = "0.4.0" | 46 | smart-leds = "0.4.0" |
| 46 | heapless = "0.8" | 47 | heapless = "0.8" |
| 47 | usbd-hid = "0.8.1" | 48 | usbd-hid = "0.8.1" |
| 48 | rand_core = "0.6.4" | ||
| 49 | 49 | ||
| 50 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 50 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 51 | embedded-hal-async = "1.0" | 51 | embedded-hal-async = "1.0" |
| @@ -55,15 +55,14 @@ embedded-storage = { version = "0.3" } | |||
| 55 | static_cell = "2.1" | 55 | static_cell = "2.1" |
| 56 | portable-atomic = { version = "1.5", features = ["critical-section"] } | 56 | portable-atomic = { version = "1.5", features = ["critical-section"] } |
| 57 | log = "0.4" | 57 | log = "0.4" |
| 58 | rand = { version = "0.8.5", default-features = false } | 58 | rand = { version = "0.9.0", default-features = false } |
| 59 | embedded-sdmmc = "0.7.0" | 59 | embedded-sdmmc = "0.7.0" |
| 60 | 60 | ||
| 61 | [profile.release] | 61 | [profile.release] |
| 62 | debug = 2 | 62 | # Enable generation of debug symbols even on release builds |
| 63 | lto = true | 63 | debug = true |
| 64 | opt-level = 'z' | ||
| 65 | 64 | ||
| 66 | [profile.dev] | 65 | [package.metadata.embassy] |
| 67 | debug = 2 | 66 | build = [ |
| 68 | lto = true | 67 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/rp" } |
| 69 | opt-level = "z" | 68 | ] |
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 1bb7c2249..015915586 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs | |||
| @@ -12,9 +12,12 @@ use embassy_rp::gpio::Pull; | |||
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!( |
| 16 | ADC_IRQ_FIFO => InterruptHandler; | 16 | /// Binds the ADC interrupts. |
| 17 | }); | 17 | struct Irqs { |
| 18 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 19 | } | ||
| 20 | ); | ||
| 18 | 21 | ||
| 19 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 20 | async fn main(_spawner: Spawner) { | 23 | async fn main(_spawner: Spawner) { |
diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs index 341f54d22..4ee4278b5 100644 --- a/examples/rp/src/bin/assign_resources.rs +++ b/examples/rp/src/bin/assign_resources.rs | |||
| @@ -26,15 +26,13 @@ async fn main(spawner: Spawner) { | |||
| 26 | let p = embassy_rp::init(Default::default()); | 26 | let p = embassy_rp::init(Default::default()); |
| 27 | 27 | ||
| 28 | // 1) Assigning a resource to a task by passing parts of the peripherals. | 28 | // 1) Assigning a resource to a task by passing parts of the peripherals. |
| 29 | spawner | 29 | spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap()); |
| 30 | .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) | ||
| 31 | .unwrap(); | ||
| 32 | 30 | ||
| 33 | // 2) Using the assign-resources macro to assign resources to a task. | 31 | // 2) Using the assign-resources macro to assign resources to a task. |
| 34 | // we perform the split, see further below for the definition of the resources struct | 32 | // we perform the split, see further below for the definition of the resources struct |
| 35 | let r = split_resources!(p); | 33 | let r = split_resources!(p); |
| 36 | // and then we can use them | 34 | // and then we can use them |
| 37 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); | 35 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap()); |
| 38 | } | 36 | } |
| 39 | 37 | ||
| 40 | // 1) Assigning a resource to a task by passing parts of the peripherals. | 38 | // 1) Assigning a resource to a task by passing parts of the peripherals. |
diff --git a/examples/rp/src/bin/blinky_two_channels.rs b/examples/rp/src/bin/blinky_two_channels.rs index 51e139e94..87f3a3545 100644 --- a/examples/rp/src/bin/blinky_two_channels.rs +++ b/examples/rp/src/bin/blinky_two_channels.rs | |||
| @@ -27,8 +27,8 @@ async fn main(spawner: Spawner) { | |||
| 27 | let dt = 100 * 1_000_000; | 27 | let dt = 100 * 1_000_000; |
| 28 | let k = 1.003; | 28 | let k = 1.003; |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); | 30 | spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); |
| 31 | unwrap!(spawner.spawn(toggle_led( | 31 | spawner.spawn(unwrap!(toggle_led( |
| 32 | CHANNEL.sender(), | 32 | CHANNEL.sender(), |
| 33 | Duration::from_nanos((dt as f64 * k) as u64) | 33 | Duration::from_nanos((dt as f64 * k) as u64) |
| 34 | ))); | 34 | ))); |
diff --git a/examples/rp/src/bin/blinky_two_tasks.rs b/examples/rp/src/bin/blinky_two_tasks.rs index 67a9108c0..aac7d928b 100644 --- a/examples/rp/src/bin/blinky_two_tasks.rs +++ b/examples/rp/src/bin/blinky_two_tasks.rs | |||
| @@ -30,8 +30,8 @@ async fn main(spawner: Spawner) { | |||
| 30 | let dt = 100 * 1_000_000; | 30 | let dt = 100 * 1_000_000; |
| 31 | let k = 1.003; | 31 | let k = 1.003; |
| 32 | 32 | ||
| 33 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); | 33 | spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt)))); |
| 34 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); | 34 | spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | #[embassy_executor::task(pool_size = 2)] | 37 | #[embassy_executor::task(pool_size = 2)] |
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp.rs b/examples/rp/src/bin/ethernet_w5500_icmp.rs index 5c42b2dde..8c684a791 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp.rs | |||
| @@ -21,7 +21,6 @@ use embassy_rp::peripherals::SPI0; | |||
| 21 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 21 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 22 | use embassy_time::{Delay, Instant, Timer}; | 22 | use embassy_time::{Delay, Instant, Timer}; |
| 23 | use embedded_hal_bus::spi::ExclusiveDevice; | 23 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 24 | use rand::RngCore; | ||
| 25 | use static_cell::StaticCell; | 24 | use static_cell::StaticCell; |
| 26 | use {defmt_rtt as _, panic_probe as _}; | 25 | use {defmt_rtt as _, panic_probe as _}; |
| 27 | 26 | ||
| @@ -62,7 +61,7 @@ async fn main(spawner: Spawner) { | |||
| 62 | ) | 61 | ) |
| 63 | .await | 62 | .await |
| 64 | .unwrap(); | 63 | .unwrap(); |
| 65 | unwrap!(spawner.spawn(ethernet_task(runner))); | 64 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 66 | 65 | ||
| 67 | // Generate random seed | 66 | // Generate random seed |
| 68 | let seed = rng.next_u64(); | 67 | let seed = rng.next_u64(); |
| @@ -77,7 +76,7 @@ async fn main(spawner: Spawner) { | |||
| 77 | ); | 76 | ); |
| 78 | 77 | ||
| 79 | // Launch network task | 78 | // Launch network task |
| 80 | unwrap!(spawner.spawn(net_task(runner))); | 79 | spawner.spawn(unwrap!(net_task(runner))); |
| 81 | 80 | ||
| 82 | info!("Waiting for DHCP..."); | 81 | info!("Waiting for DHCP..."); |
| 83 | let cfg = wait_for_config(stack).await; | 82 | let cfg = wait_for_config(stack).await; |
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs index 0724311f9..49d28071a 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs | |||
| @@ -23,7 +23,6 @@ use embassy_rp::peripherals::SPI0; | |||
| 23 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 23 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 24 | use embassy_time::{Delay, Duration}; | 24 | use embassy_time::{Delay, Duration}; |
| 25 | use embedded_hal_bus::spi::ExclusiveDevice; | 25 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 26 | use rand::RngCore; | ||
| 27 | use static_cell::StaticCell; | 26 | use static_cell::StaticCell; |
| 28 | use {defmt_rtt as _, panic_probe as _}; | 27 | use {defmt_rtt as _, panic_probe as _}; |
| 29 | 28 | ||
| @@ -64,7 +63,7 @@ async fn main(spawner: Spawner) { | |||
| 64 | ) | 63 | ) |
| 65 | .await | 64 | .await |
| 66 | .unwrap(); | 65 | .unwrap(); |
| 67 | unwrap!(spawner.spawn(ethernet_task(runner))); | 66 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 68 | 67 | ||
| 69 | // Generate random seed | 68 | // Generate random seed |
| 70 | let seed = rng.next_u64(); | 69 | let seed = rng.next_u64(); |
| @@ -79,7 +78,7 @@ async fn main(spawner: Spawner) { | |||
| 79 | ); | 78 | ); |
| 80 | 79 | ||
| 81 | // Launch network task | 80 | // Launch network task |
| 82 | unwrap!(spawner.spawn(net_task(runner))); | 81 | spawner.spawn(unwrap!(net_task(runner))); |
| 83 | 82 | ||
| 84 | info!("Waiting for DHCP..."); | 83 | info!("Waiting for DHCP..."); |
| 85 | let cfg = wait_for_config(stack).await; | 84 | let cfg = wait_for_config(stack).await; |
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 2bea9fc9d..5c049ddca 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs | |||
| @@ -18,7 +18,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | |||
| 18 | use embassy_time::{Delay, Duration}; | 18 | use embassy_time::{Delay, Duration}; |
| 19 | use embedded_hal_bus::spi::ExclusiveDevice; | 19 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 20 | use embedded_io_async::Write; | 20 | use embedded_io_async::Write; |
| 21 | use rand::RngCore; | ||
| 22 | use static_cell::StaticCell; | 21 | use static_cell::StaticCell; |
| 23 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
| 24 | 23 | ||
| @@ -65,7 +64,7 @@ async fn main(spawner: Spawner) { | |||
| 65 | ) | 64 | ) |
| 66 | .await | 65 | .await |
| 67 | .unwrap(); | 66 | .unwrap(); |
| 68 | unwrap!(spawner.spawn(ethernet_task(runner))); | 67 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 69 | 68 | ||
| 70 | // Generate random seed | 69 | // Generate random seed |
| 71 | let seed = rng.next_u64(); | 70 | let seed = rng.next_u64(); |
| @@ -80,7 +79,7 @@ async fn main(spawner: Spawner) { | |||
| 80 | ); | 79 | ); |
| 81 | 80 | ||
| 82 | // Launch network task | 81 | // Launch network task |
| 83 | unwrap!(spawner.spawn(net_task(runner))); | 82 | spawner.spawn(unwrap!(net_task(runner))); |
| 84 | 83 | ||
| 85 | info!("Waiting for DHCP..."); | 84 | info!("Waiting for DHCP..."); |
| 86 | let cfg = wait_for_config(stack).await; | 85 | let cfg = wait_for_config(stack).await; |
| @@ -88,8 +87,8 @@ async fn main(spawner: Spawner) { | |||
| 88 | info!("IP address: {:?}", local_addr); | 87 | info!("IP address: {:?}", local_addr); |
| 89 | 88 | ||
| 90 | // Create two sockets listening to the same port, to handle simultaneous connections | 89 | // Create two sockets listening to the same port, to handle simultaneous connections |
| 91 | unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); | 90 | spawner.spawn(unwrap!(listen_task(stack, 0, 1234))); |
| 92 | unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); | 91 | spawner.spawn(unwrap!(listen_task(stack, 1, 1234))); |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | #[embassy_executor::task(pool_size = 2)] | 94 | #[embassy_executor::task(pool_size = 2)] |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 78d1b0b83..7552e4f9b 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs | |||
| @@ -20,7 +20,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | |||
| 20 | use embassy_time::{Delay, Duration, Timer}; | 20 | use embassy_time::{Delay, Duration, Timer}; |
| 21 | use embedded_hal_bus::spi::ExclusiveDevice; | 21 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 22 | use embedded_io_async::Write; | 22 | use embedded_io_async::Write; |
| 23 | use rand::RngCore; | ||
| 24 | use static_cell::StaticCell; | 23 | use static_cell::StaticCell; |
| 25 | use {defmt_rtt as _, panic_probe as _}; | 24 | use {defmt_rtt as _, panic_probe as _}; |
| 26 | 25 | ||
| @@ -68,7 +67,7 @@ async fn main(spawner: Spawner) { | |||
| 68 | ) | 67 | ) |
| 69 | .await | 68 | .await |
| 70 | .unwrap(); | 69 | .unwrap(); |
| 71 | unwrap!(spawner.spawn(ethernet_task(runner))); | 70 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 72 | 71 | ||
| 73 | // Generate random seed | 72 | // Generate random seed |
| 74 | let seed = rng.next_u64(); | 73 | let seed = rng.next_u64(); |
| @@ -83,7 +82,7 @@ async fn main(spawner: Spawner) { | |||
| 83 | ); | 82 | ); |
| 84 | 83 | ||
| 85 | // Launch network task | 84 | // Launch network task |
| 86 | unwrap!(spawner.spawn(net_task(runner))); | 85 | spawner.spawn(unwrap!(net_task(runner))); |
| 87 | 86 | ||
| 88 | info!("Waiting for DHCP..."); | 87 | info!("Waiting for DHCP..."); |
| 89 | let cfg = wait_for_config(stack).await; | 88 | let cfg = wait_for_config(stack).await; |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 25a38c714..7b6fecad4 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs | |||
| @@ -19,7 +19,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | |||
| 19 | use embassy_time::{Delay, Duration}; | 19 | use embassy_time::{Delay, Duration}; |
| 20 | use embedded_hal_bus::spi::ExclusiveDevice; | 20 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 21 | use embedded_io_async::Write; | 21 | use embedded_io_async::Write; |
| 22 | use rand::RngCore; | ||
| 23 | use static_cell::StaticCell; | 22 | use static_cell::StaticCell; |
| 24 | use {defmt_rtt as _, panic_probe as _}; | 23 | use {defmt_rtt as _, panic_probe as _}; |
| 25 | 24 | ||
| @@ -67,7 +66,7 @@ async fn main(spawner: Spawner) { | |||
| 67 | ) | 66 | ) |
| 68 | .await | 67 | .await |
| 69 | .unwrap(); | 68 | .unwrap(); |
| 70 | unwrap!(spawner.spawn(ethernet_task(runner))); | 69 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 71 | 70 | ||
| 72 | // Generate random seed | 71 | // Generate random seed |
| 73 | let seed = rng.next_u64(); | 72 | let seed = rng.next_u64(); |
| @@ -82,7 +81,7 @@ async fn main(spawner: Spawner) { | |||
| 82 | ); | 81 | ); |
| 83 | 82 | ||
| 84 | // Launch network task | 83 | // Launch network task |
| 85 | unwrap!(spawner.spawn(net_task(runner))); | 84 | spawner.spawn(unwrap!(net_task(runner))); |
| 86 | 85 | ||
| 87 | info!("Waiting for DHCP..."); | 86 | info!("Waiting for DHCP..."); |
| 88 | let cfg = wait_for_config(stack).await; | 87 | let cfg = wait_for_config(stack).await; |
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 683e29222..f099490f5 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs | |||
| @@ -18,7 +18,6 @@ use embassy_rp::peripherals::SPI0; | |||
| 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 19 | use embassy_time::Delay; | 19 | use embassy_time::Delay; |
| 20 | use embedded_hal_bus::spi::ExclusiveDevice; | 20 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 21 | use rand::RngCore; | ||
| 22 | use static_cell::StaticCell; | 21 | use static_cell::StaticCell; |
| 23 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
| 24 | 23 | ||
| @@ -65,7 +64,7 @@ async fn main(spawner: Spawner) { | |||
| 65 | ) | 64 | ) |
| 66 | .await | 65 | .await |
| 67 | .unwrap(); | 66 | .unwrap(); |
| 68 | unwrap!(spawner.spawn(ethernet_task(runner))); | 67 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 69 | 68 | ||
| 70 | // Generate random seed | 69 | // Generate random seed |
| 71 | let seed = rng.next_u64(); | 70 | let seed = rng.next_u64(); |
| @@ -80,7 +79,7 @@ async fn main(spawner: Spawner) { | |||
| 80 | ); | 79 | ); |
| 81 | 80 | ||
| 82 | // Launch network task | 81 | // Launch network task |
| 83 | unwrap!(spawner.spawn(net_task(runner))); | 82 | spawner.spawn(unwrap!(net_task(runner))); |
| 84 | 83 | ||
| 85 | info!("Waiting for DHCP..."); | 84 | info!("Waiting for DHCP..."); |
| 86 | let cfg = wait_for_config(stack).await; | 85 | let cfg = wait_for_config(stack).await; |
diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs new file mode 100644 index 000000000..f51df2df9 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | //! This example implements a TCP echo server on port 1234 and using DHCP. | ||
| 2 | //! Send it some data, you should see it echoed back and printed in the console. | ||
| 3 | //! | ||
| 4 | //! Example written for the [`WIZnet W55RP20-EVB-Pico`](https://docs.wiznet.io/Product/ioNIC/W55RP20/w55rp20-evb-pico) board. | ||
| 5 | //! Note: the W55RP20 is a single package that contains both a RP2040 and the Wiznet W5500 ethernet | ||
| 6 | //! controller | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_futures::yield_now; | ||
| 14 | use embassy_net::{Stack, StackResources}; | ||
| 15 | use embassy_net_wiznet::chip::W5500; | ||
| 16 | use embassy_net_wiznet::*; | ||
| 17 | use embassy_rp::clocks::RoscRng; | ||
| 18 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 19 | use embassy_rp::peripherals::PIO0; | ||
| 20 | use embassy_rp::pio_programs::spi::Spi; | ||
| 21 | use embassy_rp::spi::{Async, Config as SpiConfig}; | ||
| 22 | use embassy_rp::{bind_interrupts, pio}; | ||
| 23 | use embassy_time::{Delay, Duration}; | ||
| 24 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 25 | use embedded_io_async::Write; | ||
| 26 | use static_cell::StaticCell; | ||
| 27 | use {defmt_rtt as _, panic_probe as _}; | ||
| 28 | |||
| 29 | bind_interrupts!(struct Irqs { | ||
| 30 | PIO0_IRQ_0 => pio::InterruptHandler<PIO0>; | ||
| 31 | }); | ||
| 32 | |||
| 33 | #[embassy_executor::task] | ||
| 34 | async fn ethernet_task( | ||
| 35 | runner: Runner< | ||
| 36 | 'static, | ||
| 37 | W5500, | ||
| 38 | ExclusiveDevice<Spi<'static, PIO0, 0, Async>, Output<'static>, Delay>, | ||
| 39 | Input<'static>, | ||
| 40 | Output<'static>, | ||
| 41 | >, | ||
| 42 | ) -> ! { | ||
| 43 | runner.run().await | ||
| 44 | } | ||
| 45 | |||
| 46 | #[embassy_executor::task] | ||
| 47 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 48 | runner.run().await | ||
| 49 | } | ||
| 50 | |||
| 51 | #[embassy_executor::main] | ||
| 52 | async fn main(spawner: Spawner) { | ||
| 53 | let p = embassy_rp::init(Default::default()); | ||
| 54 | let mut rng = RoscRng; | ||
| 55 | let mut led = Output::new(p.PIN_19, Level::Low); | ||
| 56 | |||
| 57 | // The W55RP20 uses a PIO unit for SPI communication, once the SPI bus has been formed using a | ||
| 58 | // PIO statemachine everything else is generally unchanged from the other examples that use the W5500 | ||
| 59 | let mosi = p.PIN_23; | ||
| 60 | let miso = p.PIN_22; | ||
| 61 | let clk = p.PIN_21; | ||
| 62 | |||
| 63 | let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); | ||
| 64 | |||
| 65 | // Construct an SPI driver backed by a PIO state machine | ||
| 66 | let mut spi_cfg = SpiConfig::default(); | ||
| 67 | spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI | ||
| 68 | // peripheral, use higher speeds at your peril | ||
| 69 | let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 70 | |||
| 71 | // Further control pins | ||
| 72 | let cs = Output::new(p.PIN_20, Level::High); | ||
| 73 | let w5500_int = Input::new(p.PIN_24, Pull::Up); | ||
| 74 | let w5500_reset = Output::new(p.PIN_25, Level::High); | ||
| 75 | |||
| 76 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 77 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 78 | let state = STATE.init(State::<8, 8>::new()); | ||
| 79 | let (device, runner) = embassy_net_wiznet::new( | ||
| 80 | mac_addr, | ||
| 81 | state, | ||
| 82 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 83 | w5500_int, | ||
| 84 | w5500_reset, | ||
| 85 | ) | ||
| 86 | .await | ||
| 87 | .unwrap(); | ||
| 88 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 89 | |||
| 90 | // Generate random seed | ||
| 91 | let seed = rng.next_u64(); | ||
| 92 | |||
| 93 | // Init network stack | ||
| 94 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 95 | let (stack, runner) = embassy_net::new( | ||
| 96 | device, | ||
| 97 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 98 | RESOURCES.init(StackResources::new()), | ||
| 99 | seed, | ||
| 100 | ); | ||
| 101 | |||
| 102 | // Launch network task | ||
| 103 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 104 | |||
| 105 | info!("Waiting for DHCP..."); | ||
| 106 | let cfg = wait_for_config(stack).await; | ||
| 107 | let local_addr = cfg.address.address(); | ||
| 108 | info!("IP address: {:?}", local_addr); | ||
| 109 | |||
| 110 | let mut rx_buffer = [0; 4096]; | ||
| 111 | let mut tx_buffer = [0; 4096]; | ||
| 112 | let mut buf = [0; 4096]; | ||
| 113 | loop { | ||
| 114 | let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 115 | socket.set_timeout(Some(Duration::from_secs(10))); | ||
| 116 | |||
| 117 | led.set_low(); | ||
| 118 | info!("Listening on TCP:1234..."); | ||
| 119 | if let Err(e) = socket.accept(1234).await { | ||
| 120 | warn!("accept error: {:?}", e); | ||
| 121 | continue; | ||
| 122 | } | ||
| 123 | info!("Received connection from {:?}", socket.remote_endpoint()); | ||
| 124 | led.set_high(); | ||
| 125 | |||
| 126 | loop { | ||
| 127 | let n = match socket.read(&mut buf).await { | ||
| 128 | Ok(0) => { | ||
| 129 | warn!("read EOF"); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | Ok(n) => n, | ||
| 133 | Err(e) => { | ||
| 134 | warn!("{:?}", e); | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | }; | ||
| 138 | info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); | ||
| 139 | |||
| 140 | if let Err(e) = socket.write_all(&buf[..n]).await { | ||
| 141 | warn!("write error: {:?}", e); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 149 | loop { | ||
| 150 | if let Some(config) = stack.config_v4() { | ||
| 151 | return config.clone(); | ||
| 152 | } | ||
| 153 | yield_now().await; | ||
| 154 | } | ||
| 155 | } | ||
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index c9c8a2760..317921374 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs | |||
| @@ -49,7 +49,9 @@ async fn main(_spawner: Spawner) { | |||
| 49 | let scl = p.PIN_15; | 49 | let scl = p.PIN_15; |
| 50 | 50 | ||
| 51 | info!("set up i2c "); | 51 | info!("set up i2c "); |
| 52 | let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); | 52 | // Default I2C config enables internal pull-up resistors. |
| 53 | let config = Config::default(); | ||
| 54 | let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, config); | ||
| 53 | 55 | ||
| 54 | use mcp23017::*; | 56 | use mcp23017::*; |
| 55 | 57 | ||
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs index 08f31001b..e2b8b0d06 100644 --- a/examples/rp/src/bin/i2c_slave.rs +++ b/examples/rp/src/bin/i2c_slave.rs | |||
| @@ -105,7 +105,7 @@ async fn main(spawner: Spawner) { | |||
| 105 | config.addr = DEV_ADDR as u16; | 105 | config.addr = DEV_ADDR as u16; |
| 106 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_scl, d_sda, Irqs, config); | 106 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_scl, d_sda, Irqs, config); |
| 107 | 107 | ||
| 108 | unwrap!(spawner.spawn(device_task(device))); | 108 | spawner.spawn(unwrap!(device_task(device))); |
| 109 | 109 | ||
| 110 | let c_sda = p.PIN_0; | 110 | let c_sda = p.PIN_0; |
| 111 | let c_scl = p.PIN_1; | 111 | let c_scl = p.PIN_1; |
| @@ -113,5 +113,5 @@ async fn main(spawner: Spawner) { | |||
| 113 | config.frequency = 1_000_000; | 113 | config.frequency = 1_000_000; |
| 114 | let controller = i2c::I2c::new_async(p.I2C0, c_scl, c_sda, Irqs, config); | 114 | let controller = i2c::I2c::new_async(p.I2C0, c_scl, c_sda, Irqs, config); |
| 115 | 115 | ||
| 116 | unwrap!(spawner.spawn(controller_task(controller))); | 116 | spawner.spawn(unwrap!(controller_task(controller))); |
| 117 | } | 117 | } |
diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs index 787cdc112..2748f778a 100644 --- a/examples/rp/src/bin/interrupt.rs +++ b/examples/rp/src/bin/interrupt.rs | |||
| @@ -51,7 +51,7 @@ async fn main(spawner: Spawner) { | |||
| 51 | // No Mutex needed when sharing within the same executor/prio level | 51 | // No Mutex needed when sharing within the same executor/prio level |
| 52 | static AVG: StaticCell<Cell<u32>> = StaticCell::new(); | 52 | static AVG: StaticCell<Cell<u32>> = StaticCell::new(); |
| 53 | let avg = AVG.init(Default::default()); | 53 | let avg = AVG.init(Default::default()); |
| 54 | spawner.must_spawn(processing(avg)); | 54 | spawner.spawn(processing(avg).unwrap()); |
| 55 | 55 | ||
| 56 | let mut ticker = Ticker::every(Duration::from_secs(1)); | 56 | let mut ticker = Ticker::every(Duration::from_secs(1)); |
| 57 | loop { | 57 | loop { |
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 7cb546c91..3a6367420 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs | |||
| @@ -35,12 +35,12 @@ fn main() -> ! { | |||
| 35 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, | 35 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, |
| 36 | move || { | 36 | move || { |
| 37 | let executor1 = EXECUTOR1.init(Executor::new()); | 37 | let executor1 = EXECUTOR1.init(Executor::new()); |
| 38 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); | 38 | executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led)))); |
| 39 | }, | 39 | }, |
| 40 | ); | 40 | ); |
| 41 | 41 | ||
| 42 | let executor0 = EXECUTOR0.init(Executor::new()); | 42 | let executor0 = EXECUTOR0.init(Executor::new()); |
| 43 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); | 43 | executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[embassy_executor::task] | 46 | #[embassy_executor::task] |
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index 2b397f97d..96cdf8fb1 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs | |||
| @@ -130,16 +130,16 @@ fn main() -> ! { | |||
| 130 | // High-priority executor: SWI_IRQ_1, priority level 2 | 130 | // High-priority executor: SWI_IRQ_1, priority level 2 |
| 131 | interrupt::SWI_IRQ_1.set_priority(Priority::P2); | 131 | interrupt::SWI_IRQ_1.set_priority(Priority::P2); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); | 132 | let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); |
| 133 | unwrap!(spawner.spawn(run_high())); | 133 | spawner.spawn(unwrap!(run_high())); |
| 134 | 134 | ||
| 135 | // Medium-priority executor: SWI_IRQ_0, priority level 3 | 135 | // Medium-priority executor: SWI_IRQ_0, priority level 3 |
| 136 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | 136 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); |
| 137 | let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); | 137 | let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); |
| 138 | unwrap!(spawner.spawn(run_med())); | 138 | spawner.spawn(unwrap!(run_med())); |
| 139 | 139 | ||
| 140 | // Low priority executor: runs in thread mode, using WFE/SEV | 140 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 141 | let executor = EXECUTOR_LOW.init(Executor::new()); | 141 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 142 | executor.run(|spawner| { | 142 | executor.run(|spawner| { |
| 143 | unwrap!(spawner.spawn(run_low())); | 143 | spawner.spawn(unwrap!(run_low())); |
| 144 | }); | 144 | }); |
| 145 | } | 145 | } |
diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs index 5e2775793..9f25e1087 100644 --- a/examples/rp/src/bin/orchestrate_tasks.rs +++ b/examples/rp/src/bin/orchestrate_tasks.rs | |||
| @@ -29,7 +29,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | |||
| 29 | use embassy_sync::mutex::Mutex; | 29 | use embassy_sync::mutex::Mutex; |
| 30 | use embassy_sync::{channel, signal}; | 30 | use embassy_sync::{channel, signal}; |
| 31 | use embassy_time::{Duration, Timer}; | 31 | use embassy_time::{Duration, Timer}; |
| 32 | use rand::RngCore; | ||
| 33 | use {defmt_rtt as _, panic_probe as _}; | 32 | use {defmt_rtt as _, panic_probe as _}; |
| 34 | 33 | ||
| 35 | // Hardware resource assignment. See other examples for different ways of doing this. | 34 | // Hardware resource assignment. See other examples for different ways of doing this. |
| @@ -130,13 +129,13 @@ async fn main(spawner: Spawner) { | |||
| 130 | let p = embassy_rp::init(Default::default()); | 129 | let p = embassy_rp::init(Default::default()); |
| 131 | let r = split_resources! {p}; | 130 | let r = split_resources! {p}; |
| 132 | 131 | ||
| 133 | spawner.spawn(orchestrate(spawner)).unwrap(); | 132 | spawner.spawn(orchestrate(spawner).unwrap()); |
| 134 | spawner.spawn(random_60s(spawner)).unwrap(); | 133 | spawner.spawn(random_60s(spawner).unwrap()); |
| 135 | spawner.spawn(random_90s(spawner)).unwrap(); | 134 | spawner.spawn(random_90s(spawner).unwrap()); |
| 136 | // `random_30s` is not spawned here, butin the orchestrate task depending on state | 135 | // `random_30s` is not spawned here, butin the orchestrate task depending on state |
| 137 | spawner.spawn(usb_power(spawner, r.vbus)).unwrap(); | 136 | spawner.spawn(usb_power(spawner, r.vbus).unwrap()); |
| 138 | spawner.spawn(vsys_voltage(spawner, r.vsys)).unwrap(); | 137 | spawner.spawn(vsys_voltage(spawner, r.vsys).unwrap()); |
| 139 | spawner.spawn(consumer(spawner)).unwrap(); | 138 | spawner.spawn(consumer(spawner).unwrap()); |
| 140 | } | 139 | } |
| 141 | 140 | ||
| 142 | /// Main task that processes all events and updates system state. | 141 | /// Main task that processes all events and updates system state. |
| @@ -199,7 +198,7 @@ async fn orchestrate(spawner: Spawner) { | |||
| 199 | drop(state); | 198 | drop(state); |
| 200 | if respawn_first_random_seed_task { | 199 | if respawn_first_random_seed_task { |
| 201 | info!("(Re)-Starting the first random signal task"); | 200 | info!("(Re)-Starting the first random signal task"); |
| 202 | spawner.spawn(random_30s(spawner)).unwrap(); | 201 | spawner.spawn(random_30s(spawner).unwrap()); |
| 203 | } | 202 | } |
| 204 | } | 203 | } |
| 205 | _ => {} | 204 | _ => {} |
diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 9c78e0c9d..83b17308b 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks::{clk_sys_freq, ClockConfig}; | 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig}; |
| 11 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 12 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 13 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -18,10 +18,7 @@ const COUNT_TO: i64 = 10_000_000; | |||
| 18 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) -> ! { | 19 | async fn main(_spawner: Spawner) -> ! { |
| 20 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. | 20 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. |
| 21 | let config = Config::new(ClockConfig::system_freq(200_000_000)); | 21 | let config = Config::new(ClockConfig::system_freq(200_000_000).unwrap()); |
| 22 | |||
| 23 | // Show the voltage scale for verification | ||
| 24 | info!("System core voltage: {}", Debug2Format(&config.clocks.core_voltage)); | ||
| 25 | 22 | ||
| 26 | // Initialize the peripherals | 23 | // Initialize the peripherals |
| 27 | let p = embassy_rp::init(config); | 24 | let p = embassy_rp::init(config); |
| @@ -29,6 +26,9 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 29 | // Show CPU frequency for verification | 26 | // Show CPU frequency for verification |
| 30 | let sys_freq = clk_sys_freq(); | 27 | let sys_freq = clk_sys_freq(); |
| 31 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | 28 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); |
| 29 | // Show core voltage for verification | ||
| 30 | let core_voltage = core_voltage().unwrap(); | ||
| 31 | info!("Core voltage: {}", core_voltage); | ||
| 32 | 32 | ||
| 33 | // LED to indicate the system is running | 33 | // LED to indicate the system is running |
| 34 | let mut led = Output::new(p.PIN_25, Level::Low); | 34 | let mut led = Output::new(p.PIN_25, Level::Low); |
diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs index 35160b250..dea5cfb3c 100644 --- a/examples/rp/src/bin/overclock_manual.rs +++ b/examples/rp/src/bin/overclock_manual.rs | |||
| @@ -7,8 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks; | 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig}; |
| 11 | use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig}; | ||
| 12 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 13 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -41,9 +40,12 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 41 | // Initialize with our manual overclock configuration | 40 | // Initialize with our manual overclock configuration |
| 42 | let p = embassy_rp::init(configure_manual_overclock()); | 41 | let p = embassy_rp::init(configure_manual_overclock()); |
| 43 | 42 | ||
| 44 | // Verify the actual system clock frequency | 43 | // Show CPU frequency for verification |
| 45 | let sys_freq = clocks::clk_sys_freq(); | 44 | let sys_freq = clk_sys_freq(); |
| 46 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | 45 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); |
| 46 | // Show core voltage for verification | ||
| 47 | let core_voltage = core_voltage().unwrap(); | ||
| 48 | info!("Core voltage: {}", core_voltage); | ||
| 47 | 49 | ||
| 48 | // LED to indicate the system is running | 50 | // LED to indicate the system is running |
| 49 | let mut led = Output::new(p.PIN_25, Level::Low); | 51 | let mut led = Output::new(p.PIN_25, Level::Low); |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index bf6dbee69..1743a417e 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -125,7 +125,7 @@ async fn main(spawner: Spawner) { | |||
| 125 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); | 125 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); |
| 126 | setup_pio_task_sm1(&mut common, &mut sm1); | 126 | setup_pio_task_sm1(&mut common, &mut sm1); |
| 127 | setup_pio_task_sm2(&mut common, &mut sm2); | 127 | setup_pio_task_sm2(&mut common, &mut sm2); |
| 128 | spawner.spawn(pio_task_sm0(sm0)).unwrap(); | 128 | spawner.spawn(pio_task_sm0(sm0).unwrap()); |
| 129 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); | 129 | spawner.spawn(pio_task_sm1(sm1).unwrap()); |
| 130 | spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); | 130 | spawner.spawn(pio_task_sm2(irq3, sm2).unwrap()); |
| 131 | } | 131 | } |
diff --git a/examples/rp/src/bin/pio_i2s.rs b/examples/rp/src/bin/pio_i2s.rs index 192c8f854..695a74cc3 100644 --- a/examples/rp/src/bin/pio_i2s.rs +++ b/examples/rp/src/bin/pio_i2s.rs | |||
| @@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs { | |||
| 27 | 27 | ||
| 28 | const SAMPLE_RATE: u32 = 48_000; | 28 | const SAMPLE_RATE: u32 = 48_000; |
| 29 | const BIT_DEPTH: u32 = 16; | 29 | const BIT_DEPTH: u32 = 16; |
| 30 | const CHANNELS: u32 = 2; | ||
| 31 | 30 | ||
| 32 | #[embassy_executor::main] | 31 | #[embassy_executor::main] |
| 33 | async fn main(_spawner: Spawner) { | 32 | async fn main(_spawner: Spawner) { |
| @@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) { | |||
| 50 | left_right_clock_pin, | 49 | left_right_clock_pin, |
| 51 | SAMPLE_RATE, | 50 | SAMPLE_RATE, |
| 52 | BIT_DEPTH, | 51 | BIT_DEPTH, |
| 53 | CHANNELS, | ||
| 54 | &program, | 52 | &program, |
| 55 | ); | 53 | ); |
| 56 | 54 | ||
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs index 379e2b8f9..102f13c45 100644 --- a/examples/rp/src/bin/pio_onewire.rs +++ b/examples/rp/src/bin/pio_onewire.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | //! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. | 1 | //! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. |
| 2 | //! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example. | ||
| 2 | 3 | ||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs new file mode 100644 index 000000000..fd076dee0 --- /dev/null +++ b/examples/rp/src/bin/pio_onewire_parasite.rs | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | //! This example shows how you can use PIO to read one or more `DS18B20` | ||
| 2 | //! one-wire temperature sensors using parasite power. | ||
| 3 | //! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet. | ||
| 4 | //! For externally powered sensors, use the pio_onewire.rs example. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::peripherals::PIO0; | ||
| 12 | use embassy_rp::pio::{InterruptHandler, Pio}; | ||
| 13 | use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; | ||
| 14 | use embassy_time::Duration; | ||
| 15 | use heapless::Vec; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) { | ||
| 24 | let p = embassy_rp::init(Default::default()); | ||
| 25 | let mut pio = Pio::new(p.PIO0, Irqs); | ||
| 26 | |||
| 27 | let prg = PioOneWireProgram::new(&mut pio.common); | ||
| 28 | let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); | ||
| 29 | |||
| 30 | info!("Starting onewire search"); | ||
| 31 | |||
| 32 | let mut devices = Vec::<u64, 10>::new(); | ||
| 33 | let mut search = PioOneWireSearch::new(); | ||
| 34 | for _ in 0..10 { | ||
| 35 | if !search.is_finished() { | ||
| 36 | if let Some(address) = search.next(&mut onewire).await { | ||
| 37 | if crc8(&address.to_le_bytes()) == 0 { | ||
| 38 | info!("Found address: {:x}", address); | ||
| 39 | let _ = devices.push(address); | ||
| 40 | } else { | ||
| 41 | warn!("Found invalid address: {:x}", address); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | info!("Search done, found {} devices", devices.len()); | ||
| 48 | |||
| 49 | loop { | ||
| 50 | // Read all devices one by one | ||
| 51 | for device in &devices { | ||
| 52 | onewire.reset().await; | ||
| 53 | onewire.write_bytes(&[0x55]).await; // Match rom | ||
| 54 | onewire.write_bytes(&device.to_le_bytes()).await; | ||
| 55 | // 750 ms delay required for default 12-bit resolution. | ||
| 56 | onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await; | ||
| 57 | |||
| 58 | onewire.reset().await; | ||
| 59 | onewire.write_bytes(&[0x55]).await; // Match rom | ||
| 60 | onewire.write_bytes(&device.to_le_bytes()).await; | ||
| 61 | onewire.write_bytes(&[0xBE]).await; // Read scratchpad | ||
| 62 | |||
| 63 | let mut data = [0; 9]; | ||
| 64 | onewire.read_bytes(&mut data).await; | ||
| 65 | if crc8(&data) == 0 { | ||
| 66 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | ||
| 67 | info!("Read device {:x}: {} deg C", device, temp); | ||
| 68 | } else { | ||
| 69 | warn!("Reading device {:x} failed. {:02x}", device, data); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | fn crc8(data: &[u8]) -> u8 { | ||
| 76 | let mut crc = 0; | ||
| 77 | for b in data { | ||
| 78 | let mut data_byte = *b; | ||
| 79 | for _ in 0..8 { | ||
| 80 | let temp = (crc ^ data_byte) & 0x01; | ||
| 81 | crc >>= 1; | ||
| 82 | if temp != 0 { | ||
| 83 | crc ^= 0x8C; | ||
| 84 | } | ||
| 85 | data_byte >>= 1; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | crc | ||
| 89 | } | ||
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs index 2750f61ae..2fc19970b 100644 --- a/examples/rp/src/bin/pio_rotary_encoder.rs +++ b/examples/rp/src/bin/pio_rotary_encoder.rs | |||
| @@ -50,6 +50,6 @@ async fn main(spawner: Spawner) { | |||
| 50 | let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); | 50 | let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); |
| 51 | let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); | 51 | let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); |
| 52 | 52 | ||
| 53 | spawner.must_spawn(encoder_0(encoder0)); | 53 | spawner.spawn(encoder_0(encoder0).unwrap()); |
| 54 | spawner.must_spawn(encoder_1(encoder1)); | 54 | spawner.spawn(encoder_1(encoder1).unwrap()); |
| 55 | } | 55 | } |
diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs new file mode 100644 index 000000000..4218327ec --- /dev/null +++ b/examples/rp/src/bin/pio_spi.rs | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | //! This example shows how to use a PIO state machine as an additional SPI | ||
| 2 | //! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is | ||
| 3 | //! specified in this example. | ||
| 4 | //! | ||
| 5 | //! If you connect pin 6 and 7 you should get the same data back. | ||
| 6 | |||
| 7 | #![no_std] | ||
| 8 | #![no_main] | ||
| 9 | |||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_rp::peripherals::PIO0; | ||
| 13 | use embassy_rp::pio_programs::spi::Spi; | ||
| 14 | use embassy_rp::spi::Config; | ||
| 15 | use embassy_rp::{bind_interrupts, pio}; | ||
| 16 | use embassy_time::Timer; | ||
| 17 | use {defmt_rtt as _, panic_probe as _}; | ||
| 18 | |||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | PIO0_IRQ_0 => pio::InterruptHandler<PIO0>; | ||
| 21 | }); | ||
| 22 | |||
| 23 | #[embassy_executor::main] | ||
| 24 | async fn main(_spawner: Spawner) { | ||
| 25 | let p = embassy_rp::init(Default::default()); | ||
| 26 | info!("Hello World!"); | ||
| 27 | |||
| 28 | // These pins are routed to different hardware SPI peripherals, but we can | ||
| 29 | // use them together regardless | ||
| 30 | let mosi = p.PIN_6; // SPI0 SCLK | ||
| 31 | let miso = p.PIN_7; // SPI0 MOSI | ||
| 32 | let clk = p.PIN_8; // SPI1 MISO | ||
| 33 | |||
| 34 | let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); | ||
| 35 | |||
| 36 | // Construct an SPI driver backed by a PIO state machine | ||
| 37 | let mut spi = Spi::new_blocking(&mut common, sm0, clk, mosi, miso, Config::default()); | ||
| 38 | |||
| 39 | loop { | ||
| 40 | let tx_buf = [1_u8, 2, 3, 4, 5, 6]; | ||
| 41 | let mut rx_buf = [0_u8; 6]; | ||
| 42 | |||
| 43 | spi.blocking_transfer(&mut rx_buf, &tx_buf).unwrap(); | ||
| 44 | info!("{:?}", rx_buf); | ||
| 45 | |||
| 46 | Timer::after_secs(1).await; | ||
| 47 | } | ||
| 48 | } | ||
diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs new file mode 100644 index 000000000..18b57d26e --- /dev/null +++ b/examples/rp/src/bin/pio_spi_async.rs | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | //! This example shows how to use a PIO state machine as an additional SPI | ||
| 2 | //! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is | ||
| 3 | //! specified in this example. | ||
| 4 | //! | ||
| 5 | //! If you connect pin 6 and 7 you should get the same data back. | ||
| 6 | |||
| 7 | #![no_std] | ||
| 8 | #![no_main] | ||
| 9 | |||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_rp::peripherals::PIO0; | ||
| 13 | use embassy_rp::pio_programs::spi::Spi; | ||
| 14 | use embassy_rp::spi::Config; | ||
| 15 | use embassy_rp::{bind_interrupts, pio}; | ||
| 16 | use embassy_time::Timer; | ||
| 17 | use {defmt_rtt as _, panic_probe as _}; | ||
| 18 | |||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | PIO0_IRQ_0 => pio::InterruptHandler<PIO0>; | ||
| 21 | }); | ||
| 22 | |||
| 23 | #[embassy_executor::main] | ||
| 24 | async fn main(_spawner: Spawner) { | ||
| 25 | let p = embassy_rp::init(Default::default()); | ||
| 26 | info!("Hello World!"); | ||
| 27 | |||
| 28 | // These pins are routed to different hardware SPI peripherals, but we can | ||
| 29 | // use them together regardless | ||
| 30 | let mosi = p.PIN_6; // SPI0 SCLK | ||
| 31 | let miso = p.PIN_7; // SPI0 MOSI | ||
| 32 | let clk = p.PIN_8; // SPI1 MISO | ||
| 33 | |||
| 34 | let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); | ||
| 35 | |||
| 36 | // Construct an SPI driver backed by a PIO state machine | ||
| 37 | let mut spi = Spi::new( | ||
| 38 | &mut common, | ||
| 39 | sm0, | ||
| 40 | clk, | ||
| 41 | mosi, | ||
| 42 | miso, | ||
| 43 | p.DMA_CH0, | ||
| 44 | p.DMA_CH1, | ||
| 45 | Config::default(), | ||
| 46 | ); | ||
| 47 | |||
| 48 | loop { | ||
| 49 | let tx_buf = [1_u8, 2, 3, 4, 5, 6]; | ||
| 50 | let mut rx_buf = [0_u8; 6]; | ||
| 51 | |||
| 52 | spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); | ||
| 53 | info!("{:?}", rx_buf); | ||
| 54 | |||
| 55 | Timer::after_secs(1).await; | ||
| 56 | } | ||
| 57 | } | ||
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 04374323d..9dd07ab6e 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs | |||
| @@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 18 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 19 | async fn main(spawner: Spawner) { | 19 | async fn main(spawner: Spawner) { |
| 20 | let p = embassy_rp::init(Default::default()); | 20 | let p = embassy_rp::init(Default::default()); |
| 21 | spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); | 21 | spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap()); |
| 22 | spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); | 22 | spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap()); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | /// Demonstrate PWM by modifying & applying the config | 25 | /// Demonstrate PWM by modifying & applying the config |
diff --git a/examples/rp/src/bin/shared_bus.rs b/examples/rp/src/bin/shared_bus.rs index 9267dfccb..db7566b1a 100644 --- a/examples/rp/src/bin/shared_bus.rs +++ b/examples/rp/src/bin/shared_bus.rs | |||
| @@ -35,8 +35,8 @@ async fn main(spawner: Spawner) { | |||
| 35 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); | 35 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); |
| 36 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); | 36 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); |
| 37 | 37 | ||
| 38 | spawner.must_spawn(i2c_task_a(i2c_bus)); | 38 | spawner.spawn(i2c_task_a(i2c_bus).unwrap()); |
| 39 | spawner.must_spawn(i2c_task_b(i2c_bus)); | 39 | spawner.spawn(i2c_task_b(i2c_bus).unwrap()); |
| 40 | 40 | ||
| 41 | // Shared SPI bus | 41 | // Shared SPI bus |
| 42 | let spi_cfg = spi::Config::default(); | 42 | let spi_cfg = spi::Config::default(); |
| @@ -48,8 +48,8 @@ async fn main(spawner: Spawner) { | |||
| 48 | let cs_a = Output::new(p.PIN_0, Level::High); | 48 | let cs_a = Output::new(p.PIN_0, Level::High); |
| 49 | let cs_b = Output::new(p.PIN_1, Level::High); | 49 | let cs_b = Output::new(p.PIN_1, Level::High); |
| 50 | 50 | ||
| 51 | spawner.must_spawn(spi_task_a(spi_bus, cs_a)); | 51 | spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap()); |
| 52 | spawner.must_spawn(spi_task_b(spi_bus, cs_b)); | 52 | spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap()); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #[embassy_executor::task] | 55 | #[embassy_executor::task] |
diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs index 497c4f845..d4c89946b 100644 --- a/examples/rp/src/bin/sharing.rs +++ b/examples/rp/src/bin/sharing.rs | |||
| @@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt}; | |||
| 27 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 27 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 28 | use embassy_sync::{blocking_mutex, mutex}; | 28 | use embassy_sync::{blocking_mutex, mutex}; |
| 29 | use embassy_time::{Duration, Ticker}; | 29 | use embassy_time::{Duration, Ticker}; |
| 30 | use rand::RngCore; | ||
| 31 | use static_cell::{ConstStaticCell, StaticCell}; | 30 | use static_cell::{ConstStaticCell, StaticCell}; |
| 32 | use {defmt_rtt as _, panic_probe as _}; | 31 | use {defmt_rtt as _, panic_probe as _}; |
| 33 | 32 | ||
| @@ -69,7 +68,7 @@ fn main() -> ! { | |||
| 69 | // High-priority executor: runs in interrupt mode | 68 | // High-priority executor: runs in interrupt mode |
| 70 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | 69 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); |
| 71 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); | 70 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); |
| 72 | spawner.must_spawn(task_a(uart)); | 71 | spawner.spawn(task_a(uart).unwrap()); |
| 73 | 72 | ||
| 74 | // Low priority executor: runs in thread mode | 73 | // Low priority executor: runs in thread mode |
| 75 | let executor = EXECUTOR_LOW.init(Executor::new()); | 74 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| @@ -84,8 +83,8 @@ fn main() -> ! { | |||
| 84 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); | 83 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); |
| 85 | let ref_cell = REF_CELL.take(); | 84 | let ref_cell = REF_CELL.take(); |
| 86 | 85 | ||
| 87 | spawner.must_spawn(task_b(uart, cell, ref_cell)); | 86 | spawner.spawn(task_b(uart, cell, ref_cell).unwrap()); |
| 88 | spawner.must_spawn(task_c(cell, ref_cell)); | 87 | spawner.spawn(task_c(cell, ref_cell).unwrap()); |
| 89 | }); | 88 | }); |
| 90 | } | 89 | } |
| 91 | 90 | ||
diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs index 30afc253d..fdef09d4b 100644 --- a/examples/rp/src/bin/spi_gc9a01.rs +++ b/examples/rp/src/bin/spi_gc9a01.rs | |||
| @@ -26,7 +26,6 @@ use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | |||
| 26 | use mipidsi::models::GC9A01; | 26 | use mipidsi::models::GC9A01; |
| 27 | use mipidsi::options::{ColorInversion, ColorOrder}; | 27 | use mipidsi::options::{ColorInversion, ColorOrder}; |
| 28 | use mipidsi::Builder; | 28 | use mipidsi::Builder; |
| 29 | use rand_core::RngCore; | ||
| 30 | use {defmt_rtt as _, panic_probe as _}; | 29 | use {defmt_rtt as _, panic_probe as _}; |
| 31 | 30 | ||
| 32 | const DISPLAY_FREQ: u32 = 64_000_000; | 31 | const DISPLAY_FREQ: u32 = 64_000_000; |
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 3adbc18ab..820daed96 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs | |||
| @@ -33,7 +33,7 @@ async fn main(spawner: Spawner) { | |||
| 33 | let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); | 33 | let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); |
| 34 | let (mut tx, rx) = uart.split(); | 34 | let (mut tx, rx) = uart.split(); |
| 35 | 35 | ||
| 36 | unwrap!(spawner.spawn(reader(rx))); | 36 | spawner.spawn(unwrap!(reader(rx))); |
| 37 | 37 | ||
| 38 | info!("Writing..."); | 38 | info!("Writing..."); |
| 39 | loop { | 39 | loop { |
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index c2c8dfad8..573b45b51 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs | |||
| @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) { | |||
| 27 | let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); | 27 | let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); |
| 28 | let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); | 28 | let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(reader(uart_rx))); | 30 | spawner.spawn(unwrap!(reader(uart_rx))); |
| 31 | 31 | ||
| 32 | info!("Writing..."); | 32 | info!("Writing..."); |
| 33 | loop { | 33 | loop { |
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 2add20bc6..912e52e96 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -17,7 +17,6 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState | |||
| 17 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 17 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 18 | use embassy_usb::{Builder, Config, UsbDevice}; | 18 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 19 | use embedded_io_async::Write; | 19 | use embedded_io_async::Write; |
| 20 | use rand::RngCore; | ||
| 21 | use static_cell::StaticCell; | 20 | use static_cell::StaticCell; |
| 22 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 23 | 22 | ||
| @@ -85,11 +84,11 @@ async fn main(spawner: Spawner) { | |||
| 85 | // Build the builder. | 84 | // Build the builder. |
| 86 | let usb = builder.build(); | 85 | let usb = builder.build(); |
| 87 | 86 | ||
| 88 | unwrap!(spawner.spawn(usb_task(usb))); | 87 | spawner.spawn(unwrap!(usb_task(usb))); |
| 89 | 88 | ||
| 90 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); | 89 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); |
| 91 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); | 90 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); |
| 92 | unwrap!(spawner.spawn(usb_ncm_task(runner))); | 91 | spawner.spawn(unwrap!(usb_ncm_task(runner))); |
| 93 | 92 | ||
| 94 | let config = embassy_net::Config::dhcpv4(Default::default()); | 93 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 95 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 94 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
| @@ -105,7 +104,7 @@ async fn main(spawner: Spawner) { | |||
| 105 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 104 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 106 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 105 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 107 | 106 | ||
| 108 | unwrap!(spawner.spawn(net_task(runner))); | 107 | spawner.spawn(unwrap!(net_task(runner))); |
| 109 | 108 | ||
| 110 | // And now we can use it! | 109 | // And now we can use it! |
| 111 | 110 | ||
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index 5ee650910..4454c593c 100644..100755 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs | |||
| @@ -85,8 +85,8 @@ async fn main(_spawner: Spawner) { | |||
| 85 | _ = Timer::after_secs(1).await; | 85 | _ = Timer::after_secs(1).await; |
| 86 | let report = MouseReport { | 86 | let report = MouseReport { |
| 87 | buttons: 0, | 87 | buttons: 0, |
| 88 | x: rng.gen_range(-100..100), // random small x movement | 88 | x: rng.random_range(-100..100), // random small x movement |
| 89 | y: rng.gen_range(-100..100), // random small y movement | 89 | y: rng.random_range(-100..100), // random small y movement |
| 90 | wheel: 0, | 90 | wheel: 0, |
| 91 | pan: 0, | 91 | pan: 0, |
| 92 | }; | 92 | }; |
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index af401ed63..ed2333efc 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs | |||
| @@ -25,7 +25,7 @@ async fn logger_task(driver: Driver<'static, USB>) { | |||
| 25 | async fn main(spawner: Spawner) { | 25 | async fn main(spawner: Spawner) { |
| 26 | let p = embassy_rp::init(Default::default()); | 26 | let p = embassy_rp::init(Default::default()); |
| 27 | let driver = Driver::new(p.USB, Irqs); | 27 | let driver = Driver::new(p.USB, Irqs); |
| 28 | spawner.spawn(logger_task(driver)).unwrap(); | 28 | spawner.spawn(logger_task(driver).unwrap()); |
| 29 | 29 | ||
| 30 | let mut counter = 0; | 30 | let mut counter = 0; |
| 31 | loop { | 31 | loop { |
diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs index 103269791..0747901d1 100644 --- a/examples/rp/src/bin/usb_raw_bulk.rs +++ b/examples/rp/src/bin/usb_raw_bulk.rs | |||
| @@ -96,8 +96,8 @@ async fn main(_spawner: Spawner) { | |||
| 96 | let mut function = builder.function(0xFF, 0, 0); | 96 | let mut function = builder.function(0xFF, 0, 0); |
| 97 | let mut interface = function.interface(); | 97 | let mut interface = function.interface(); |
| 98 | let mut alt = interface.alt_setting(0xFF, 0, 0, None); | 98 | let mut alt = interface.alt_setting(0xFF, 0, 0, None); |
| 99 | let mut read_ep = alt.endpoint_bulk_out(64); | 99 | let mut read_ep = alt.endpoint_bulk_out(None, 64); |
| 100 | let mut write_ep = alt.endpoint_bulk_in(64); | 100 | let mut write_ep = alt.endpoint_bulk_in(None, 64); |
| 101 | drop(function); | 101 | drop(function); |
| 102 | 102 | ||
| 103 | // Build the builder. | 103 | // Build the builder. |
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 5e3f0f378..b79012acb 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs | |||
| @@ -69,7 +69,7 @@ async fn main(spawner: Spawner) { | |||
| 69 | let usb = builder.build(); | 69 | let usb = builder.build(); |
| 70 | 70 | ||
| 71 | // Run the USB device. | 71 | // Run the USB device. |
| 72 | unwrap!(spawner.spawn(usb_task(usb))); | 72 | spawner.spawn(unwrap!(usb_task(usb))); |
| 73 | 73 | ||
| 74 | // Do stuff with the class! | 74 | // Do stuff with the class! |
| 75 | loop { | 75 | loop { |
diff --git a/examples/rp/src/bin/usb_serial_with_handler.rs b/examples/rp/src/bin/usb_serial_with_handler.rs index a9e65be70..b85c9029b 100644 --- a/examples/rp/src/bin/usb_serial_with_handler.rs +++ b/examples/rp/src/bin/usb_serial_with_handler.rs | |||
| @@ -53,7 +53,7 @@ async fn logger_task(driver: Driver<'static, USB>) { | |||
| 53 | async fn main(spawner: Spawner) { | 53 | async fn main(spawner: Spawner) { |
| 54 | let p = embassy_rp::init(Default::default()); | 54 | let p = embassy_rp::init(Default::default()); |
| 55 | let driver = Driver::new(p.USB, Irqs); | 55 | let driver = Driver::new(p.USB, Irqs); |
| 56 | spawner.spawn(logger_task(driver)).unwrap(); | 56 | spawner.spawn(logger_task(driver).unwrap()); |
| 57 | 57 | ||
| 58 | let mut counter = 0; | 58 | let mut counter = 0; |
| 59 | loop { | 59 | loop { |
diff --git a/examples/rp/src/bin/usb_webusb.rs b/examples/rp/src/bin/usb_webusb.rs index a5dc94d5b..5cecb92f0 100644 --- a/examples/rp/src/bin/usb_webusb.rs +++ b/examples/rp/src/bin/usb_webusb.rs | |||
| @@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> { | |||
| 125 | let mut iface = func.interface(); | 125 | let mut iface = func.interface(); |
| 126 | let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); | 126 | let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); |
| 127 | 127 | ||
| 128 | let write_ep = alt.endpoint_bulk_in(config.max_packet_size); | 128 | let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size); |
| 129 | let read_ep = alt.endpoint_bulk_out(config.max_packet_size); | 129 | let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size); |
| 130 | 130 | ||
| 131 | WebEndpoints { write_ep, read_ep } | 131 | WebEndpoints { write_ep, read_ep } |
| 132 | } | 132 | } |
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index e97ddb4c1..128599e0d 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -19,7 +19,6 @@ use embassy_rp::peripherals::{DMA_CH0, PIO0}; | |||
| 19 | use embassy_rp::pio::{InterruptHandler, Pio}; | 19 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 20 | use embassy_time::Duration; | 20 | use embassy_time::Duration; |
| 21 | use embedded_io_async::Write; | 21 | use embedded_io_async::Write; |
| 22 | use rand::RngCore; | ||
| 23 | use static_cell::StaticCell; | 22 | use static_cell::StaticCell; |
| 24 | use {defmt_rtt as _, panic_probe as _}; | 23 | use {defmt_rtt as _, panic_probe as _}; |
| 25 | 24 | ||
| @@ -71,7 +70,7 @@ async fn main(spawner: Spawner) { | |||
| 71 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 70 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 72 | let state = STATE.init(cyw43::State::new()); | 71 | let state = STATE.init(cyw43::State::new()); |
| 73 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 72 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 74 | unwrap!(spawner.spawn(cyw43_task(runner))); | 73 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 75 | 74 | ||
| 76 | control.init(clm).await; | 75 | control.init(clm).await; |
| 77 | control | 76 | control |
| @@ -92,7 +91,7 @@ async fn main(spawner: Spawner) { | |||
| 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 91 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); | 92 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 94 | 93 | ||
| 95 | unwrap!(spawner.spawn(net_task(runner))); | 94 | spawner.spawn(unwrap!(net_task(runner))); |
| 96 | 95 | ||
| 97 | //control.start_ap_open("cyw43", 5).await; | 96 | //control.start_ap_open("cyw43", 5).await; |
| 98 | control.start_ap_wpa2("cyw43", "password", 5).await; | 97 | control.start_ap_wpa2("cyw43", "password", 5).await; |
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index 6e91ce167..b2e08c517 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs | |||
| @@ -55,7 +55,7 @@ async fn main(spawner: Spawner) { | |||
| 55 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 55 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 56 | let state = STATE.init(cyw43::State::new()); | 56 | let state = STATE.init(cyw43::State::new()); |
| 57 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 57 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 58 | unwrap!(spawner.spawn(cyw43_task(runner))); | 58 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 59 | 59 | ||
| 60 | control.init(clm).await; | 60 | control.init(clm).await; |
| 61 | control | 61 | control |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index fe9c363d9..c884aa2ba 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) { | |||
| 59 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 59 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 60 | let state = STATE.init(cyw43::State::new()); | 60 | let state = STATE.init(cyw43::State::new()); |
| 61 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 61 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 62 | unwrap!(spawner.spawn(cyw43_task(runner))); | 62 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 63 | 63 | ||
| 64 | control.init(clm).await; | 64 | control.init(clm).await; |
| 65 | control | 65 | control |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 7e3c663fe..126475779 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -18,9 +18,8 @@ use embassy_rp::clocks::RoscRng; | |||
| 18 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| 19 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | 19 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; |
| 20 | use embassy_rp::pio::{InterruptHandler, Pio}; | 20 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 21 | use embassy_time::{Duration, Timer}; | 21 | use embassy_time::Duration; |
| 22 | use embedded_io_async::Write; | 22 | use embedded_io_async::Write; |
| 23 | use rand::RngCore; | ||
| 24 | use static_cell::StaticCell; | 23 | use static_cell::StaticCell; |
| 25 | use {defmt_rtt as _, panic_probe as _}; | 24 | use {defmt_rtt as _, panic_probe as _}; |
| 26 | 25 | ||
| @@ -75,7 +74,7 @@ async fn main(spawner: Spawner) { | |||
| 75 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 74 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 76 | let state = STATE.init(cyw43::State::new()); | 75 | let state = STATE.init(cyw43::State::new()); |
| 77 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 76 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 78 | unwrap!(spawner.spawn(cyw43_task(runner))); | 77 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 79 | 78 | ||
| 80 | control.init(clm).await; | 79 | control.init(clm).await; |
| 81 | control | 80 | control |
| @@ -96,28 +95,23 @@ async fn main(spawner: Spawner) { | |||
| 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 97 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); | 96 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 98 | 97 | ||
| 99 | unwrap!(spawner.spawn(net_task(runner))); | 98 | spawner.spawn(unwrap!(net_task(runner))); |
| 100 | 99 | ||
| 101 | loop { | 100 | while let Err(err) = control |
| 102 | match control | 101 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 103 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 102 | .await |
| 104 | .await | 103 | { |
| 105 | { | 104 | info!("join failed with status={}", err.status); |
| 106 | Ok(_) => break, | ||
| 107 | Err(err) => { | ||
| 108 | info!("join failed with status={}", err.status); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | 105 | } |
| 112 | 106 | ||
| 113 | // Wait for DHCP, not necessary when using static IP | 107 | info!("waiting for link..."); |
| 108 | stack.wait_link_up().await; | ||
| 109 | |||
| 114 | info!("waiting for DHCP..."); | 110 | info!("waiting for DHCP..."); |
| 115 | while !stack.is_config_up() { | 111 | stack.wait_config_up().await; |
| 116 | Timer::after_millis(100).await; | ||
| 117 | } | ||
| 118 | info!("DHCP is now up!"); | ||
| 119 | 112 | ||
| 120 | // And now we can use it! | 113 | // And now we can use it! |
| 114 | info!("Stack is up!"); | ||
| 121 | 115 | ||
| 122 | let mut rx_buffer = [0; 4096]; | 116 | let mut rx_buffer = [0; 4096]; |
| 123 | let mut tx_buffer = [0; 4096]; | 117 | let mut tx_buffer = [0; 4096]; |
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index f1b398b65..079def370 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs | |||
| @@ -20,7 +20,6 @@ use embassy_rp::gpio::{Level, Output}; | |||
| 20 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | 20 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; |
| 21 | use embassy_rp::pio::{InterruptHandler, Pio}; | 21 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 22 | use embassy_time::{Duration, Timer}; | 22 | use embassy_time::{Duration, Timer}; |
| 23 | use rand::RngCore; | ||
| 24 | use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; | 23 | use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; |
| 25 | use reqwless::request::Method; | 24 | use reqwless::request::Method; |
| 26 | use serde::Deserialize; | 25 | use serde::Deserialize; |
| @@ -77,7 +76,7 @@ async fn main(spawner: Spawner) { | |||
| 77 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 76 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 78 | let state = STATE.init(cyw43::State::new()); | 77 | let state = STATE.init(cyw43::State::new()); |
| 79 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 78 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 80 | unwrap!(spawner.spawn(cyw43_task(runner))); | 79 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 81 | 80 | ||
| 82 | control.init(clm).await; | 81 | control.init(clm).await; |
| 83 | control | 82 | control |
| @@ -99,35 +98,22 @@ async fn main(spawner: Spawner) { | |||
| 99 | static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new(); | 98 | static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new(); |
| 100 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); | 99 | let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); |
| 101 | 100 | ||
| 102 | unwrap!(spawner.spawn(net_task(runner))); | 101 | spawner.spawn(unwrap!(net_task(runner))); |
| 103 | 102 | ||
| 104 | loop { | 103 | while let Err(err) = control |
| 105 | match control | 104 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 106 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 105 | .await |
| 107 | .await | 106 | { |
| 108 | { | 107 | info!("join failed with status={}", err.status); |
| 109 | Ok(_) => break, | ||
| 110 | Err(err) => { | ||
| 111 | info!("join failed with status={}", err.status); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | // Wait for DHCP, not necessary when using static IP | ||
| 117 | info!("waiting for DHCP..."); | ||
| 118 | while !stack.is_config_up() { | ||
| 119 | Timer::after_millis(100).await; | ||
| 120 | } | 108 | } |
| 121 | info!("DHCP is now up!"); | ||
| 122 | 109 | ||
| 123 | info!("waiting for link up..."); | 110 | info!("waiting for link..."); |
| 124 | while !stack.is_link_up() { | 111 | stack.wait_link_up().await; |
| 125 | Timer::after_millis(500).await; | ||
| 126 | } | ||
| 127 | info!("Link is up!"); | ||
| 128 | 112 | ||
| 129 | info!("waiting for stack to be up..."); | 113 | info!("waiting for DHCP..."); |
| 130 | stack.wait_config_up().await; | 114 | stack.wait_config_up().await; |
| 115 | |||
| 116 | // And now we can use it! | ||
| 131 | info!("Stack is up!"); | 117 | info!("Stack is up!"); |
| 132 | 118 | ||
| 133 | // And now we can use it! | 119 | // And now we can use it! |
diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs index d1fb0eb00..d603e1ed3 100644 --- a/examples/rp/src/bin/zerocopy.rs +++ b/examples/rp/src/bin/zerocopy.rs | |||
| @@ -52,8 +52,8 @@ async fn main(spawner: Spawner) { | |||
| 52 | let channel = CHANNEL.init(Channel::new(buf)); | 52 | let channel = CHANNEL.init(Channel::new(buf)); |
| 53 | let (sender, receiver) = channel.split(); | 53 | let (sender, receiver) = channel.split(); |
| 54 | 54 | ||
| 55 | spawner.must_spawn(consumer(receiver)); | 55 | spawner.spawn(consumer(receiver).unwrap()); |
| 56 | spawner.must_spawn(producer(sender, adc_parts)); | 56 | spawner.spawn(producer(sender, adc_parts).unwrap()); |
| 57 | 57 | ||
| 58 | let mut ticker = Ticker::every(Duration::from_secs(1)); | 58 | let mut ticker = Ticker::every(Duration::from_secs(1)); |
| 59 | loop { | 59 | loop { |
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 345a915af..40fbb5798 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml | |||
| @@ -4,23 +4,24 @@ name = "embassy-rp2350-examples" | |||
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | publish = false | ||
| 7 | 8 | ||
| 8 | [dependencies] | 9 | [dependencies] |
| 9 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } | 10 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } | 14 | embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } | 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } |
| 16 | embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 18 | embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } | 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } |
| 19 | cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } | 20 | cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } |
| 20 | cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } | 21 | cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } |
| 21 | 22 | ||
| 22 | defmt = "0.3" | 23 | defmt = "1.0.1" |
| 23 | defmt-rtt = "0.4" | 24 | defmt-rtt = "1.0.0" |
| 24 | fixed = "1.23.1" | 25 | fixed = "1.23.1" |
| 25 | fixed-macro = "1.2" | 26 | fixed-macro = "1.2" |
| 26 | 27 | ||
| @@ -37,7 +38,7 @@ tb6612fng = "1.0.0" | |||
| 37 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | 38 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } |
| 38 | cortex-m-rt = "0.7.0" | 39 | cortex-m-rt = "0.7.0" |
| 39 | critical-section = "1.1" | 40 | critical-section = "1.1" |
| 40 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 41 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 41 | display-interface-spi = "0.5.0" | 42 | display-interface-spi = "0.5.0" |
| 42 | embedded-graphics = "0.8.1" | 43 | embedded-graphics = "0.8.1" |
| 43 | mipidsi = "0.8.0" | 44 | mipidsi = "0.8.0" |
| @@ -55,12 +56,13 @@ embedded-storage = { version = "0.3" } | |||
| 55 | static_cell = "2.1" | 56 | static_cell = "2.1" |
| 56 | portable-atomic = { version = "1.5", features = ["critical-section"] } | 57 | portable-atomic = { version = "1.5", features = ["critical-section"] } |
| 57 | log = "0.4" | 58 | log = "0.4" |
| 58 | rand = { version = "0.8.5", default-features = false } | ||
| 59 | embedded-sdmmc = "0.7.0" | 59 | embedded-sdmmc = "0.7.0" |
| 60 | 60 | ||
| 61 | [profile.release] | 61 | [profile.release] |
| 62 | debug = 2 | 62 | # Enable generation of debug symbols even on release builds |
| 63 | debug = true | ||
| 63 | 64 | ||
| 64 | [profile.dev] | 65 | [package.metadata.embassy] |
| 65 | lto = true | 66 | build = [ |
| 66 | opt-level = "z" | 67 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/rp235x" } |
| 68 | ] | ||
diff --git a/examples/rp235x/memory.x b/examples/rp235x/memory.x index c803896f6..4382e2065 100644 --- a/examples/rp235x/memory.x +++ b/examples/rp235x/memory.x | |||
| @@ -17,8 +17,8 @@ MEMORY { | |||
| 17 | * of access times. | 17 | * of access times. |
| 18 | * Example: Separate stacks for core0 and core1. | 18 | * Example: Separate stacks for core0 and core1. |
| 19 | */ | 19 | */ |
| 20 | SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K | 20 | SRAM8 : ORIGIN = 0x20080000, LENGTH = 4K |
| 21 | SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K | 21 | SRAM9 : ORIGIN = 0x20081000, LENGTH = 4K |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | SECTIONS { | 24 | SECTIONS { |
diff --git a/examples/rp235x/src/bin/assign_resources.rs b/examples/rp235x/src/bin/assign_resources.rs index 341f54d22..4ee4278b5 100644 --- a/examples/rp235x/src/bin/assign_resources.rs +++ b/examples/rp235x/src/bin/assign_resources.rs | |||
| @@ -26,15 +26,13 @@ async fn main(spawner: Spawner) { | |||
| 26 | let p = embassy_rp::init(Default::default()); | 26 | let p = embassy_rp::init(Default::default()); |
| 27 | 27 | ||
| 28 | // 1) Assigning a resource to a task by passing parts of the peripherals. | 28 | // 1) Assigning a resource to a task by passing parts of the peripherals. |
| 29 | spawner | 29 | spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap()); |
| 30 | .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) | ||
| 31 | .unwrap(); | ||
| 32 | 30 | ||
| 33 | // 2) Using the assign-resources macro to assign resources to a task. | 31 | // 2) Using the assign-resources macro to assign resources to a task. |
| 34 | // we perform the split, see further below for the definition of the resources struct | 32 | // we perform the split, see further below for the definition of the resources struct |
| 35 | let r = split_resources!(p); | 33 | let r = split_resources!(p); |
| 36 | // and then we can use them | 34 | // and then we can use them |
| 37 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); | 35 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap()); |
| 38 | } | 36 | } |
| 39 | 37 | ||
| 40 | // 1) Assigning a resource to a task by passing parts of the peripherals. | 38 | // 1) Assigning a resource to a task by passing parts of the peripherals. |
diff --git a/examples/rp235x/src/bin/blinky_two_channels.rs b/examples/rp235x/src/bin/blinky_two_channels.rs index 51e139e94..87f3a3545 100644 --- a/examples/rp235x/src/bin/blinky_two_channels.rs +++ b/examples/rp235x/src/bin/blinky_two_channels.rs | |||
| @@ -27,8 +27,8 @@ async fn main(spawner: Spawner) { | |||
| 27 | let dt = 100 * 1_000_000; | 27 | let dt = 100 * 1_000_000; |
| 28 | let k = 1.003; | 28 | let k = 1.003; |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); | 30 | spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); |
| 31 | unwrap!(spawner.spawn(toggle_led( | 31 | spawner.spawn(unwrap!(toggle_led( |
| 32 | CHANNEL.sender(), | 32 | CHANNEL.sender(), |
| 33 | Duration::from_nanos((dt as f64 * k) as u64) | 33 | Duration::from_nanos((dt as f64 * k) as u64) |
| 34 | ))); | 34 | ))); |
diff --git a/examples/rp235x/src/bin/blinky_two_tasks.rs b/examples/rp235x/src/bin/blinky_two_tasks.rs index 67a9108c0..aac7d928b 100644 --- a/examples/rp235x/src/bin/blinky_two_tasks.rs +++ b/examples/rp235x/src/bin/blinky_two_tasks.rs | |||
| @@ -30,8 +30,8 @@ async fn main(spawner: Spawner) { | |||
| 30 | let dt = 100 * 1_000_000; | 30 | let dt = 100 * 1_000_000; |
| 31 | let k = 1.003; | 31 | let k = 1.003; |
| 32 | 32 | ||
| 33 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); | 33 | spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt)))); |
| 34 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); | 34 | spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | #[embassy_executor::task(pool_size = 2)] | 37 | #[embassy_executor::task(pool_size = 2)] |
diff --git a/examples/rp235x/src/bin/blinky_wifi.rs b/examples/rp235x/src/bin/blinky_wifi.rs index 8c352ebc4..b2201f0ae 100644 --- a/examples/rp235x/src/bin/blinky_wifi.rs +++ b/examples/rp235x/src/bin/blinky_wifi.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #![no_std] | 5 | #![no_std] |
| 6 | #![no_main] | 6 | #![no_main] |
| 7 | 7 | ||
| 8 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 8 | use cyw43_pio::{PioSpi, RM2_CLOCK_DIVIDER}; |
| 9 | use defmt::*; | 9 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_rp::bind_interrupts; | 11 | use embassy_rp::bind_interrupts; |
| @@ -58,7 +58,9 @@ async fn main(spawner: Spawner) { | |||
| 58 | let spi = PioSpi::new( | 58 | let spi = PioSpi::new( |
| 59 | &mut pio.common, | 59 | &mut pio.common, |
| 60 | pio.sm0, | 60 | pio.sm0, |
| 61 | DEFAULT_CLOCK_DIVIDER, | 61 | // SPI communication won't work if the speed is too high, so we use a divider larger than `DEFAULT_CLOCK_DIVIDER`. |
| 62 | // See: https://github.com/embassy-rs/embassy/issues/3960. | ||
| 63 | RM2_CLOCK_DIVIDER, | ||
| 62 | pio.irq0, | 64 | pio.irq0, |
| 63 | cs, | 65 | cs, |
| 64 | p.PIN_24, | 66 | p.PIN_24, |
| @@ -69,7 +71,7 @@ async fn main(spawner: Spawner) { | |||
| 69 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 71 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 70 | let state = STATE.init(cyw43::State::new()); | 72 | let state = STATE.init(cyw43::State::new()); |
| 71 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 73 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 72 | unwrap!(spawner.spawn(cyw43_task(runner))); | 74 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 73 | 75 | ||
| 74 | control.init(clm).await; | 76 | control.init(clm).await; |
| 75 | control | 77 | control |
diff --git a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs index 0a5bccfb3..e6d6f687b 100644 --- a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs +++ b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs | |||
| @@ -68,7 +68,7 @@ async fn main(spawner: Spawner) { | |||
| 68 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 68 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 69 | let state = STATE.init(cyw43::State::new()); | 69 | let state = STATE.init(cyw43::State::new()); |
| 70 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 70 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 71 | unwrap!(spawner.spawn(cyw43_task(runner))); | 71 | spawner.spawn(unwrap!(cyw43_task(runner))); |
| 72 | 72 | ||
| 73 | control.init(clm).await; | 73 | control.init(clm).await; |
| 74 | control | 74 | control |
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs new file mode 100644 index 000000000..f012c9589 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | //! This example implements an echo (ping) with an ICMP Socket and using defmt to report the results. | ||
| 2 | //! | ||
| 3 | //! Although there is a better way to execute pings using the child module ping of the icmp module, | ||
| 4 | //! this example allows for other icmp messages like `Destination unreachable` to be sent aswell. | ||
| 5 | //! | ||
| 6 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_futures::yield_now; | ||
| 14 | use embassy_net::icmp::{ChecksumCapabilities, IcmpEndpoint, IcmpSocket, Icmpv4Packet, Icmpv4Repr, PacketMetadata}; | ||
| 15 | use embassy_net::{Stack, StackResources}; | ||
| 16 | use embassy_net_wiznet::chip::W5500; | ||
| 17 | use embassy_net_wiznet::*; | ||
| 18 | use embassy_rp::clocks::RoscRng; | ||
| 19 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 20 | use embassy_rp::peripherals::SPI0; | ||
| 21 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 22 | use embassy_time::{Delay, Instant, Timer}; | ||
| 23 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 24 | use static_cell::StaticCell; | ||
| 25 | use {defmt_rtt as _, panic_probe as _}; | ||
| 26 | |||
| 27 | type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>; | ||
| 28 | |||
| 29 | #[embassy_executor::task] | ||
| 30 | async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! { | ||
| 31 | runner.run().await | ||
| 32 | } | ||
| 33 | |||
| 34 | #[embassy_executor::task] | ||
| 35 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 36 | runner.run().await | ||
| 37 | } | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(spawner: Spawner) { | ||
| 41 | let p = embassy_rp::init(Default::default()); | ||
| 42 | let mut rng = RoscRng; | ||
| 43 | |||
| 44 | let mut spi_cfg = SpiConfig::default(); | ||
| 45 | spi_cfg.frequency = 50_000_000; | ||
| 46 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 47 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 48 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 49 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 50 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 51 | |||
| 52 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 53 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 54 | let state = STATE.init(State::<8, 8>::new()); | ||
| 55 | let (device, runner) = embassy_net_wiznet::new( | ||
| 56 | mac_addr, | ||
| 57 | state, | ||
| 58 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 59 | w5500_int, | ||
| 60 | w5500_reset, | ||
| 61 | ) | ||
| 62 | .await | ||
| 63 | .unwrap(); | ||
| 64 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 65 | |||
| 66 | // Generate random seed | ||
| 67 | let seed = rng.next_u64(); | ||
| 68 | |||
| 69 | // Init network stack | ||
| 70 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 71 | let (stack, runner) = embassy_net::new( | ||
| 72 | device, | ||
| 73 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 74 | RESOURCES.init(StackResources::new()), | ||
| 75 | seed, | ||
| 76 | ); | ||
| 77 | |||
| 78 | // Launch network task | ||
| 79 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 80 | |||
| 81 | info!("Waiting for DHCP..."); | ||
| 82 | let cfg = wait_for_config(stack).await; | ||
| 83 | let local_addr = cfg.address.address(); | ||
| 84 | info!("IP address: {:?}", local_addr); | ||
| 85 | |||
| 86 | // Then we can use it! | ||
| 87 | let mut rx_buffer = [0; 256]; | ||
| 88 | let mut tx_buffer = [0; 256]; | ||
| 89 | let mut rx_meta = [PacketMetadata::EMPTY]; | ||
| 90 | let mut tx_meta = [PacketMetadata::EMPTY]; | ||
| 91 | |||
| 92 | // Identifier used for the ICMP socket | ||
| 93 | let ident = 42; | ||
| 94 | |||
| 95 | // Create and bind the socket | ||
| 96 | let mut socket = IcmpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 97 | socket.bind(IcmpEndpoint::Ident(ident)).unwrap(); | ||
| 98 | |||
| 99 | // Create the repr for the packet | ||
| 100 | let icmp_repr = Icmpv4Repr::EchoRequest { | ||
| 101 | ident, | ||
| 102 | seq_no: 0, | ||
| 103 | data: b"Hello, icmp!", | ||
| 104 | }; | ||
| 105 | |||
| 106 | // Send the packet and store the starting instant to mesure latency later | ||
| 107 | let start = socket | ||
| 108 | .send_to_with(icmp_repr.buffer_len(), cfg.gateway.unwrap(), |buf| { | ||
| 109 | // Create and populate the packet buffer allocated by `send_to_with` | ||
| 110 | let mut icmp_packet = Icmpv4Packet::new_unchecked(buf); | ||
| 111 | icmp_repr.emit(&mut icmp_packet, &ChecksumCapabilities::default()); | ||
| 112 | Instant::now() // Return the instant where the packet was sent | ||
| 113 | }) | ||
| 114 | .await | ||
| 115 | .unwrap(); | ||
| 116 | |||
| 117 | // Recieve and log the data of the reply | ||
| 118 | socket | ||
| 119 | .recv_from_with(|(buf, addr)| { | ||
| 120 | let packet = Icmpv4Packet::new_checked(buf).unwrap(); | ||
| 121 | info!( | ||
| 122 | "Recieved {:?} from {} in {}ms", | ||
| 123 | packet.data(), | ||
| 124 | addr, | ||
| 125 | start.elapsed().as_millis() | ||
| 126 | ); | ||
| 127 | }) | ||
| 128 | .await | ||
| 129 | .unwrap(); | ||
| 130 | |||
| 131 | loop { | ||
| 132 | Timer::after_secs(10).await; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 137 | loop { | ||
| 138 | if let Some(config) = stack.config_v4() { | ||
| 139 | return config.clone(); | ||
| 140 | } | ||
| 141 | yield_now().await; | ||
| 142 | } | ||
| 143 | } | ||
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs new file mode 100644 index 000000000..309d3e4f7 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | //! This example implements a LAN ping scan with the ping utilities in the icmp module of embassy-net. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use core::net::Ipv4Addr; | ||
| 9 | use core::ops::Not; | ||
| 10 | use core::str::FromStr; | ||
| 11 | |||
| 12 | use defmt::*; | ||
| 13 | use embassy_executor::Spawner; | ||
| 14 | use embassy_futures::yield_now; | ||
| 15 | use embassy_net::icmp::ping::{PingManager, PingParams}; | ||
| 16 | use embassy_net::icmp::PacketMetadata; | ||
| 17 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; | ||
| 18 | use embassy_net_wiznet::chip::W5500; | ||
| 19 | use embassy_net_wiznet::*; | ||
| 20 | use embassy_rp::clocks::RoscRng; | ||
| 21 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 22 | use embassy_rp::peripherals::SPI0; | ||
| 23 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 24 | use embassy_time::{Delay, Duration}; | ||
| 25 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 26 | use static_cell::StaticCell; | ||
| 27 | use {defmt_rtt as _, panic_probe as _}; | ||
| 28 | |||
| 29 | type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>; | ||
| 30 | |||
| 31 | #[embassy_executor::task] | ||
| 32 | async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! { | ||
| 33 | runner.run().await | ||
| 34 | } | ||
| 35 | |||
| 36 | #[embassy_executor::task] | ||
| 37 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 38 | runner.run().await | ||
| 39 | } | ||
| 40 | |||
| 41 | #[embassy_executor::main] | ||
| 42 | async fn main(spawner: Spawner) { | ||
| 43 | let p = embassy_rp::init(Default::default()); | ||
| 44 | let mut rng = RoscRng; | ||
| 45 | |||
| 46 | let mut spi_cfg = SpiConfig::default(); | ||
| 47 | spi_cfg.frequency = 50_000_000; | ||
| 48 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 49 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 50 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 51 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 52 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 53 | |||
| 54 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 55 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 56 | let state = STATE.init(State::<8, 8>::new()); | ||
| 57 | let (device, runner) = embassy_net_wiznet::new( | ||
| 58 | mac_addr, | ||
| 59 | state, | ||
| 60 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 61 | w5500_int, | ||
| 62 | w5500_reset, | ||
| 63 | ) | ||
| 64 | .await | ||
| 65 | .unwrap(); | ||
| 66 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 67 | |||
| 68 | // Generate random seed | ||
| 69 | let seed = rng.next_u64(); | ||
| 70 | |||
| 71 | // Init network stack | ||
| 72 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 73 | let (stack, runner) = embassy_net::new( | ||
| 74 | device, | ||
| 75 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 76 | RESOURCES.init(StackResources::new()), | ||
| 77 | seed, | ||
| 78 | ); | ||
| 79 | |||
| 80 | // Launch network task | ||
| 81 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 82 | |||
| 83 | info!("Waiting for DHCP..."); | ||
| 84 | let cfg = wait_for_config(stack).await; | ||
| 85 | let local_addr = cfg.address.address(); | ||
| 86 | info!("IP address: {:?}", local_addr); | ||
| 87 | let gateway = cfg.gateway.unwrap(); | ||
| 88 | let mask = cfg.address.netmask(); | ||
| 89 | let lower_bound = (gateway.to_bits() & mask.to_bits()) + 1; | ||
| 90 | let upper_bound = gateway.to_bits() | mask.to_bits().not(); | ||
| 91 | let addr_range = lower_bound..=upper_bound; | ||
| 92 | |||
| 93 | // Then we can use it! | ||
| 94 | let mut rx_buffer = [0; 256]; | ||
| 95 | let mut tx_buffer = [0; 256]; | ||
| 96 | let mut rx_meta = [PacketMetadata::EMPTY]; | ||
| 97 | let mut tx_meta = [PacketMetadata::EMPTY]; | ||
| 98 | |||
| 99 | // Create the ping manager instance | ||
| 100 | let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 101 | let addr = "192.168.8.1"; // Address to ping to | ||
| 102 | // Create the PingParams with the target address | ||
| 103 | let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); | ||
| 104 | // (optional) Set custom properties of the ping | ||
| 105 | ping_params.set_payload(b"Hello, Ping!"); // custom payload | ||
| 106 | ping_params.set_count(1); // ping 1 times per ping call | ||
| 107 | ping_params.set_timeout(Duration::from_millis(500)); // wait .5 seconds instead of 4 | ||
| 108 | |||
| 109 | info!("Online hosts in {}:", Ipv4Cidr::from_netmask(gateway, mask).unwrap()); | ||
| 110 | let mut total_online_hosts = 0u32; | ||
| 111 | for addr in addr_range { | ||
| 112 | let ip_addr = Ipv4Addr::from_bits(addr); | ||
| 113 | // Set the target address in the ping params | ||
| 114 | ping_params.set_target(ip_addr); | ||
| 115 | // Execute the ping with the given parameters and wait for the reply | ||
| 116 | match ping_manager.ping(&ping_params).await { | ||
| 117 | Ok(time) => { | ||
| 118 | info!("{} is online\n- latency: {}ms\n", ip_addr, time.as_millis()); | ||
| 119 | total_online_hosts += 1; | ||
| 120 | } | ||
| 121 | _ => continue, | ||
| 122 | } | ||
| 123 | } | ||
| 124 | info!("Ping scan complete, total online hosts: {}", total_online_hosts); | ||
| 125 | } | ||
| 126 | |||
| 127 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 128 | loop { | ||
| 129 | if let Some(config) = stack.config_v4() { | ||
| 130 | return config.clone(); | ||
| 131 | } | ||
| 132 | yield_now().await; | ||
| 133 | } | ||
| 134 | } | ||
diff --git a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs new file mode 100644 index 000000000..7cfc00776 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | //! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_futures::yield_now; | ||
| 11 | use embassy_net::{Stack, StackResources}; | ||
| 12 | use embassy_net_wiznet::chip::W5500; | ||
| 13 | use embassy_net_wiznet::*; | ||
| 14 | use embassy_rp::clocks::RoscRng; | ||
| 15 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 16 | use embassy_rp::peripherals::SPI0; | ||
| 17 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 18 | use embassy_time::{Delay, Duration}; | ||
| 19 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 20 | use embedded_io_async::Write; | ||
| 21 | use static_cell::StaticCell; | ||
| 22 | use {defmt_rtt as _, panic_probe as _}; | ||
| 23 | |||
| 24 | #[embassy_executor::task] | ||
| 25 | async fn ethernet_task( | ||
| 26 | runner: Runner< | ||
| 27 | 'static, | ||
| 28 | W5500, | ||
| 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>, | ||
| 30 | Input<'static>, | ||
| 31 | Output<'static>, | ||
| 32 | >, | ||
| 33 | ) -> ! { | ||
| 34 | runner.run().await | ||
| 35 | } | ||
| 36 | |||
| 37 | #[embassy_executor::task] | ||
| 38 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 39 | runner.run().await | ||
| 40 | } | ||
| 41 | |||
| 42 | #[embassy_executor::main] | ||
| 43 | async fn main(spawner: Spawner) { | ||
| 44 | let p = embassy_rp::init(Default::default()); | ||
| 45 | let mut rng = RoscRng; | ||
| 46 | |||
| 47 | let mut spi_cfg = SpiConfig::default(); | ||
| 48 | spi_cfg.frequency = 50_000_000; | ||
| 49 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 50 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 51 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 52 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 53 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 54 | |||
| 55 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 56 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 57 | let state = STATE.init(State::<8, 8>::new()); | ||
| 58 | let (device, runner) = embassy_net_wiznet::new( | ||
| 59 | mac_addr, | ||
| 60 | state, | ||
| 61 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 62 | w5500_int, | ||
| 63 | w5500_reset, | ||
| 64 | ) | ||
| 65 | .await | ||
| 66 | .unwrap(); | ||
| 67 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 68 | |||
| 69 | // Generate random seed | ||
| 70 | let seed = rng.next_u64(); | ||
| 71 | |||
| 72 | // Init network stack | ||
| 73 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 74 | let (stack, runner) = embassy_net::new( | ||
| 75 | device, | ||
| 76 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 77 | RESOURCES.init(StackResources::new()), | ||
| 78 | seed, | ||
| 79 | ); | ||
| 80 | |||
| 81 | // Launch network task | ||
| 82 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 83 | |||
| 84 | info!("Waiting for DHCP..."); | ||
| 85 | let cfg = wait_for_config(stack).await; | ||
| 86 | let local_addr = cfg.address.address(); | ||
| 87 | info!("IP address: {:?}", local_addr); | ||
| 88 | |||
| 89 | // Create two sockets listening to the same port, to handle simultaneous connections | ||
| 90 | spawner.spawn(unwrap!(listen_task(stack, 0, 1234))); | ||
| 91 | spawner.spawn(unwrap!(listen_task(stack, 1, 1234))); | ||
| 92 | } | ||
| 93 | |||
| 94 | #[embassy_executor::task(pool_size = 2)] | ||
| 95 | async fn listen_task(stack: Stack<'static>, id: u8, port: u16) { | ||
| 96 | let mut rx_buffer = [0; 4096]; | ||
| 97 | let mut tx_buffer = [0; 4096]; | ||
| 98 | let mut buf = [0; 4096]; | ||
| 99 | loop { | ||
| 100 | let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 101 | socket.set_timeout(Some(Duration::from_secs(10))); | ||
| 102 | |||
| 103 | info!("SOCKET {}: Listening on TCP:{}...", id, port); | ||
| 104 | if let Err(e) = socket.accept(port).await { | ||
| 105 | warn!("accept error: {:?}", e); | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | info!("SOCKET {}: Received connection from {:?}", id, socket.remote_endpoint()); | ||
| 109 | |||
| 110 | loop { | ||
| 111 | let n = match socket.read(&mut buf).await { | ||
| 112 | Ok(0) => { | ||
| 113 | warn!("read EOF"); | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | Ok(n) => n, | ||
| 117 | Err(e) => { | ||
| 118 | warn!("SOCKET {}: {:?}", id, e); | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | }; | ||
| 122 | info!("SOCKET {}: rxd {}", id, core::str::from_utf8(&buf[..n]).unwrap()); | ||
| 123 | |||
| 124 | if let Err(e) = socket.write_all(&buf[..n]).await { | ||
| 125 | warn!("write error: {:?}", e); | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 133 | loop { | ||
| 134 | if let Some(config) = stack.config_v4() { | ||
| 135 | return config.clone(); | ||
| 136 | } | ||
| 137 | yield_now().await; | ||
| 138 | } | ||
| 139 | } | ||
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs new file mode 100644 index 000000000..254aada9a --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | //! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use core::str::FromStr; | ||
| 9 | |||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_futures::yield_now; | ||
| 13 | use embassy_net::{Stack, StackResources}; | ||
| 14 | use embassy_net_wiznet::chip::W5500; | ||
| 15 | use embassy_net_wiznet::*; | ||
| 16 | use embassy_rp::clocks::RoscRng; | ||
| 17 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 18 | use embassy_rp::peripherals::SPI0; | ||
| 19 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 20 | use embassy_time::{Delay, Duration, Timer}; | ||
| 21 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 22 | use embedded_io_async::Write; | ||
| 23 | use static_cell::StaticCell; | ||
| 24 | use {defmt_rtt as _, panic_probe as _}; | ||
| 25 | |||
| 26 | #[embassy_executor::task] | ||
| 27 | async fn ethernet_task( | ||
| 28 | runner: Runner< | ||
| 29 | 'static, | ||
| 30 | W5500, | ||
| 31 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>, | ||
| 32 | Input<'static>, | ||
| 33 | Output<'static>, | ||
| 34 | >, | ||
| 35 | ) -> ! { | ||
| 36 | runner.run().await | ||
| 37 | } | ||
| 38 | |||
| 39 | #[embassy_executor::task] | ||
| 40 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 41 | runner.run().await | ||
| 42 | } | ||
| 43 | |||
| 44 | #[embassy_executor::main] | ||
| 45 | async fn main(spawner: Spawner) { | ||
| 46 | let p = embassy_rp::init(Default::default()); | ||
| 47 | let mut rng = RoscRng; | ||
| 48 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 49 | |||
| 50 | let mut spi_cfg = SpiConfig::default(); | ||
| 51 | spi_cfg.frequency = 50_000_000; | ||
| 52 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 53 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 54 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 55 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 56 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 57 | |||
| 58 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 59 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 60 | let state = STATE.init(State::<8, 8>::new()); | ||
| 61 | let (device, runner) = embassy_net_wiznet::new( | ||
| 62 | mac_addr, | ||
| 63 | state, | ||
| 64 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 65 | w5500_int, | ||
| 66 | w5500_reset, | ||
| 67 | ) | ||
| 68 | .await | ||
| 69 | .unwrap(); | ||
| 70 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 71 | |||
| 72 | // Generate random seed | ||
| 73 | let seed = rng.next_u64(); | ||
| 74 | |||
| 75 | // Init network stack | ||
| 76 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 77 | let (stack, runner) = embassy_net::new( | ||
| 78 | device, | ||
| 79 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 80 | RESOURCES.init(StackResources::new()), | ||
| 81 | seed, | ||
| 82 | ); | ||
| 83 | |||
| 84 | // Launch network task | ||
| 85 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 86 | |||
| 87 | info!("Waiting for DHCP..."); | ||
| 88 | let cfg = wait_for_config(stack).await; | ||
| 89 | let local_addr = cfg.address.address(); | ||
| 90 | info!("IP address: {:?}", local_addr); | ||
| 91 | |||
| 92 | let mut rx_buffer = [0; 4096]; | ||
| 93 | let mut tx_buffer = [0; 4096]; | ||
| 94 | loop { | ||
| 95 | let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 96 | socket.set_timeout(Some(Duration::from_secs(10))); | ||
| 97 | |||
| 98 | led.set_low(); | ||
| 99 | info!("Connecting..."); | ||
| 100 | let host_addr = embassy_net::Ipv4Address::from_str("192.168.0.118").unwrap(); | ||
| 101 | if let Err(e) = socket.connect((host_addr, 1234)).await { | ||
| 102 | warn!("connect error: {:?}", e); | ||
| 103 | continue; | ||
| 104 | } | ||
| 105 | info!("Connected to {:?}", socket.remote_endpoint()); | ||
| 106 | led.set_high(); | ||
| 107 | |||
| 108 | let msg = b"Hello world!\n"; | ||
| 109 | loop { | ||
| 110 | if let Err(e) = socket.write_all(msg).await { | ||
| 111 | warn!("write error: {:?}", e); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | info!("txd: {}", core::str::from_utf8(msg).unwrap()); | ||
| 115 | Timer::after_secs(1).await; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 121 | loop { | ||
| 122 | if let Some(config) = stack.config_v4() { | ||
| 123 | return config.clone(); | ||
| 124 | } | ||
| 125 | yield_now().await; | ||
| 126 | } | ||
| 127 | } | ||
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs new file mode 100644 index 000000000..ba812f4fd --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | //! This example implements a TCP echo server on port 1234 and using DHCP. | ||
| 2 | //! Send it some data, you should see it echoed back and printed in the console. | ||
| 3 | //! | ||
| 4 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_futures::yield_now; | ||
| 12 | use embassy_net::{Stack, StackResources}; | ||
| 13 | use embassy_net_wiznet::chip::W5500; | ||
| 14 | use embassy_net_wiznet::*; | ||
| 15 | use embassy_rp::clocks::RoscRng; | ||
| 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 17 | use embassy_rp::peripherals::SPI0; | ||
| 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 19 | use embassy_time::{Delay, Duration}; | ||
| 20 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 21 | use embedded_io_async::Write; | ||
| 22 | use static_cell::StaticCell; | ||
| 23 | use {defmt_rtt as _, panic_probe as _}; | ||
| 24 | |||
| 25 | #[embassy_executor::task] | ||
| 26 | async fn ethernet_task( | ||
| 27 | runner: Runner< | ||
| 28 | 'static, | ||
| 29 | W5500, | ||
| 30 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>, | ||
| 31 | Input<'static>, | ||
| 32 | Output<'static>, | ||
| 33 | >, | ||
| 34 | ) -> ! { | ||
| 35 | runner.run().await | ||
| 36 | } | ||
| 37 | |||
| 38 | #[embassy_executor::task] | ||
| 39 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 40 | runner.run().await | ||
| 41 | } | ||
| 42 | |||
| 43 | #[embassy_executor::main] | ||
| 44 | async fn main(spawner: Spawner) { | ||
| 45 | let p = embassy_rp::init(Default::default()); | ||
| 46 | let mut rng = RoscRng; | ||
| 47 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 48 | |||
| 49 | let mut spi_cfg = SpiConfig::default(); | ||
| 50 | spi_cfg.frequency = 50_000_000; | ||
| 51 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 52 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 53 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 54 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 55 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 56 | |||
| 57 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 58 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 59 | let state = STATE.init(State::<8, 8>::new()); | ||
| 60 | let (device, runner) = embassy_net_wiznet::new( | ||
| 61 | mac_addr, | ||
| 62 | state, | ||
| 63 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 64 | w5500_int, | ||
| 65 | w5500_reset, | ||
| 66 | ) | ||
| 67 | .await | ||
| 68 | .unwrap(); | ||
| 69 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 70 | |||
| 71 | // Generate random seed | ||
| 72 | let seed = rng.next_u64(); | ||
| 73 | |||
| 74 | // Init network stack | ||
| 75 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 76 | let (stack, runner) = embassy_net::new( | ||
| 77 | device, | ||
| 78 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 79 | RESOURCES.init(StackResources::new()), | ||
| 80 | seed, | ||
| 81 | ); | ||
| 82 | |||
| 83 | // Launch network task | ||
| 84 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 85 | |||
| 86 | info!("Waiting for DHCP..."); | ||
| 87 | let cfg = wait_for_config(stack).await; | ||
| 88 | let local_addr = cfg.address.address(); | ||
| 89 | info!("IP address: {:?}", local_addr); | ||
| 90 | |||
| 91 | let mut rx_buffer = [0; 4096]; | ||
| 92 | let mut tx_buffer = [0; 4096]; | ||
| 93 | let mut buf = [0; 4096]; | ||
| 94 | loop { | ||
| 95 | let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 96 | socket.set_timeout(Some(Duration::from_secs(10))); | ||
| 97 | |||
| 98 | led.set_low(); | ||
| 99 | info!("Listening on TCP:1234..."); | ||
| 100 | if let Err(e) = socket.accept(1234).await { | ||
| 101 | warn!("accept error: {:?}", e); | ||
| 102 | continue; | ||
| 103 | } | ||
| 104 | info!("Received connection from {:?}", socket.remote_endpoint()); | ||
| 105 | led.set_high(); | ||
| 106 | |||
| 107 | loop { | ||
| 108 | let n = match socket.read(&mut buf).await { | ||
| 109 | Ok(0) => { | ||
| 110 | warn!("read EOF"); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | Ok(n) => n, | ||
| 114 | Err(e) => { | ||
| 115 | warn!("{:?}", e); | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | }; | ||
| 119 | info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); | ||
| 120 | |||
| 121 | if let Err(e) = socket.write_all(&buf[..n]).await { | ||
| 122 | warn!("write error: {:?}", e); | ||
| 123 | break; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 130 | loop { | ||
| 131 | if let Some(config) = stack.config_v4() { | ||
| 132 | return config.clone(); | ||
| 133 | } | ||
| 134 | yield_now().await; | ||
| 135 | } | ||
| 136 | } | ||
diff --git a/examples/rp235x/src/bin/ethernet_w5500_udp.rs b/examples/rp235x/src/bin/ethernet_w5500_udp.rs new file mode 100644 index 000000000..ae74ad518 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_udp.rs | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | //! This example implements a UDP server listening on port 1234 and echoing back the data. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_futures::yield_now; | ||
| 11 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | ||
| 12 | use embassy_net::{Stack, StackResources}; | ||
| 13 | use embassy_net_wiznet::chip::W5500; | ||
| 14 | use embassy_net_wiznet::*; | ||
| 15 | use embassy_rp::clocks::RoscRng; | ||
| 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 17 | use embassy_rp::peripherals::SPI0; | ||
| 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | ||
| 19 | use embassy_time::Delay; | ||
| 20 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 21 | use static_cell::StaticCell; | ||
| 22 | use {defmt_rtt as _, panic_probe as _}; | ||
| 23 | |||
| 24 | #[embassy_executor::task] | ||
| 25 | async fn ethernet_task( | ||
| 26 | runner: Runner< | ||
| 27 | 'static, | ||
| 28 | W5500, | ||
| 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>, | ||
| 30 | Input<'static>, | ||
| 31 | Output<'static>, | ||
| 32 | >, | ||
| 33 | ) -> ! { | ||
| 34 | runner.run().await | ||
| 35 | } | ||
| 36 | |||
| 37 | #[embassy_executor::task] | ||
| 38 | async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { | ||
| 39 | runner.run().await | ||
| 40 | } | ||
| 41 | |||
| 42 | #[embassy_executor::main] | ||
| 43 | async fn main(spawner: Spawner) { | ||
| 44 | let p = embassy_rp::init(Default::default()); | ||
| 45 | let mut rng = RoscRng; | ||
| 46 | |||
| 47 | let mut spi_cfg = SpiConfig::default(); | ||
| 48 | spi_cfg.frequency = 50_000_000; | ||
| 49 | let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); | ||
| 50 | let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 51 | let cs = Output::new(p.PIN_17, Level::High); | ||
| 52 | let w5500_int = Input::new(p.PIN_21, Pull::Up); | ||
| 53 | let w5500_reset = Output::new(p.PIN_20, Level::High); | ||
| 54 | |||
| 55 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | ||
| 56 | static STATE: StaticCell<State<8, 8>> = StaticCell::new(); | ||
| 57 | let state = STATE.init(State::<8, 8>::new()); | ||
| 58 | let (device, runner) = embassy_net_wiznet::new( | ||
| 59 | mac_addr, | ||
| 60 | state, | ||
| 61 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 62 | w5500_int, | ||
| 63 | w5500_reset, | ||
| 64 | ) | ||
| 65 | .await | ||
| 66 | .unwrap(); | ||
| 67 | spawner.spawn(unwrap!(ethernet_task(runner))); | ||
| 68 | |||
| 69 | // Generate random seed | ||
| 70 | let seed = rng.next_u64(); | ||
| 71 | |||
| 72 | // Init network stack | ||
| 73 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 74 | let (stack, runner) = embassy_net::new( | ||
| 75 | device, | ||
| 76 | embassy_net::Config::dhcpv4(Default::default()), | ||
| 77 | RESOURCES.init(StackResources::new()), | ||
| 78 | seed, | ||
| 79 | ); | ||
| 80 | |||
| 81 | // Launch network task | ||
| 82 | spawner.spawn(unwrap!(net_task(runner))); | ||
| 83 | |||
| 84 | info!("Waiting for DHCP..."); | ||
| 85 | let cfg = wait_for_config(stack).await; | ||
| 86 | let local_addr = cfg.address.address(); | ||
| 87 | info!("IP address: {:?}", local_addr); | ||
| 88 | |||
| 89 | // Then we can use it! | ||
| 90 | let mut rx_buffer = [0; 4096]; | ||
| 91 | let mut tx_buffer = [0; 4096]; | ||
| 92 | let mut rx_meta = [PacketMetadata::EMPTY; 16]; | ||
| 93 | let mut tx_meta = [PacketMetadata::EMPTY; 16]; | ||
| 94 | let mut buf = [0; 4096]; | ||
| 95 | loop { | ||
| 96 | let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 97 | socket.bind(1234).unwrap(); | ||
| 98 | |||
| 99 | loop { | ||
| 100 | let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); | ||
| 101 | if let Ok(s) = core::str::from_utf8(&buf[..n]) { | ||
| 102 | info!("rxd from {}: {}", ep, s); | ||
| 103 | } | ||
| 104 | socket.send_to(&buf[..n], ep).await.unwrap(); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { | ||
| 110 | loop { | ||
| 111 | if let Some(config) = stack.config_v4() { | ||
| 112 | return config.clone(); | ||
| 113 | } | ||
| 114 | yield_now().await; | ||
| 115 | } | ||
| 116 | } | ||
diff --git a/examples/rp235x/src/bin/i2c_slave.rs b/examples/rp235x/src/bin/i2c_slave.rs index 9fffb4646..02ad9a003 100644 --- a/examples/rp235x/src/bin/i2c_slave.rs +++ b/examples/rp235x/src/bin/i2c_slave.rs | |||
| @@ -105,7 +105,7 @@ async fn main(spawner: Spawner) { | |||
| 105 | config.addr = DEV_ADDR as u16; | 105 | config.addr = DEV_ADDR as u16; |
| 106 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); | 106 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); |
| 107 | 107 | ||
| 108 | unwrap!(spawner.spawn(device_task(device))); | 108 | spawner.spawn(unwrap!(device_task(device))); |
| 109 | 109 | ||
| 110 | let c_sda = p.PIN_1; | 110 | let c_sda = p.PIN_1; |
| 111 | let c_scl = p.PIN_0; | 111 | let c_scl = p.PIN_0; |
| @@ -113,5 +113,5 @@ async fn main(spawner: Spawner) { | |||
| 113 | config.frequency = 1_000_000; | 113 | config.frequency = 1_000_000; |
| 114 | let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); | 114 | let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); |
| 115 | 115 | ||
| 116 | unwrap!(spawner.spawn(controller_task(controller))); | 116 | spawner.spawn(unwrap!(controller_task(controller))); |
| 117 | } | 117 | } |
diff --git a/examples/rp235x/src/bin/interrupt.rs b/examples/rp235x/src/bin/interrupt.rs index e9ac76486..88513180c 100644 --- a/examples/rp235x/src/bin/interrupt.rs +++ b/examples/rp235x/src/bin/interrupt.rs | |||
| @@ -51,7 +51,7 @@ async fn main(spawner: Spawner) { | |||
| 51 | // No Mutex needed when sharing within the same executor/prio level | 51 | // No Mutex needed when sharing within the same executor/prio level |
| 52 | static AVG: StaticCell<Cell<u32>> = StaticCell::new(); | 52 | static AVG: StaticCell<Cell<u32>> = StaticCell::new(); |
| 53 | let avg = AVG.init(Default::default()); | 53 | let avg = AVG.init(Default::default()); |
| 54 | spawner.must_spawn(processing(avg)); | 54 | spawner.spawn(processing(avg).unwrap()); |
| 55 | 55 | ||
| 56 | let mut ticker = Ticker::every(Duration::from_secs(1)); | 56 | let mut ticker = Ticker::every(Duration::from_secs(1)); |
| 57 | loop { | 57 | loop { |
diff --git a/examples/rp235x/src/bin/multicore.rs b/examples/rp235x/src/bin/multicore.rs index f02dc3876..4f82801d6 100644 --- a/examples/rp235x/src/bin/multicore.rs +++ b/examples/rp235x/src/bin/multicore.rs | |||
| @@ -35,12 +35,12 @@ fn main() -> ! { | |||
| 35 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, | 35 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, |
| 36 | move || { | 36 | move || { |
| 37 | let executor1 = EXECUTOR1.init(Executor::new()); | 37 | let executor1 = EXECUTOR1.init(Executor::new()); |
| 38 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); | 38 | executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led)))); |
| 39 | }, | 39 | }, |
| 40 | ); | 40 | ); |
| 41 | 41 | ||
| 42 | let executor0 = EXECUTOR0.init(Executor::new()); | 42 | let executor0 = EXECUTOR0.init(Executor::new()); |
| 43 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); | 43 | executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[embassy_executor::task] | 46 | #[embassy_executor::task] |
diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs index 2b397f97d..96cdf8fb1 100644 --- a/examples/rp235x/src/bin/multiprio.rs +++ b/examples/rp235x/src/bin/multiprio.rs | |||
| @@ -130,16 +130,16 @@ fn main() -> ! { | |||
| 130 | // High-priority executor: SWI_IRQ_1, priority level 2 | 130 | // High-priority executor: SWI_IRQ_1, priority level 2 |
| 131 | interrupt::SWI_IRQ_1.set_priority(Priority::P2); | 131 | interrupt::SWI_IRQ_1.set_priority(Priority::P2); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); | 132 | let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); |
| 133 | unwrap!(spawner.spawn(run_high())); | 133 | spawner.spawn(unwrap!(run_high())); |
| 134 | 134 | ||
| 135 | // Medium-priority executor: SWI_IRQ_0, priority level 3 | 135 | // Medium-priority executor: SWI_IRQ_0, priority level 3 |
| 136 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | 136 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); |
| 137 | let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); | 137 | let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); |
| 138 | unwrap!(spawner.spawn(run_med())); | 138 | spawner.spawn(unwrap!(run_med())); |
| 139 | 139 | ||
| 140 | // Low priority executor: runs in thread mode, using WFE/SEV | 140 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 141 | let executor = EXECUTOR_LOW.init(Executor::new()); | 141 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 142 | executor.run(|spawner| { | 142 | executor.run(|spawner| { |
| 143 | unwrap!(spawner.spawn(run_low())); | 143 | spawner.spawn(unwrap!(run_low())); |
| 144 | }); | 144 | }); |
| 145 | } | 145 | } |
diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs new file mode 100644 index 000000000..5fd97ef97 --- /dev/null +++ b/examples/rp235x/src/bin/overclock.rs | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | //! # Overclocking the RP2350 to 200 MHz | ||
| 2 | //! | ||
| 3 | //! This example demonstrates how to configure the RP2350 to run at 200 MHz instead of the default 150 MHz. | ||
| 4 | //! | ||
| 5 | //! ## Note | ||
| 6 | //! | ||
| 7 | //! As of yet there is no official support for running the RP235x at higher clock frequencies and/or other core voltages than the default. | ||
| 8 | //! Doing so may cause unexpected behavior and/or damage the chip. | ||
| 9 | |||
| 10 | #![no_std] | ||
| 11 | #![no_main] | ||
| 12 | |||
| 13 | use defmt::*; | ||
| 14 | use embassy_executor::Spawner; | ||
| 15 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; | ||
| 16 | use embassy_rp::config::Config; | ||
| 17 | use embassy_rp::gpio::{Level, Output}; | ||
| 18 | use embassy_time::{Duration, Instant, Timer}; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | const COUNT_TO: i64 = 10_000_000; | ||
| 22 | |||
| 23 | #[embassy_executor::main] | ||
| 24 | async fn main(_spawner: Spawner) -> ! { | ||
| 25 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. | ||
| 26 | let mut config = Config::new(ClockConfig::system_freq(200_000_000).unwrap()); | ||
| 27 | |||
| 28 | // since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us. | ||
| 29 | // We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on | ||
| 30 | // what we know about the RP2040. This is not guaranteed to be correct. | ||
| 31 | config.clocks.core_voltage = CoreVoltage::V1_15; | ||
| 32 | |||
| 33 | // Initialize the peripherals | ||
| 34 | let p = embassy_rp::init(config); | ||
| 35 | |||
| 36 | // Show CPU frequency for verification | ||
| 37 | let sys_freq = clk_sys_freq(); | ||
| 38 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | ||
| 39 | // Show core voltage for verification | ||
| 40 | let core_voltage = core_voltage().unwrap(); | ||
| 41 | info!("Core voltage: {}", core_voltage); | ||
| 42 | |||
| 43 | // LED to indicate the system is running | ||
| 44 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 45 | |||
| 46 | loop { | ||
| 47 | // Reset the counter at the start of measurement period | ||
| 48 | let mut counter = 0; | ||
| 49 | |||
| 50 | // Turn LED on while counting | ||
| 51 | led.set_high(); | ||
| 52 | |||
| 53 | let start = Instant::now(); | ||
| 54 | |||
| 55 | // This is a busy loop that will take some time to complete | ||
| 56 | while counter < COUNT_TO { | ||
| 57 | counter += 1; | ||
| 58 | } | ||
| 59 | |||
| 60 | let elapsed = Instant::now() - start; | ||
| 61 | |||
| 62 | // Report the elapsed time | ||
| 63 | led.set_low(); | ||
| 64 | info!( | ||
| 65 | "At {}Mhz: Elapsed time to count to {}: {}ms", | ||
| 66 | sys_freq / 1_000_000, | ||
| 67 | counter, | ||
| 68 | elapsed.as_millis() | ||
| 69 | ); | ||
| 70 | |||
| 71 | // Wait 2 seconds before starting the next measurement | ||
| 72 | Timer::after(Duration::from_secs(2)).await; | ||
| 73 | } | ||
| 74 | } | ||
diff --git a/examples/rp235x/src/bin/pio_async.rs b/examples/rp235x/src/bin/pio_async.rs index a519b8a50..d76930f5c 100644 --- a/examples/rp235x/src/bin/pio_async.rs +++ b/examples/rp235x/src/bin/pio_async.rs | |||
| @@ -125,7 +125,7 @@ async fn main(spawner: Spawner) { | |||
| 125 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); | 125 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); |
| 126 | setup_pio_task_sm1(&mut common, &mut sm1); | 126 | setup_pio_task_sm1(&mut common, &mut sm1); |
| 127 | setup_pio_task_sm2(&mut common, &mut sm2); | 127 | setup_pio_task_sm2(&mut common, &mut sm2); |
| 128 | spawner.spawn(pio_task_sm0(sm0)).unwrap(); | 128 | spawner.spawn(pio_task_sm0(sm0).unwrap()); |
| 129 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); | 129 | spawner.spawn(pio_task_sm1(sm1).unwrap()); |
| 130 | spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); | 130 | spawner.spawn(pio_task_sm2(irq3, sm2).unwrap()); |
| 131 | } | 131 | } |
diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs index 5a4bcfcac..cfcb0221d 100644 --- a/examples/rp235x/src/bin/pio_i2s.rs +++ b/examples/rp235x/src/bin/pio_i2s.rs | |||
| @@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs { | |||
| 27 | 27 | ||
| 28 | const SAMPLE_RATE: u32 = 48_000; | 28 | const SAMPLE_RATE: u32 = 48_000; |
| 29 | const BIT_DEPTH: u32 = 16; | 29 | const BIT_DEPTH: u32 = 16; |
| 30 | const CHANNELS: u32 = 2; | ||
| 31 | 30 | ||
| 32 | #[embassy_executor::main] | 31 | #[embassy_executor::main] |
| 33 | async fn main(_spawner: Spawner) { | 32 | async fn main(_spawner: Spawner) { |
| @@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) { | |||
| 50 | left_right_clock_pin, | 49 | left_right_clock_pin, |
| 51 | SAMPLE_RATE, | 50 | SAMPLE_RATE, |
| 52 | BIT_DEPTH, | 51 | BIT_DEPTH, |
| 53 | CHANNELS, | ||
| 54 | &program, | 52 | &program, |
| 55 | ); | 53 | ); |
| 56 | 54 | ||
diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs new file mode 100644 index 000000000..c3f505b13 --- /dev/null +++ b/examples/rp235x/src/bin/pio_i2s_rx.rs | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | //! This example shows receiving audio from a connected I2S microphone (or other audio source) | ||
| 2 | //! using the PIO module of the RP235x. | ||
| 3 | //! | ||
| 4 | //! | ||
| 5 | //! Connect the i2s microphone as follows: | ||
| 6 | //! bclk : GPIO 18 | ||
| 7 | //! lrc : GPIO 19 | ||
| 8 | //! din : GPIO 20 | ||
| 9 | //! Then hold down the boot select button to begin receiving audio. Received I2S words will be written to | ||
| 10 | //! buffers for the left and right channels for use in your application, whether that's storage or | ||
| 11 | //! further processing | ||
| 12 | //! | ||
| 13 | //! Note the const USE_ONBOARD_PULLDOWN is by default set to false, meaning an external | ||
| 14 | //! pull-down resistor is being used on the data pin if required by the mic being used. | ||
| 15 | |||
| 16 | #![no_std] | ||
| 17 | #![no_main] | ||
| 18 | use core::mem; | ||
| 19 | |||
| 20 | use defmt::*; | ||
| 21 | use embassy_executor::Spawner; | ||
| 22 | use embassy_rp::bind_interrupts; | ||
| 23 | use embassy_rp::peripherals::PIO0; | ||
| 24 | use embassy_rp::pio::{InterruptHandler, Pio}; | ||
| 25 | use embassy_rp::pio_programs::i2s::{PioI2sIn, PioI2sInProgram}; | ||
| 26 | use static_cell::StaticCell; | ||
| 27 | use {defmt_rtt as _, panic_probe as _}; | ||
| 28 | |||
| 29 | bind_interrupts!(struct Irqs { | ||
| 30 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 31 | }); | ||
| 32 | |||
| 33 | const SAMPLE_RATE: u32 = 48_000; | ||
| 34 | const BIT_DEPTH: u32 = 16; | ||
| 35 | const CHANNELS: u32 = 2; | ||
| 36 | const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor, | ||
| 37 | // which has documented issues on many RP235x boards | ||
| 38 | #[embassy_executor::main] | ||
| 39 | async fn main(_spawner: Spawner) { | ||
| 40 | let p = embassy_rp::init(Default::default()); | ||
| 41 | |||
| 42 | // Setup pio state machine for i2s input | ||
| 43 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); | ||
| 44 | |||
| 45 | let bit_clock_pin = p.PIN_18; | ||
| 46 | let left_right_clock_pin = p.PIN_19; | ||
| 47 | let data_pin = p.PIN_20; | ||
| 48 | |||
| 49 | let program = PioI2sInProgram::new(&mut common); | ||
| 50 | let mut i2s = PioI2sIn::new( | ||
| 51 | &mut common, | ||
| 52 | sm0, | ||
| 53 | p.DMA_CH0, | ||
| 54 | USE_ONBOARD_PULLDOWN, | ||
| 55 | data_pin, | ||
| 56 | bit_clock_pin, | ||
| 57 | left_right_clock_pin, | ||
| 58 | SAMPLE_RATE, | ||
| 59 | BIT_DEPTH, | ||
| 60 | CHANNELS, | ||
| 61 | &program, | ||
| 62 | ); | ||
| 63 | |||
| 64 | // create two audio buffers (back and front) which will take turns being | ||
| 65 | // filled with new audio data from the PIO fifo using DMA | ||
| 66 | const BUFFER_SIZE: usize = 960; | ||
| 67 | static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new(); | ||
| 68 | let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]); | ||
| 69 | let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE); | ||
| 70 | |||
| 71 | loop { | ||
| 72 | // trigger transfer of front buffer data to the pio fifo | ||
| 73 | // but don't await the returned future, yet | ||
| 74 | let dma_future = i2s.read(front_buffer); | ||
| 75 | // now await the dma future. once the dma finishes, the next buffer needs to be queued | ||
| 76 | // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us | ||
| 77 | dma_future.await; | ||
| 78 | info!("Received I2S data word: {:?}", &front_buffer); | ||
| 79 | mem::swap(&mut back_buffer, &mut front_buffer); | ||
| 80 | } | ||
| 81 | } | ||
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs index 991510851..102f13c45 100644 --- a/examples/rp235x/src/bin/pio_onewire.rs +++ b/examples/rp235x/src/bin/pio_onewire.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | //! This example shows how you can use PIO to read a `DS18B20` one-wire temperature sensor. | 1 | //! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. |
| 2 | //! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example. | ||
| 2 | 3 | ||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
| @@ -6,9 +7,10 @@ use defmt::*; | |||
| 6 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::bind_interrupts; | 8 | use embassy_rp::bind_interrupts; |
| 8 | use embassy_rp::peripherals::PIO0; | 9 | use embassy_rp::peripherals::PIO0; |
| 9 | use embassy_rp::pio::{self, InterruptHandler, Pio}; | 10 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 10 | use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram}; | 11 | use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; |
| 11 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use heapless::Vec; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 15 | ||
| 14 | bind_interrupts!(struct Irqs { | 16 | bind_interrupts!(struct Irqs { |
| @@ -21,63 +23,66 @@ async fn main(_spawner: Spawner) { | |||
| 21 | let mut pio = Pio::new(p.PIO0, Irqs); | 23 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 22 | 24 | ||
| 23 | let prg = PioOneWireProgram::new(&mut pio.common); | 25 | let prg = PioOneWireProgram::new(&mut pio.common); |
| 24 | let onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); | 26 | let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); |
| 25 | 27 | ||
| 26 | let mut sensor = Ds18b20::new(onewire); | 28 | info!("Starting onewire search"); |
| 27 | 29 | ||
| 28 | loop { | 30 | let mut devices = Vec::<u64, 10>::new(); |
| 29 | sensor.start().await; // Start a new measurement | 31 | let mut search = PioOneWireSearch::new(); |
| 30 | Timer::after_secs(1).await; // Allow 1s for the measurement to finish | 32 | for _ in 0..10 { |
| 31 | match sensor.temperature().await { | 33 | if !search.is_finished() { |
| 32 | Ok(temp) => info!("temp = {:?} deg C", temp), | 34 | if let Some(address) = search.next(&mut onewire).await { |
| 33 | _ => error!("sensor error"), | 35 | if crc8(&address.to_le_bytes()) == 0 { |
| 36 | info!("Found addres: {:x}", address); | ||
| 37 | let _ = devices.push(address); | ||
| 38 | } else { | ||
| 39 | warn!("Found invalid address: {:x}", address); | ||
| 40 | } | ||
| 41 | } | ||
| 34 | } | 42 | } |
| 35 | Timer::after_secs(1).await; | ||
| 36 | } | 43 | } |
| 37 | } | ||
| 38 | 44 | ||
| 39 | /// DS18B20 temperature sensor driver | 45 | info!("Search done, found {} devices", devices.len()); |
| 40 | pub struct Ds18b20<'d, PIO: pio::Instance, const SM: usize> { | ||
| 41 | wire: PioOneWire<'d, PIO, SM>, | ||
| 42 | } | ||
| 43 | 46 | ||
| 44 | impl<'d, PIO: pio::Instance, const SM: usize> Ds18b20<'d, PIO, SM> { | 47 | loop { |
| 45 | pub fn new(wire: PioOneWire<'d, PIO, SM>) -> Self { | 48 | onewire.reset().await; |
| 46 | Self { wire } | 49 | // Skip rom and trigger conversion, we can trigger all devices on the bus immediately |
| 47 | } | 50 | onewire.write_bytes(&[0xCC, 0x44]).await; |
| 48 | 51 | ||
| 49 | /// Calculate CRC8 of the data | 52 | Timer::after_secs(1).await; // Allow 1s for the measurement to finish |
| 50 | fn crc8(data: &[u8]) -> u8 { | 53 | |
| 51 | let mut temp; | 54 | // Read all devices one by one |
| 52 | let mut data_byte; | 55 | for device in &devices { |
| 53 | let mut crc = 0; | 56 | onewire.reset().await; |
| 54 | for b in data { | 57 | onewire.write_bytes(&[0x55]).await; // Match rom |
| 55 | data_byte = *b; | 58 | onewire.write_bytes(&device.to_le_bytes()).await; |
| 56 | for _ in 0..8 { | 59 | onewire.write_bytes(&[0xBE]).await; // Read scratchpad |
| 57 | temp = (crc ^ data_byte) & 0x01; | 60 | |
| 58 | crc >>= 1; | 61 | let mut data = [0; 9]; |
| 59 | if temp != 0 { | 62 | onewire.read_bytes(&mut data).await; |
| 60 | crc ^= 0x8C; | 63 | if crc8(&data) == 0 { |
| 61 | } | 64 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; |
| 62 | data_byte >>= 1; | 65 | info!("Read device {:x}: {} deg C", device, temp); |
| 66 | } else { | ||
| 67 | warn!("Reading device {:x} failed", device); | ||
| 63 | } | 68 | } |
| 64 | } | 69 | } |
| 65 | crc | 70 | Timer::after_secs(1).await; |
| 66 | } | ||
| 67 | |||
| 68 | /// Start a new measurement. Allow at least 1000ms before getting `temperature`. | ||
| 69 | pub async fn start(&mut self) { | ||
| 70 | self.wire.write_bytes(&[0xCC, 0x44]).await; | ||
| 71 | } | 71 | } |
| 72 | } | ||
| 72 | 73 | ||
| 73 | /// Read the temperature. Ensure >1000ms has passed since `start` before calling this. | 74 | fn crc8(data: &[u8]) -> u8 { |
| 74 | pub async fn temperature(&mut self) -> Result<f32, ()> { | 75 | let mut crc = 0; |
| 75 | self.wire.write_bytes(&[0xCC, 0xBE]).await; | 76 | for b in data { |
| 76 | let mut data = [0; 9]; | 77 | let mut data_byte = *b; |
| 77 | self.wire.read_bytes(&mut data).await; | 78 | for _ in 0..8 { |
| 78 | match Self::crc8(&data) == 0 { | 79 | let temp = (crc ^ data_byte) & 0x01; |
| 79 | true => Ok(((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.), | 80 | crc >>= 1; |
| 80 | false => Err(()), | 81 | if temp != 0 { |
| 82 | crc ^= 0x8C; | ||
| 83 | } | ||
| 84 | data_byte >>= 1; | ||
| 81 | } | 85 | } |
| 82 | } | 86 | } |
| 87 | crc | ||
| 83 | } | 88 | } |
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs new file mode 100644 index 000000000..fd076dee0 --- /dev/null +++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | //! This example shows how you can use PIO to read one or more `DS18B20` | ||
| 2 | //! one-wire temperature sensors using parasite power. | ||
| 3 | //! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet. | ||
| 4 | //! For externally powered sensors, use the pio_onewire.rs example. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::peripherals::PIO0; | ||
| 12 | use embassy_rp::pio::{InterruptHandler, Pio}; | ||
| 13 | use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; | ||
| 14 | use embassy_time::Duration; | ||
| 15 | use heapless::Vec; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) { | ||
| 24 | let p = embassy_rp::init(Default::default()); | ||
| 25 | let mut pio = Pio::new(p.PIO0, Irqs); | ||
| 26 | |||
| 27 | let prg = PioOneWireProgram::new(&mut pio.common); | ||
| 28 | let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); | ||
| 29 | |||
| 30 | info!("Starting onewire search"); | ||
| 31 | |||
| 32 | let mut devices = Vec::<u64, 10>::new(); | ||
| 33 | let mut search = PioOneWireSearch::new(); | ||
| 34 | for _ in 0..10 { | ||
| 35 | if !search.is_finished() { | ||
| 36 | if let Some(address) = search.next(&mut onewire).await { | ||
| 37 | if crc8(&address.to_le_bytes()) == 0 { | ||
| 38 | info!("Found address: {:x}", address); | ||
| 39 | let _ = devices.push(address); | ||
| 40 | } else { | ||
| 41 | warn!("Found invalid address: {:x}", address); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | info!("Search done, found {} devices", devices.len()); | ||
| 48 | |||
| 49 | loop { | ||
| 50 | // Read all devices one by one | ||
| 51 | for device in &devices { | ||
| 52 | onewire.reset().await; | ||
| 53 | onewire.write_bytes(&[0x55]).await; // Match rom | ||
| 54 | onewire.write_bytes(&device.to_le_bytes()).await; | ||
| 55 | // 750 ms delay required for default 12-bit resolution. | ||
| 56 | onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await; | ||
| 57 | |||
| 58 | onewire.reset().await; | ||
| 59 | onewire.write_bytes(&[0x55]).await; // Match rom | ||
| 60 | onewire.write_bytes(&device.to_le_bytes()).await; | ||
| 61 | onewire.write_bytes(&[0xBE]).await; // Read scratchpad | ||
| 62 | |||
| 63 | let mut data = [0; 9]; | ||
| 64 | onewire.read_bytes(&mut data).await; | ||
| 65 | if crc8(&data) == 0 { | ||
| 66 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | ||
| 67 | info!("Read device {:x}: {} deg C", device, temp); | ||
| 68 | } else { | ||
| 69 | warn!("Reading device {:x} failed. {:02x}", device, data); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | fn crc8(data: &[u8]) -> u8 { | ||
| 76 | let mut crc = 0; | ||
| 77 | for b in data { | ||
| 78 | let mut data_byte = *b; | ||
| 79 | for _ in 0..8 { | ||
| 80 | let temp = (crc ^ data_byte) & 0x01; | ||
| 81 | crc >>= 1; | ||
| 82 | if temp != 0 { | ||
| 83 | crc ^= 0x8C; | ||
| 84 | } | ||
| 85 | data_byte >>= 1; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | crc | ||
| 89 | } | ||
diff --git a/examples/rp235x/src/bin/pio_rotary_encoder.rs b/examples/rp235x/src/bin/pio_rotary_encoder.rs index e820d316d..610d1a40b 100644 --- a/examples/rp235x/src/bin/pio_rotary_encoder.rs +++ b/examples/rp235x/src/bin/pio_rotary_encoder.rs | |||
| @@ -50,6 +50,6 @@ async fn main(spawner: Spawner) { | |||
| 50 | let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); | 50 | let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); |
| 51 | let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); | 51 | let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); |
| 52 | 52 | ||
| 53 | spawner.must_spawn(encoder_0(encoder0)); | 53 | spawner.spawn(encoder_0(encoder0).unwrap()); |
| 54 | spawner.must_spawn(encoder_1(encoder1)); | 54 | spawner.spawn(encoder_1(encoder1).unwrap()); |
| 55 | } | 55 | } |
diff --git a/examples/rp235x/src/bin/psram.rs b/examples/rp235x/src/bin/psram.rs new file mode 100644 index 000000000..716ac7695 --- /dev/null +++ b/examples/rp235x/src/bin/psram.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | //! This example tests an APS6404L PSRAM chip connected to the RP235x | ||
| 2 | //! It fills the PSRAM with alternating patterns and reads back a value | ||
| 3 | //! | ||
| 4 | //! In this example, the PSRAM CS is connected to Pin 0. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use core::slice; | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let config = embassy_rp::config::Config::default(); | ||
| 19 | let p = embassy_rp::init(config); | ||
| 20 | let psram_config = embassy_rp::psram::Config::aps6404l(); | ||
| 21 | let psram = embassy_rp::psram::Psram::new(embassy_rp::qmi_cs1::QmiCs1::new(p.QMI_CS1, p.PIN_0), psram_config); | ||
| 22 | |||
| 23 | let Ok(psram) = psram else { | ||
| 24 | error!("PSRAM not found"); | ||
| 25 | loop { | ||
| 26 | Timer::after_secs(1).await; | ||
| 27 | } | ||
| 28 | }; | ||
| 29 | |||
| 30 | let psram_slice = unsafe { | ||
| 31 | let psram_ptr = psram.base_address(); | ||
| 32 | let slice: &'static mut [u8] = slice::from_raw_parts_mut(psram_ptr, psram.size() as usize); | ||
| 33 | slice | ||
| 34 | }; | ||
| 35 | |||
| 36 | loop { | ||
| 37 | psram_slice.fill(0x55); | ||
| 38 | info!("PSRAM filled with 0x55"); | ||
| 39 | let at_addr = psram_slice[0x100]; | ||
| 40 | info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr); | ||
| 41 | Timer::after_secs(1).await; | ||
| 42 | |||
| 43 | psram_slice.fill(0xAA); | ||
| 44 | info!("PSRAM filled with 0xAA"); | ||
| 45 | let at_addr = psram_slice[0x100]; | ||
| 46 | info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr); | ||
| 47 | Timer::after_secs(1).await; | ||
| 48 | } | ||
| 49 | } | ||
diff --git a/examples/rp235x/src/bin/pwm.rs b/examples/rp235x/src/bin/pwm.rs index da1acc18a..289480c85 100644 --- a/examples/rp235x/src/bin/pwm.rs +++ b/examples/rp235x/src/bin/pwm.rs | |||
| @@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 18 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 19 | async fn main(spawner: Spawner) { | 19 | async fn main(spawner: Spawner) { |
| 20 | let p = embassy_rp::init(Default::default()); | 20 | let p = embassy_rp::init(Default::default()); |
| 21 | spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); | 21 | spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap()); |
| 22 | spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); | 22 | spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap()); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | /// Demonstrate PWM by modifying & applying the config | 25 | /// Demonstrate PWM by modifying & applying the config |
diff --git a/examples/rp235x/src/bin/shared_bus.rs b/examples/rp235x/src/bin/shared_bus.rs index 9267dfccb..db7566b1a 100644 --- a/examples/rp235x/src/bin/shared_bus.rs +++ b/examples/rp235x/src/bin/shared_bus.rs | |||
| @@ -35,8 +35,8 @@ async fn main(spawner: Spawner) { | |||
| 35 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); | 35 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); |
| 36 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); | 36 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); |
| 37 | 37 | ||
| 38 | spawner.must_spawn(i2c_task_a(i2c_bus)); | 38 | spawner.spawn(i2c_task_a(i2c_bus).unwrap()); |
| 39 | spawner.must_spawn(i2c_task_b(i2c_bus)); | 39 | spawner.spawn(i2c_task_b(i2c_bus).unwrap()); |
| 40 | 40 | ||
| 41 | // Shared SPI bus | 41 | // Shared SPI bus |
| 42 | let spi_cfg = spi::Config::default(); | 42 | let spi_cfg = spi::Config::default(); |
| @@ -48,8 +48,8 @@ async fn main(spawner: Spawner) { | |||
| 48 | let cs_a = Output::new(p.PIN_0, Level::High); | 48 | let cs_a = Output::new(p.PIN_0, Level::High); |
| 49 | let cs_b = Output::new(p.PIN_1, Level::High); | 49 | let cs_b = Output::new(p.PIN_1, Level::High); |
| 50 | 50 | ||
| 51 | spawner.must_spawn(spi_task_a(spi_bus, cs_a)); | 51 | spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap()); |
| 52 | spawner.must_spawn(spi_task_b(spi_bus, cs_b)); | 52 | spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap()); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #[embassy_executor::task] | 55 | #[embassy_executor::task] |
diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs index 497c4f845..d4c89946b 100644 --- a/examples/rp235x/src/bin/sharing.rs +++ b/examples/rp235x/src/bin/sharing.rs | |||
| @@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt}; | |||
| 27 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 27 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 28 | use embassy_sync::{blocking_mutex, mutex}; | 28 | use embassy_sync::{blocking_mutex, mutex}; |
| 29 | use embassy_time::{Duration, Ticker}; | 29 | use embassy_time::{Duration, Ticker}; |
| 30 | use rand::RngCore; | ||
| 31 | use static_cell::{ConstStaticCell, StaticCell}; | 30 | use static_cell::{ConstStaticCell, StaticCell}; |
| 32 | use {defmt_rtt as _, panic_probe as _}; | 31 | use {defmt_rtt as _, panic_probe as _}; |
| 33 | 32 | ||
| @@ -69,7 +68,7 @@ fn main() -> ! { | |||
| 69 | // High-priority executor: runs in interrupt mode | 68 | // High-priority executor: runs in interrupt mode |
| 70 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | 69 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); |
| 71 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); | 70 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); |
| 72 | spawner.must_spawn(task_a(uart)); | 71 | spawner.spawn(task_a(uart).unwrap()); |
| 73 | 72 | ||
| 74 | // Low priority executor: runs in thread mode | 73 | // Low priority executor: runs in thread mode |
| 75 | let executor = EXECUTOR_LOW.init(Executor::new()); | 74 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| @@ -84,8 +83,8 @@ fn main() -> ! { | |||
| 84 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); | 83 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); |
| 85 | let ref_cell = REF_CELL.take(); | 84 | let ref_cell = REF_CELL.take(); |
| 86 | 85 | ||
| 87 | spawner.must_spawn(task_b(uart, cell, ref_cell)); | 86 | spawner.spawn(task_b(uart, cell, ref_cell).unwrap()); |
| 88 | spawner.must_spawn(task_c(cell, ref_cell)); | 87 | spawner.spawn(task_c(cell, ref_cell).unwrap()); |
| 89 | }); | 88 | }); |
| 90 | } | 89 | } |
| 91 | 90 | ||
diff --git a/examples/rp235x/src/bin/trng.rs b/examples/rp235x/src/bin/trng.rs index ad19aef3e..100d6b104 100644 --- a/examples/rp235x/src/bin/trng.rs +++ b/examples/rp235x/src/bin/trng.rs | |||
| @@ -10,7 +10,6 @@ use embassy_rp::gpio::{Level, Output}; | |||
| 10 | use embassy_rp::peripherals::TRNG; | 10 | use embassy_rp::peripherals::TRNG; |
| 11 | use embassy_rp::trng::Trng; | 11 | use embassy_rp::trng::Trng; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use rand::RngCore; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 14 | ||
| 16 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| @@ -33,8 +32,8 @@ async fn main(_spawner: Spawner) { | |||
| 33 | info!("Random bytes async {}", &randomness); | 32 | info!("Random bytes async {}", &randomness); |
| 34 | trng.blocking_fill_bytes(&mut randomness); | 33 | trng.blocking_fill_bytes(&mut randomness); |
| 35 | info!("Random bytes blocking {}", &randomness); | 34 | info!("Random bytes blocking {}", &randomness); |
| 36 | let random_u32 = trng.next_u32(); | 35 | let random_u32 = trng.blocking_next_u32(); |
| 37 | let random_u64 = trng.next_u64(); | 36 | let random_u64 = trng.blocking_next_u64(); |
| 38 | info!("Random u32 {} u64 {}", random_u32, random_u64); | 37 | info!("Random u32 {} u64 {}", random_u32, random_u64); |
| 39 | // Random number of blinks between 0 and 31 | 38 | // Random number of blinks between 0 and 31 |
| 40 | let blinks = random_u32 % 32; | 39 | let blinks = random_u32 % 32; |
diff --git a/examples/rp235x/src/bin/uart_buffered_split.rs b/examples/rp235x/src/bin/uart_buffered_split.rs index 7cad09f9b..061be873d 100644 --- a/examples/rp235x/src/bin/uart_buffered_split.rs +++ b/examples/rp235x/src/bin/uart_buffered_split.rs | |||
| @@ -33,7 +33,7 @@ async fn main(spawner: Spawner) { | |||
| 33 | let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); | 33 | let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); |
| 34 | let (mut tx, rx) = uart.split(); | 34 | let (mut tx, rx) = uart.split(); |
| 35 | 35 | ||
| 36 | unwrap!(spawner.spawn(reader(rx))); | 36 | spawner.spawn(unwrap!(reader(rx))); |
| 37 | 37 | ||
| 38 | info!("Writing..."); | 38 | info!("Writing..."); |
| 39 | loop { | 39 | loop { |
diff --git a/examples/rp235x/src/bin/uart_unidir.rs b/examples/rp235x/src/bin/uart_unidir.rs index 45c9c8407..0c80d24c9 100644 --- a/examples/rp235x/src/bin/uart_unidir.rs +++ b/examples/rp235x/src/bin/uart_unidir.rs | |||
| @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) { | |||
| 27 | let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); | 27 | let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); |
| 28 | let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); | 28 | let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(reader(uart_rx))); | 30 | spawner.spawn(unwrap!(reader(uart_rx))); |
| 31 | 31 | ||
| 32 | info!("Writing..."); | 32 | info!("Writing..."); |
| 33 | loop { | 33 | loop { |
diff --git a/examples/rp235x/src/bin/usb_webusb.rs b/examples/rp235x/src/bin/usb_webusb.rs index 75d28c853..a68163b61 100644 --- a/examples/rp235x/src/bin/usb_webusb.rs +++ b/examples/rp235x/src/bin/usb_webusb.rs | |||
| @@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> { | |||
| 125 | let mut iface = func.interface(); | 125 | let mut iface = func.interface(); |
| 126 | let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); | 126 | let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); |
| 127 | 127 | ||
| 128 | let write_ep = alt.endpoint_bulk_in(config.max_packet_size); | 128 | let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size); |
| 129 | let read_ep = alt.endpoint_bulk_out(config.max_packet_size); | 129 | let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size); |
| 130 | 130 | ||
| 131 | WebEndpoints { write_ep, read_ep } | 131 | WebEndpoints { write_ep, read_ep } |
| 132 | } | 132 | } |
diff --git a/examples/rp235x/src/bin/zerocopy.rs b/examples/rp235x/src/bin/zerocopy.rs index 086c86cac..62ba4cfb8 100644 --- a/examples/rp235x/src/bin/zerocopy.rs +++ b/examples/rp235x/src/bin/zerocopy.rs | |||
| @@ -52,8 +52,8 @@ async fn main(spawner: Spawner) { | |||
| 52 | let channel = CHANNEL.init(Channel::new(buf)); | 52 | let channel = CHANNEL.init(Channel::new(buf)); |
| 53 | let (sender, receiver) = channel.split(); | 53 | let (sender, receiver) = channel.split(); |
| 54 | 54 | ||
| 55 | spawner.must_spawn(consumer(receiver)); | 55 | spawner.spawn(consumer(receiver).unwrap()); |
| 56 | spawner.must_spawn(producer(sender, adc_parts)); | 56 | spawner.spawn(producer(sender, adc_parts).unwrap()); |
| 57 | 57 | ||
| 58 | let mut ticker = Ticker::every(Duration::from_secs(1)); | 58 | let mut ticker = Ticker::every(Duration::from_secs(1)); |
| 59 | loop { | 59 | loop { |
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index f00953167..449c5ddca 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -3,14 +3,15 @@ edition = "2021" | |||
| 3 | name = "embassy-std-examples" | 3 | name = "embassy-std-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } | 9 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } | 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "std", ] } |
| 11 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } | 12 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } |
| 12 | embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } | 13 | embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } |
| 13 | embassy-net-ppp = { version = "0.2.0", path = "../../embassy-net-ppp", features = ["log"]} | 14 | embassy-net-ppp = { version = "0.2.1", path = "../../embassy-net-ppp", features = ["log"]} |
| 14 | embedded-io-async = { version = "0.6.1" } | 15 | embedded-io-async = { version = "0.6.1" } |
| 15 | embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] } | 16 | embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] } |
| 16 | critical-section = { version = "1.1", features = ["std"] } | 17 | critical-section = { version = "1.1", features = ["std"] } |
| @@ -21,9 +22,14 @@ futures = { version = "0.3.17" } | |||
| 21 | log = "0.4.14" | 22 | log = "0.4.14" |
| 22 | nix = "0.26.2" | 23 | nix = "0.26.2" |
| 23 | clap = { version = "3.0.0-beta.5", features = ["derive"] } | 24 | clap = { version = "3.0.0-beta.5", features = ["derive"] } |
| 24 | rand_core = { version = "0.6.3", features = ["std"] } | 25 | rand_core = { version = "0.9.1", features = ["std", "os_rng"] } |
| 25 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 26 | static_cell = "2" | 27 | static_cell = "2" |
| 27 | 28 | ||
| 28 | [profile.release] | 29 | [profile.release] |
| 29 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { artifact-dir = "out/examples/std" } | ||
| 35 | ] | ||
diff --git a/examples/std/README.md b/examples/std/README.md index dcc152fc2..ac2c2a1a6 100644 --- a/examples/std/README.md +++ b/examples/std/README.md | |||
| @@ -1,19 +1,128 @@ | |||
| 1 | 1 | ||
| 2 | ## Running the `embassy-net` examples | 2 | ## Running the `embassy-net` examples |
| 3 | 3 | ||
| 4 | First, create the tap99 interface. (The number was chosen to | 4 | To run `net`, `tcp_accept`, `net_udp` and `net_dns` examples you will need a tap interface. Before running these examples, create the tap99 interface. (The number was chosen to |
| 5 | hopefully not collide with anything.) You only need to do | 5 | hopefully not collide with anything.) You only need to do this once every time you reboot your computer. |
| 6 | this once. | ||
| 7 | 6 | ||
| 8 | ```sh | 7 | ```sh |
| 8 | cd $EMBASSY_ROOT/examples/std/ | ||
| 9 | sudo sh tap.sh | 9 | sudo sh tap.sh |
| 10 | ``` | 10 | ``` |
| 11 | 11 | ||
| 12 | Second, have something listening there. For example `nc -lp 8000` | 12 | The example `net_ppp` requires different steps that are detailed in its section. |
| 13 | |||
| 14 | ### `net` example | ||
| 15 | |||
| 16 | For this example, you need to have something listening in the correct port. For example `nc -lp 8000`. | ||
| 13 | 17 | ||
| 14 | Then run the example located in the `examples` folder: | 18 | Then run the example located in the `examples` folder: |
| 15 | 19 | ||
| 16 | ```sh | 20 | ```sh |
| 17 | cd $EMBASSY_ROOT/examples/std/ | 21 | cd $EMBASSY_ROOT/examples/std/ |
| 18 | sudo cargo run --bin net -- --tap tap99 --static-ip | 22 | cargo run --bin net -- --tap tap99 --static-ip |
| 23 | ``` | ||
| 24 | ### `tcp_accept` example | ||
| 25 | |||
| 26 | This example listen for a tcp connection. | ||
| 27 | |||
| 28 | First run the example located in the `examples` folder: | ||
| 29 | |||
| 30 | ```sh | ||
| 31 | cd $EMBASSY_ROOT/examples/std/ | ||
| 32 | cargo run --bin tcp_accept -- --tap tap99 --static-ip | ||
| 33 | ``` | ||
| 34 | |||
| 35 | Then open a connection to the port. For example `nc 192.168.69.2 9999`. | ||
| 36 | |||
| 37 | ### `net_udp` example | ||
| 38 | |||
| 39 | This example listen for a udp connection. | ||
| 40 | |||
| 41 | First run the example located in the `examples` folder: | ||
| 42 | |||
| 43 | ```sh | ||
| 44 | cd $EMBASSY_ROOT/examples/std/ | ||
| 45 | cargo run --bin net_udp -- --tap tap99 --static-ip | ||
| 46 | ``` | ||
| 47 | |||
| 48 | Then open a connection to the port. For example `nc -u 192.168.69.2 9400`. | ||
| 49 | |||
| 50 | ### `net_dns` example | ||
| 51 | |||
| 52 | This example queries a `DNS` for the IP address of `www.example.com`. | ||
| 53 | |||
| 54 | In order to achieve this, the `tap99` interface requires configuring tap99 as a gateway device temporarily. | ||
| 55 | |||
| 56 | For example, in Ubuntu you can do this by: | ||
| 57 | |||
| 58 | 1. Identifying your default route device. In the next example `eth0` | ||
| 59 | |||
| 60 | ```sh | ||
| 61 | ip r | grep "default" | ||
| 62 | default via 192.168.2.1 dev eth0 proto kernel metric 35 | ||
| 63 | ``` | ||
| 64 | |||
| 65 | 2. Enabling temporarily IP Forwarding: | ||
| 66 | |||
| 67 | ```sh | ||
| 68 | sudo sysctl -w net.ipv4.ip_forward=1 | ||
| 69 | ``` | ||
| 70 | |||
| 71 | 3. Configuring NAT to mascarade traffic from `tap99` to `eth0` | ||
| 72 | |||
| 73 | ```sh | ||
| 74 | sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE | ||
| 75 | sudo iptables -A FORWARD -i tap99 -j ACCEPT | ||
| 76 | sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT | ||
| 77 | ``` | ||
| 78 | |||
| 79 | 4. Then you can run the example located in the `examples` folder: | ||
| 80 | |||
| 81 | ```sh | ||
| 82 | cd $EMBASSY_ROOT/examples/std/ | ||
| 83 | cargo run --bin net_dns -- --tap tap99 --static-ip | ||
| 84 | ``` | ||
| 85 | |||
| 86 | ### `net_ppp` example | ||
| 87 | |||
| 88 | This example establish a Point-to-Point Protocol (PPP) connection that can be used, for example, for connecting to internet through a 4G modem via a serial channel. | ||
| 89 | |||
| 90 | The example creates a PPP bridge over a virtual serial channel between `pty1` and `pty2` for the example code and a PPP server running on the same computer. | ||
| 91 | |||
| 92 | To run this example you will need: | ||
| 93 | - ppp (pppd server) | ||
| 94 | - socat (socket CAT) | ||
| 95 | |||
| 96 | To run the examples you may follow the next steps: | ||
| 97 | |||
| 98 | 1. Save the PPP server configuration: | ||
| 99 | ```sh | ||
| 100 | sudo sh -c 'echo "myuser $(hostname) mypass 192.168.7.10" >> /etc/ppp/pap-secrets' | ||
| 101 | ``` | ||
| 102 | |||
| 103 | 2. Create a files `pty1` and `pty2` and link them | ||
| 104 | ```sh | ||
| 105 | cd $EMBASSY_ROOT/examples/std/ | ||
| 106 | socat -v -x PTY,link=pty1,rawer PTY,link=pty2,rawer | ||
| 107 | ``` | ||
| 108 | |||
| 109 | 3. open a second terminal and start the PPP server: | ||
| 110 | ```sh | ||
| 111 | cd $EMBASSY_ROOT/examples/std/ | ||
| 112 | sudo pppd $PWD/pty1 115200 192.168.7.1: ms-dns 8.8.4.4 ms-dns 8.8.8.8 nodetach debug local persist silent | ||
| 113 | ``` | ||
| 114 | |||
| 115 | 4. Open a third terminal and run the example | ||
| 116 | ```sh | ||
| 117 | cd $EMBASSY_ROOT/examples/std/ | ||
| 118 | RUST_LOG=trace cargo run --bin net_ppp -- --device pty2 | ||
| 119 | ``` | ||
| 120 | 5. Observe the output in the second and third terminal | ||
| 121 | 6. Open one last terminal to interact with `net_ppp` example through the PPP connection | ||
| 122 | ```sh | ||
| 123 | # ping the net_ppp client | ||
| 124 | ping 192.168.7.10 | ||
| 125 | # open an tcp connection | ||
| 126 | nc 192.168.7.10 1234 | ||
| 127 | # Type anything and observe the output in the different terminals | ||
| 19 | ``` | 128 | ``` |
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 6e50b1a01..fd7b6c930 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs | |||
| @@ -9,7 +9,7 @@ use embassy_time::Duration; | |||
| 9 | use embedded_io_async::Write; | 9 | use embedded_io_async::Write; |
| 10 | use heapless::Vec; | 10 | use heapless::Vec; |
| 11 | use log::*; | 11 | use log::*; |
| 12 | use rand_core::{OsRng, RngCore}; | 12 | use rand_core::{OsRng, TryRngCore}; |
| 13 | use static_cell::StaticCell; | 13 | use static_cell::StaticCell; |
| 14 | 14 | ||
| 15 | #[derive(Parser)] | 15 | #[derive(Parser)] |
| @@ -48,7 +48,7 @@ async fn main_task(spawner: Spawner) { | |||
| 48 | 48 | ||
| 49 | // Generate random seed | 49 | // Generate random seed |
| 50 | let mut seed = [0; 8]; | 50 | let mut seed = [0; 8]; |
| 51 | OsRng.fill_bytes(&mut seed); | 51 | OsRng.try_fill_bytes(&mut seed).unwrap(); |
| 52 | let seed = u64::from_le_bytes(seed); | 52 | let seed = u64::from_le_bytes(seed); |
| 53 | 53 | ||
| 54 | // Init network stack | 54 | // Init network stack |
| @@ -56,7 +56,7 @@ async fn main_task(spawner: Spawner) { | |||
| 56 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 56 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 57 | 57 | ||
| 58 | // Launch network task | 58 | // Launch network task |
| 59 | spawner.spawn(net_task(runner)).unwrap(); | 59 | spawner.spawn(net_task(runner).unwrap()); |
| 60 | 60 | ||
| 61 | // Then we can use it! | 61 | // Then we can use it! |
| 62 | let mut rx_buffer = [0; 4096]; | 62 | let mut rx_buffer = [0; 4096]; |
| @@ -95,6 +95,6 @@ fn main() { | |||
| 95 | 95 | ||
| 96 | let executor = EXECUTOR.init(Executor::new()); | 96 | let executor = EXECUTOR.init(Executor::new()); |
| 97 | executor.run(|spawner| { | 97 | executor.run(|spawner| { |
| 98 | spawner.spawn(main_task(spawner)).unwrap(); | 98 | spawner.spawn(main_task(spawner).unwrap()); |
| 99 | }); | 99 | }); |
| 100 | } | 100 | } |
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index a42c5dbb7..dff704b86 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs | |||
| @@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; | |||
| 5 | use embassy_net_tuntap::TunTapDevice; | 5 | use embassy_net_tuntap::TunTapDevice; |
| 6 | use heapless::Vec; | 6 | use heapless::Vec; |
| 7 | use log::*; | 7 | use log::*; |
| 8 | use rand_core::{OsRng, RngCore}; | 8 | use rand_core::{OsRng, TryRngCore}; |
| 9 | use static_cell::StaticCell; | 9 | use static_cell::StaticCell; |
| 10 | 10 | ||
| 11 | #[derive(Parser)] | 11 | #[derive(Parser)] |
| @@ -45,7 +45,7 @@ async fn main_task(spawner: Spawner) { | |||
| 45 | 45 | ||
| 46 | // Generate random seed | 46 | // Generate random seed |
| 47 | let mut seed = [0; 8]; | 47 | let mut seed = [0; 8]; |
| 48 | OsRng.fill_bytes(&mut seed); | 48 | OsRng.try_fill_bytes(&mut seed).unwrap(); |
| 49 | let seed = u64::from_le_bytes(seed); | 49 | let seed = u64::from_le_bytes(seed); |
| 50 | 50 | ||
| 51 | // Init network stack | 51 | // Init network stack |
| @@ -53,7 +53,7 @@ async fn main_task(spawner: Spawner) { | |||
| 53 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 53 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 54 | 54 | ||
| 55 | // Launch network task | 55 | // Launch network task |
| 56 | spawner.spawn(net_task(runner)).unwrap(); | 56 | spawner.spawn(net_task(runner).unwrap()); |
| 57 | 57 | ||
| 58 | let host = "example.com"; | 58 | let host = "example.com"; |
| 59 | info!("querying host {:?}...", host); | 59 | info!("querying host {:?}...", host); |
| @@ -78,6 +78,6 @@ fn main() { | |||
| 78 | 78 | ||
| 79 | let executor = EXECUTOR.init(Executor::new()); | 79 | let executor = EXECUTOR.init(Executor::new()); |
| 80 | executor.run(|spawner| { | 80 | executor.run(|spawner| { |
| 81 | spawner.spawn(main_task(spawner)).unwrap(); | 81 | spawner.spawn(main_task(spawner).unwrap()); |
| 82 | }); | 82 | }); |
| 83 | } | 83 | } |
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index f667e8d4c..82272c798 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs | |||
| @@ -23,7 +23,7 @@ use futures::io::BufReader; | |||
| 23 | use heapless::Vec; | 23 | use heapless::Vec; |
| 24 | use log::*; | 24 | use log::*; |
| 25 | use nix::sys::termios; | 25 | use nix::sys::termios; |
| 26 | use rand_core::{OsRng, RngCore}; | 26 | use rand_core::{OsRng, TryRngCore}; |
| 27 | use static_cell::StaticCell; | 27 | use static_cell::StaticCell; |
| 28 | 28 | ||
| 29 | use crate::serial_port::SerialPort; | 29 | use crate::serial_port::SerialPort; |
| @@ -89,7 +89,7 @@ async fn main_task(spawner: Spawner) { | |||
| 89 | 89 | ||
| 90 | // Generate random seed | 90 | // Generate random seed |
| 91 | let mut seed = [0; 8]; | 91 | let mut seed = [0; 8]; |
| 92 | OsRng.fill_bytes(&mut seed); | 92 | OsRng.try_fill_bytes(&mut seed).unwrap(); |
| 93 | let seed = u64::from_le_bytes(seed); | 93 | let seed = u64::from_le_bytes(seed); |
| 94 | 94 | ||
| 95 | // Init network stack | 95 | // Init network stack |
| @@ -102,8 +102,8 @@ async fn main_task(spawner: Spawner) { | |||
| 102 | ); | 102 | ); |
| 103 | 103 | ||
| 104 | // Launch network task | 104 | // Launch network task |
| 105 | spawner.spawn(net_task(net_runner)).unwrap(); | 105 | spawner.spawn(net_task(net_runner).unwrap()); |
| 106 | spawner.spawn(ppp_task(stack, runner, port)).unwrap(); | 106 | spawner.spawn(ppp_task(stack, runner, port).unwrap()); |
| 107 | 107 | ||
| 108 | // Then we can use it! | 108 | // Then we can use it! |
| 109 | let mut rx_buffer = [0; 4096]; | 109 | let mut rx_buffer = [0; 4096]; |
| @@ -160,6 +160,6 @@ fn main() { | |||
| 160 | 160 | ||
| 161 | let executor = EXECUTOR.init(Executor::new()); | 161 | let executor = EXECUTOR.init(Executor::new()); |
| 162 | executor.run(|spawner| { | 162 | executor.run(|spawner| { |
| 163 | spawner.spawn(main_task(spawner)).unwrap(); | 163 | spawner.spawn(main_task(spawner).unwrap()); |
| 164 | }); | 164 | }); |
| 165 | } | 165 | } |
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 02d4d3efb..c5c4da65f 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs | |||
| @@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; | |||
| 5 | use embassy_net_tuntap::TunTapDevice; | 5 | use embassy_net_tuntap::TunTapDevice; |
| 6 | use heapless::Vec; | 6 | use heapless::Vec; |
| 7 | use log::*; | 7 | use log::*; |
| 8 | use rand_core::{OsRng, RngCore}; | 8 | use rand_core::{OsRng, TryRngCore}; |
| 9 | use static_cell::StaticCell; | 9 | use static_cell::StaticCell; |
| 10 | 10 | ||
| 11 | #[derive(Parser)] | 11 | #[derive(Parser)] |
| @@ -44,7 +44,7 @@ async fn main_task(spawner: Spawner) { | |||
| 44 | 44 | ||
| 45 | // Generate random seed | 45 | // Generate random seed |
| 46 | let mut seed = [0; 8]; | 46 | let mut seed = [0; 8]; |
| 47 | OsRng.fill_bytes(&mut seed); | 47 | OsRng.try_fill_bytes(&mut seed).unwrap(); |
| 48 | let seed = u64::from_le_bytes(seed); | 48 | let seed = u64::from_le_bytes(seed); |
| 49 | 49 | ||
| 50 | // Init network stack | 50 | // Init network stack |
| @@ -52,7 +52,7 @@ async fn main_task(spawner: Spawner) { | |||
| 52 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 52 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 53 | 53 | ||
| 54 | // Launch network task | 54 | // Launch network task |
| 55 | spawner.spawn(net_task(runner)).unwrap(); | 55 | spawner.spawn(net_task(runner).unwrap()); |
| 56 | 56 | ||
| 57 | // Then we can use it! | 57 | // Then we can use it! |
| 58 | let mut rx_meta = [PacketMetadata::EMPTY; 16]; | 58 | let mut rx_meta = [PacketMetadata::EMPTY; 16]; |
| @@ -86,6 +86,6 @@ fn main() { | |||
| 86 | 86 | ||
| 87 | let executor = EXECUTOR.init(Executor::new()); | 87 | let executor = EXECUTOR.init(Executor::new()); |
| 88 | executor.run(|spawner| { | 88 | executor.run(|spawner| { |
| 89 | spawner.spawn(main_task(spawner)).unwrap(); | 89 | spawner.spawn(main_task(spawner).unwrap()); |
| 90 | }); | 90 | }); |
| 91 | } | 91 | } |
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs index 10c85511d..1ed9997c4 100644 --- a/examples/std/src/bin/serial.rs +++ b/examples/std/src/bin/serial.rs | |||
| @@ -50,6 +50,6 @@ fn main() { | |||
| 50 | 50 | ||
| 51 | let executor = EXECUTOR.init(Executor::new()); | 51 | let executor = EXECUTOR.init(Executor::new()); |
| 52 | executor.run(|spawner| { | 52 | executor.run(|spawner| { |
| 53 | spawner.spawn(run()).unwrap(); | 53 | spawner.spawn(run().unwrap()); |
| 54 | }); | 54 | }); |
| 55 | } | 55 | } |
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 18646a083..77886f471 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs | |||
| @@ -7,7 +7,7 @@ use embassy_time::{Duration, Timer}; | |||
| 7 | use embedded_io_async::Write as _; | 7 | use embedded_io_async::Write as _; |
| 8 | use heapless::Vec; | 8 | use heapless::Vec; |
| 9 | use log::*; | 9 | use log::*; |
| 10 | use rand_core::{OsRng, RngCore}; | 10 | use rand_core::{OsRng, TryRngCore}; |
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | 12 | ||
| 13 | #[derive(Parser)] | 13 | #[derive(Parser)] |
| @@ -46,7 +46,7 @@ async fn main_task(spawner: Spawner) { | |||
| 46 | 46 | ||
| 47 | // Generate random seed | 47 | // Generate random seed |
| 48 | let mut seed = [0; 8]; | 48 | let mut seed = [0; 8]; |
| 49 | OsRng.fill_bytes(&mut seed); | 49 | OsRng.try_fill_bytes(&mut seed).unwrap(); |
| 50 | let seed = u64::from_le_bytes(seed); | 50 | let seed = u64::from_le_bytes(seed); |
| 51 | 51 | ||
| 52 | // Init network stack | 52 | // Init network stack |
| @@ -54,7 +54,7 @@ async fn main_task(spawner: Spawner) { | |||
| 54 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 54 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 55 | 55 | ||
| 56 | // Launch network task | 56 | // Launch network task |
| 57 | spawner.spawn(net_task(runner)).unwrap(); | 57 | spawner.spawn(net_task(runner).unwrap()); |
| 58 | 58 | ||
| 59 | // Then we can use it! | 59 | // Then we can use it! |
| 60 | let mut rx_buffer = [0; 4096]; | 60 | let mut rx_buffer = [0; 4096]; |
| @@ -101,6 +101,6 @@ fn main() { | |||
| 101 | 101 | ||
| 102 | let executor = EXECUTOR.init(Executor::new()); | 102 | let executor = EXECUTOR.init(Executor::new()); |
| 103 | executor.run(|spawner| { | 103 | executor.run(|spawner| { |
| 104 | spawner.spawn(main_task(spawner)).unwrap(); | 104 | spawner.spawn(main_task(spawner).unwrap()); |
| 105 | }); | 105 | }); |
| 106 | } | 106 | } |
diff --git a/examples/std/src/bin/tick.rs b/examples/std/src/bin/tick.rs index f23cf3549..16b82c82b 100644 --- a/examples/std/src/bin/tick.rs +++ b/examples/std/src/bin/tick.rs | |||
| @@ -17,5 +17,5 @@ async fn main(spawner: Spawner) { | |||
| 17 | .format_timestamp_nanos() | 17 | .format_timestamp_nanos() |
| 18 | .init(); | 18 | .init(); |
| 19 | 19 | ||
| 20 | spawner.spawn(run()).unwrap(); | 20 | spawner.spawn(run().unwrap()); |
| 21 | } | 21 | } |
diff --git a/examples/std/tap.sh b/examples/std/tap.sh index 39d92a099..fb89d2381 100644 --- a/examples/std/tap.sh +++ b/examples/std/tap.sh | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ip tuntap add name tap99 mode tap user $USER | 1 | ip tuntap add name tap99 mode tap user $SUDO_USER |
| 2 | ip link set tap99 up | 2 | ip link set tap99 up |
| 3 | ip addr add 192.168.69.100/24 dev tap99 | 3 | ip addr add 192.168.69.100/24 dev tap99 |
| 4 | ip -6 addr add fe80::100/64 dev tap99 | 4 | ip -6 addr add fe80::100/64 dev tap99 |
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 767b742f7..bb7b57496 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml | |||
| @@ -3,22 +3,29 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32c0-examples" | 3 | name = "embassy-stm32c0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32c031c6 to your chip name, if necessary. | 9 | # Change stm32c031c6 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "1.0.0" |
| 16 | 17 | ||
| 17 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 18 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 18 | cortex-m-rt = "0.7.0" | 19 | cortex-m-rt = "0.7.0" |
| 19 | embedded-hal = "0.2.6" | 20 | embedded-hal = "0.2.6" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | heapless = { version = "0.8", default-features = false } | 22 | heapless = { version = "0.8", default-features = false } |
| 23 | chrono = { version = "^0.4", default-features = false} | ||
| 22 | 24 | ||
| 23 | [profile.release] | 25 | [profile.release] |
| 24 | debug = 2 | 26 | debug = 2 |
| 27 | |||
| 28 | [package.metadata.embassy] | ||
| 29 | build = [ | ||
| 30 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32c0" } | ||
| 31 | ] | ||
diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs new file mode 100644 index 000000000..82d8a37ba --- /dev/null +++ b/examples/stm32c0/src/bin/rtc.rs | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | ||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 8 | use embassy_stm32::Config; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let config = Config::default(); | ||
| 15 | let p = embassy_stm32::init(config); | ||
| 16 | |||
| 17 | info!("Hello World!"); | ||
| 18 | |||
| 19 | let now = NaiveDate::from_ymd_opt(2020, 5, 15) | ||
| 20 | .unwrap() | ||
| 21 | .and_hms_opt(10, 30, 15) | ||
| 22 | .unwrap(); | ||
| 23 | |||
| 24 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 25 | |||
| 26 | rtc.set_datetime(now.into()).expect("datetime not set"); | ||
| 27 | |||
| 28 | loop { | ||
| 29 | let now: NaiveDateTime = rtc.now().unwrap().into(); | ||
| 30 | |||
| 31 | info!("{}", now.and_utc().timestamp()); | ||
| 32 | |||
| 33 | Timer::after_millis(1000).await; | ||
| 34 | } | ||
| 35 | } | ||
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 932a97dc8..11ecbe3c2 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml | |||
| @@ -3,20 +3,26 @@ name = "embassy-stm32f0-examples" | |||
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f091rc to your chip name, if necessary. | 9 | # Change stm32f091rc to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } |
| 10 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 11 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 11 | cortex-m-rt = "0.7.0" | 12 | cortex-m-rt = "0.7.0" |
| 12 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.4" | 14 | defmt-rtt = "1.0.0" |
| 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 15 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 15 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 16 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 16 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 17 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 17 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 18 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 18 | static_cell = "2" | 19 | static_cell = "2" |
| 19 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | 20 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } |
| 20 | 21 | ||
| 21 | [profile.release] | 22 | [profile.release] |
| 22 | debug = 2 | 23 | debug = 2 |
| 24 | |||
| 25 | [package.metadata.embassy] | ||
| 26 | build = [ | ||
| 27 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32f0" } | ||
| 28 | ] | ||
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs new file mode 100644 index 000000000..ff98aac8e --- /dev/null +++ b/examples/stm32f0/src/bin/adc-watchdog.rs | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::adc::{self, Adc, WatchdogChannels}; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::peripherals::ADC1; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | ADC1_COMP => adc::InterruptHandler<ADC1>; | ||
| 13 | }); | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) { | ||
| 17 | let p = embassy_stm32::init(Default::default()); | ||
| 18 | info!("ADC watchdog example"); | ||
| 19 | |||
| 20 | let mut adc = Adc::new(p.ADC1, Irqs); | ||
| 21 | let pin = p.PC1; | ||
| 22 | |||
| 23 | loop { | ||
| 24 | // Wait for pin to go high | ||
| 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); | ||
| 26 | let v_high = adc.monitor_watchdog().await; | ||
| 27 | info!("ADC sample is high {}", v_high); | ||
| 28 | |||
| 29 | // Wait for pin to go low | ||
| 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); | ||
| 31 | let v_low = adc.monitor_watchdog().await; | ||
| 32 | info!("ADC sample is low {}", v_low); | ||
| 33 | } | ||
| 34 | } | ||
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs index 744df3e3b..f232e3290 100644 --- a/examples/stm32f0/src/bin/button_controlled_blink.rs +++ b/examples/stm32f0/src/bin/button_controlled_blink.rs | |||
| @@ -46,7 +46,7 @@ async fn main(spawner: Spawner) { | |||
| 46 | BLINK_MS.store(del_var, Ordering::Relaxed); | 46 | BLINK_MS.store(del_var, Ordering::Relaxed); |
| 47 | 47 | ||
| 48 | // Spawn LED blinking task | 48 | // Spawn LED blinking task |
| 49 | spawner.spawn(led_task(p.PA5.into())).unwrap(); | 49 | spawner.spawn(led_task(p.PA5.into()).unwrap()); |
| 50 | 50 | ||
| 51 | loop { | 51 | loop { |
| 52 | // Check if button got pressed | 52 | // Check if button got pressed |
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index 84e4077ef..b5244afc8 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs | |||
| @@ -134,16 +134,16 @@ fn main() -> ! { | |||
| 134 | // High-priority executor: USART1, priority level 6 | 134 | // High-priority executor: USART1, priority level 6 |
| 135 | interrupt::USART1.set_priority(Priority::P6); | 135 | interrupt::USART1.set_priority(Priority::P6); |
| 136 | let spawner = EXECUTOR_HIGH.start(interrupt::USART1); | 136 | let spawner = EXECUTOR_HIGH.start(interrupt::USART1); |
| 137 | unwrap!(spawner.spawn(run_high())); | 137 | spawner.spawn(unwrap!(run_high())); |
| 138 | 138 | ||
| 139 | // Medium-priority executor: USART2, priority level 7 | 139 | // Medium-priority executor: USART2, priority level 7 |
| 140 | interrupt::USART2.set_priority(Priority::P7); | 140 | interrupt::USART2.set_priority(Priority::P7); |
| 141 | let spawner = EXECUTOR_MED.start(interrupt::USART2); | 141 | let spawner = EXECUTOR_MED.start(interrupt::USART2); |
| 142 | unwrap!(spawner.spawn(run_med())); | 142 | spawner.spawn(unwrap!(run_med())); |
| 143 | 143 | ||
| 144 | // Low priority executor: runs in thread mode, using WFE/SEV | 144 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 145 | let executor = EXECUTOR_LOW.init(Executor::new()); | 145 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 146 | executor.run(|spawner| { | 146 | executor.run(|spawner| { |
| 147 | unwrap!(spawner.spawn(run_low())); | 147 | spawner.spawn(unwrap!(run_low())); |
| 148 | }); | 148 | }); |
| 149 | } | 149 | } |
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index fe800bc80..dcb58796b 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f1-examples" | 3 | name = "embassy-stm32f1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f103c8 to your chip name, if necessary. | 9 | # Change stm32f103c8 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | nb = "1.0.0" | 25 | nb = "1.0.0" |
| 25 | static_cell = "2.0.0" | 26 | static_cell = "2.0.0" |
| @@ -29,3 +30,8 @@ opt-level = "s" | |||
| 29 | 30 | ||
| 30 | [profile.release] | 31 | [profile.release] |
| 31 | debug = 2 | 32 | debug = 2 |
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f1" } | ||
| 37 | ] | ||
diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index 6fe8e0b50..b5b26938d 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 6 | use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; |
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; | 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; |
| 9 | use embassy_stm32::timer::{self, Channel}; | 9 | use embassy_stm32::timer::{self, Channel}; |
| @@ -37,10 +37,11 @@ async fn main(spawner: Spawner) { | |||
| 37 | let p = embassy_stm32::init(Default::default()); | 37 | let p = embassy_stm32::init(Default::default()); |
| 38 | info!("Hello World!"); | 38 | info!("Hello World!"); |
| 39 | 39 | ||
| 40 | unwrap!(spawner.spawn(blinky(p.PC13))); | 40 | spawner.spawn(unwrap!(blinky(p.PC13))); |
| 41 | 41 | ||
| 42 | let ch3 = CapturePin::new_ch3(p.PA2, Pull::None); | 42 | let ch3 = CapturePin::new(p.PA2, Pull::None); |
| 43 | let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); | 43 | let mut ic = |
| 44 | InputCapture::new::<AfioRemap<0>>(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); | ||
| 44 | 45 | ||
| 45 | loop { | 46 | loop { |
| 46 | info!("wait for rising edge"); | 47 | info!("wait for rising edge"); |
diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index afbef3edb..9ae747018 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 6 | use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; |
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::pwm_input::PwmInput; | 8 | use embassy_stm32::timer::pwm_input::PwmInput; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; |
| @@ -36,9 +36,9 @@ async fn main(spawner: Spawner) { | |||
| 36 | let p = embassy_stm32::init(Default::default()); | 36 | let p = embassy_stm32::init(Default::default()); |
| 37 | info!("Hello World!"); | 37 | info!("Hello World!"); |
| 38 | 38 | ||
| 39 | unwrap!(spawner.spawn(blinky(p.PC13))); | 39 | spawner.spawn(unwrap!(blinky(p.PC13))); |
| 40 | 40 | ||
| 41 | let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(10)); | 41 | let mut pwm_input = PwmInput::new_ch1::<AfioRemap<0>>(p.TIM2, p.PA0, Pull::None, khz(10)); |
| 42 | pwm_input.enable(); | 42 | pwm_input.enable(); |
| 43 | 43 | ||
| 44 | loop { | 44 | loop { |
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 26be3f485..498c20d84 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml | |||
| @@ -3,23 +3,29 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f2-examples" | 3 | name = "embassy-stm32f2-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f207zg to your chip name, if necessary. | 9 | # Change stm32f207zg to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "1.0.0" |
| 16 | 17 | ||
| 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 18 | cortex-m-rt = "0.7.0" | 19 | cortex-m-rt = "0.7.0" |
| 19 | embedded-hal = "0.2.6" | 20 | embedded-hal = "0.2.6" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | heapless = { version = "0.8", default-features = false } | 22 | heapless = { version = "0.8", default-features = false } |
| 22 | nb = "1.0.0" | 23 | nb = "1.0.0" |
| 23 | 24 | ||
| 24 | [profile.release] | 25 | [profile.release] |
| 25 | debug = 2 | 26 | debug = 2 |
| 27 | |||
| 28 | [package.metadata.embassy] | ||
| 29 | build = [ | ||
| 30 | { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f2" } | ||
| 31 | ] | ||
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 31bf040b0..23025ef0b 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f3-examples" | 3 | name = "embassy-stm32f3-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f303ze to your chip name, if necessary. | 9 | # Change stm32f303ze to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | nb = "1.0.0" | 25 | nb = "1.0.0" |
| 25 | embedded-storage = "0.3.1" | 26 | embedded-storage = "0.3.1" |
| @@ -27,3 +28,8 @@ static_cell = "2" | |||
| 27 | 28 | ||
| 28 | [profile.release] | 29 | [profile.release] |
| 29 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f3" } | ||
| 35 | ] | ||
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs index f5ed5d2c9..a54d03212 100644 --- a/examples/stm32f3/src/bin/button_events.rs +++ b/examples/stm32f3/src/bin/button_events.rs | |||
| @@ -113,8 +113,8 @@ async fn main(spawner: Spawner) { | |||
| 113 | ]; | 113 | ]; |
| 114 | let leds = Leds::new(leds); | 114 | let leds = Leds::new(leds); |
| 115 | 115 | ||
| 116 | spawner.spawn(button_waiter(button)).unwrap(); | 116 | spawner.spawn(button_waiter(button).unwrap()); |
| 117 | spawner.spawn(led_blinker(leds)).unwrap(); | 117 | spawner.spawn(led_blinker(leds).unwrap()); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | #[embassy_executor::task] | 120 | #[embassy_executor::task] |
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs | |||
| @@ -135,16 +135,16 @@ fn main() -> ! { | |||
| 135 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 136 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
| 138 | unwrap!(spawner.spawn(run_high())); | 138 | spawner.spawn(unwrap!(run_high())); |
| 139 | 139 | ||
| 140 | // Medium-priority executor: UART5, priority level 7 | 140 | // Medium-priority executor: UART5, priority level 7 |
| 141 | interrupt::UART5.set_priority(Priority::P7); | 141 | interrupt::UART5.set_priority(Priority::P7); |
| 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); | 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); |
| 143 | unwrap!(spawner.spawn(run_med())); | 143 | spawner.spawn(unwrap!(run_med())); |
| 144 | 144 | ||
| 145 | // Low priority executor: runs in thread mode, using WFE/SEV | 145 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 146 | let executor = EXECUTOR_LOW.init(Executor::new()); | 146 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 147 | executor.run(|spawner| { | 147 | executor.run(|spawner| { |
| 148 | unwrap!(spawner.spawn(run_low())); | 148 | spawner.spawn(unwrap!(run_low())); |
| 149 | }); | 149 | }); |
| 150 | } | 150 | } |
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 5fb6d60c5..3495b118c 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml | |||
| @@ -3,23 +3,29 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f334-examples" | 3 | name = "embassy-stm32f334-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 12 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | 18 | ||
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 20 | embedded-hal = "0.2.6" | 21 | embedded-hal = "0.2.6" |
| 21 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 22 | heapless = { version = "0.8", default-features = false } | 23 | heapless = { version = "0.8", default-features = false } |
| 23 | nb = "1.0.0" | 24 | nb = "1.0.0" |
| 24 | embedded-storage = "0.3.1" | 25 | embedded-storage = "0.3.1" |
| 25 | static_cell = "2" | 26 | static_cell = "2" |
| 27 | |||
| 28 | [package.metadata.embassy] | ||
| 29 | build = [ | ||
| 30 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f334" } | ||
| 31 | ] | ||
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7aa4354ca..fb5f86aac 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml | |||
| @@ -3,20 +3,21 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f4-examples" | 3 | name = "embassy-stm32f4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f429zi to your chip name, if necessary. | 9 | # Change stm32f429zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt" ] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt" ] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } |
| 15 | embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | 16 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | 21 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| @@ -24,7 +25,7 @@ embedded-hal = "0.2.6" | |||
| 24 | embedded-hal-bus = { version = "0.2", features = ["async"] } | 25 | embedded-hal-bus = { version = "0.2", features = ["async"] } |
| 25 | embedded-io = { version = "0.6.0" } | 26 | embedded-io = { version = "0.6.0" } |
| 26 | embedded-io-async = { version = "0.6.1" } | 27 | embedded-io-async = { version = "0.6.1" } |
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 28 | futures-util = { version = "0.3.30", default-features = false } | 29 | futures-util = { version = "0.3.30", default-features = false } |
| 29 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 30 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| @@ -37,3 +38,8 @@ chrono = { version = "^0.4", default-features = false} | |||
| 37 | 38 | ||
| 38 | [profile.release] | 39 | [profile.release] |
| 39 | debug = 2 | 40 | debug = 2 |
| 41 | |||
| 42 | [package.metadata.embassy] | ||
| 43 | build = [ | ||
| 44 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f4" } | ||
| 45 | ] | ||
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index 43a761e6d..2ec48640e 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs | |||
| @@ -11,7 +11,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 11 | #[embassy_executor::main] | 11 | #[embassy_executor::main] |
| 12 | async fn main(spawner: Spawner) { | 12 | async fn main(spawner: Spawner) { |
| 13 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 14 | spawner.must_spawn(adc_task(p)); | 14 | spawner.spawn(adc_task(p).unwrap()); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 634d8e2c6..f41a60529 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -91,7 +91,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 91 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 91 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 92 | 92 | ||
| 93 | // Launch network task | 93 | // Launch network task |
| 94 | unwrap!(spawner.spawn(net_task(runner))); | 94 | spawner.spawn(unwrap!(net_task(runner))); |
| 95 | 95 | ||
| 96 | // Ensure DHCP configuration is up before trying connect | 96 | // Ensure DHCP configuration is up before trying connect |
| 97 | stack.wait_config_up().await; | 97 | stack.wait_config_up().await; |
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index 6e6bef08c..7ce3bfe75 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -83,7 +83,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 83 | let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) | 83 | let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) |
| 84 | .await | 84 | .await |
| 85 | .unwrap(); | 85 | .unwrap(); |
| 86 | unwrap!(spawner.spawn(ethernet_task(runner))); | 86 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 87 | 87 | ||
| 88 | let config = embassy_net::Config::dhcpv4(Default::default()); | 88 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 89 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 89 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
| @@ -96,7 +96,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 96 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 96 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 97 | 97 | ||
| 98 | // Launch network task | 98 | // Launch network task |
| 99 | unwrap!(spawner.spawn(net_task(runner))); | 99 | spawner.spawn(unwrap!(net_task(runner))); |
| 100 | 100 | ||
| 101 | // Ensure DHCP configuration is up before trying connect | 101 | // Ensure DHCP configuration is up before trying connect |
| 102 | stack.wait_config_up().await; | 102 | stack.wait_config_up().await; |
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index 755713542..2feb9de09 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs | |||
| @@ -21,7 +21,7 @@ async fn main(spawner: Spawner) { | |||
| 21 | let mut f = Flash::new(p.FLASH, Irqs); | 21 | let mut f = Flash::new(p.FLASH, Irqs); |
| 22 | 22 | ||
| 23 | // Led should blink uninterrupted during ~2sec erase operation | 23 | // Led should blink uninterrupted during ~2sec erase operation |
| 24 | spawner.spawn(blinky(p.PB7.into())).unwrap(); | 24 | spawner.spawn(blinky(p.PB7.into()).unwrap()); |
| 25 | 25 | ||
| 26 | // Test on bank 2 in order not to stall CPU. | 26 | // Test on bank 2 in order not to stall CPU. |
| 27 | test_flash(&mut f, 1024 * 1024, 128 * 1024).await; | 27 | test_flash(&mut f, 1024 * 1024, 128 * 1024).await; |
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs index 4a96357a4..49710a92a 100644 --- a/examples/stm32f4/src/bin/i2c.rs +++ b/examples/stm32f4/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::{Error, I2c}; | 6 | use embassy_stm32::i2c::{Error, I2c}; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 8 | ||
| 10 | const ADDRESS: u8 = 0x5F; | 9 | const ADDRESS: u8 = 0x5F; |
| @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 15 | info!("Hello world!"); | 14 | info!("Hello world!"); |
| 16 | let p = embassy_stm32::init(Default::default()); | 15 | let p = embassy_stm32::init(Default::default()); |
| 17 | 16 | ||
| 18 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); | 17 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); |
| 19 | 18 | ||
| 20 | let mut data = [0u8; 1]; | 19 | let mut data = [0u8; 1]; |
| 21 | 20 | ||
diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs index 90d11d4b4..0065e92f3 100644 --- a/examples/stm32f4/src/bin/i2c_async.rs +++ b/examples/stm32f4/src/bin/i2c_async.rs | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::i2c::I2c; | 9 | use embassy_stm32::i2c::I2c; |
| 10 | use embassy_stm32::time::Hertz; | ||
| 11 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 12 | ||
| @@ -23,16 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | info!("Hello world!"); | 22 | info!("Hello world!"); |
| 24 | let p = embassy_stm32::init(Default::default()); | 23 | let p = embassy_stm32::init(Default::default()); |
| 25 | 24 | ||
| 26 | let mut i2c = I2c::new( | 25 | let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default()); |
| 27 | p.I2C1, | ||
| 28 | p.PB8, | ||
| 29 | p.PB7, | ||
| 30 | Irqs, | ||
| 31 | p.DMA1_CH6, | ||
| 32 | p.DMA1_CH0, | ||
| 33 | Hertz(100_000), | ||
| 34 | Default::default(), | ||
| 35 | ); | ||
| 36 | 26 | ||
| 37 | loop { | 27 | loop { |
| 38 | let a1454_read_sensor_command = [0x1F]; | 28 | let a1454_read_sensor_command = [0x1F]; |
diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs index 55c4891e3..59bdb8b67 100644 --- a/examples/stm32f4/src/bin/i2c_comparison.rs +++ b/examples/stm32f4/src/bin/i2c_comparison.rs | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | use defmt::*; | 10 | use defmt::*; |
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_stm32::i2c::I2c; | 12 | use embassy_stm32::i2c::I2c; |
| 13 | use embassy_stm32::time::Hertz; | ||
| 14 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 13 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 15 | use embassy_time::Instant; | 14 | use embassy_time::Instant; |
| 16 | use futures_util::future::try_join3; | 15 | use futures_util::future::try_join3; |
| @@ -48,38 +47,11 @@ async fn main(_spawner: Spawner) { | |||
| 48 | info!("Setting up peripherals."); | 47 | info!("Setting up peripherals."); |
| 49 | let p = embassy_stm32::init(Default::default()); | 48 | let p = embassy_stm32::init(Default::default()); |
| 50 | 49 | ||
| 51 | let mut i2c1 = I2c::new( | 50 | let mut i2c1 = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default()); |
| 52 | p.I2C1, | ||
| 53 | p.PB8, | ||
| 54 | p.PB7, | ||
| 55 | Irqs, | ||
| 56 | p.DMA1_CH6, | ||
| 57 | p.DMA1_CH0, | ||
| 58 | Hertz(100_000), | ||
| 59 | Default::default(), | ||
| 60 | ); | ||
| 61 | 51 | ||
| 62 | let mut i2c2 = I2c::new( | 52 | let mut i2c2 = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH7, p.DMA1_CH3, Default::default()); |
| 63 | p.I2C2, | ||
| 64 | p.PB10, | ||
| 65 | p.PB11, | ||
| 66 | Irqs, | ||
| 67 | p.DMA1_CH7, | ||
| 68 | p.DMA1_CH3, | ||
| 69 | Hertz(100_000), | ||
| 70 | Default::default(), | ||
| 71 | ); | ||
| 72 | 53 | ||
| 73 | let mut i2c3 = I2c::new( | 54 | let mut i2c3 = I2c::new(p.I2C3, p.PA8, p.PC9, Irqs, p.DMA1_CH4, p.DMA1_CH2, Default::default()); |
| 74 | p.I2C3, | ||
| 75 | p.PA8, | ||
| 76 | p.PC9, | ||
| 77 | Irqs, | ||
| 78 | p.DMA1_CH4, | ||
| 79 | p.DMA1_CH2, | ||
| 80 | Hertz(100_000), | ||
| 81 | Default::default(), | ||
| 82 | ); | ||
| 83 | 55 | ||
| 84 | let a1454_read_sensor_command = [0x1F]; | 56 | let a1454_read_sensor_command = [0x1F]; |
| 85 | let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0]; | 57 | let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0]; |
diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs index db5103d0f..6051a3c5a 100644 --- a/examples/stm32f4/src/bin/i2s_dma.rs +++ b/examples/stm32f4/src/bin/i2s_dma.rs | |||
| @@ -72,7 +72,6 @@ async fn main(_spawner: Spawner) { | |||
| 72 | p.PB3, // ck | 72 | p.PB3, // ck |
| 73 | p.DMA1_CH7, | 73 | p.DMA1_CH7, |
| 74 | &mut dma_buffer, | 74 | &mut dma_buffer, |
| 75 | Hertz(48_000), | ||
| 76 | i2s_config, | 75 | i2s_config, |
| 77 | ); | 76 | ); |
| 78 | i2s.start(); | 77 | i2s.start(); |
diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs index fe5e2bdfc..9998c4733 100644 --- a/examples/stm32f4/src/bin/input_capture.rs +++ b/examples/stm32f4/src/bin/input_capture.rs | |||
| @@ -37,9 +37,9 @@ async fn main(spawner: Spawner) { | |||
| 37 | let p = embassy_stm32::init(Default::default()); | 37 | let p = embassy_stm32::init(Default::default()); |
| 38 | info!("Hello World!"); | 38 | info!("Hello World!"); |
| 39 | 39 | ||
| 40 | unwrap!(spawner.spawn(blinky(p.PB2))); | 40 | spawner.spawn(unwrap!(blinky(p.PB2))); |
| 41 | 41 | ||
| 42 | let ch3 = CapturePin::new_ch3(p.PB10, Pull::None); | 42 | let ch3 = CapturePin::new(p.PB10, Pull::None); |
| 43 | let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); | 43 | let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); |
| 44 | 44 | ||
| 45 | loop { | 45 | loop { |
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs | |||
| @@ -135,16 +135,16 @@ fn main() -> ! { | |||
| 135 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 136 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
| 138 | unwrap!(spawner.spawn(run_high())); | 138 | spawner.spawn(unwrap!(run_high())); |
| 139 | 139 | ||
| 140 | // Medium-priority executor: UART5, priority level 7 | 140 | // Medium-priority executor: UART5, priority level 7 |
| 141 | interrupt::UART5.set_priority(Priority::P7); | 141 | interrupt::UART5.set_priority(Priority::P7); |
| 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); | 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); |
| 143 | unwrap!(spawner.spawn(run_med())); | 143 | spawner.spawn(unwrap!(run_med())); |
| 144 | 144 | ||
| 145 | // Low priority executor: runs in thread mode, using WFE/SEV | 145 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 146 | let executor = EXECUTOR_LOW.init(Executor::new()); | 146 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 147 | executor.run(|spawner| { | 147 | executor.run(|spawner| { |
| 148 | unwrap!(spawner.spawn(run_low())); | 148 | spawner.spawn(unwrap!(run_low())); |
| 149 | }); | 149 | }); |
| 150 | } | 150 | } |
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs index 04811162b..e385842f0 100644 --- a/examples/stm32f4/src/bin/pwm.rs +++ b/examples/stm32f4/src/bin/pwm.rs | |||
| @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 15 | info!("Hello World!"); | 15 | info!("Hello World!"); |
| 16 | 16 | ||
| 17 | let ch1_pin = PwmPin::new_ch1(p.PE9, OutputType::PushPull); | 17 | let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull); |
| 18 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); | 18 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); |
| 19 | let mut ch1 = pwm.ch1(); | 19 | let mut ch1 = pwm.ch1(); |
| 20 | ch1.enable(); | 20 | ch1.enable(); |
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs index 161f43c48..c981f1a76 100644 --- a/examples/stm32f4/src/bin/pwm_complementary.rs +++ b/examples/stm32f4/src/bin/pwm_complementary.rs | |||
| @@ -16,8 +16,8 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let p = embassy_stm32::init(Default::default()); | 16 | let p = embassy_stm32::init(Default::default()); |
| 17 | info!("Hello World!"); | 17 | info!("Hello World!"); |
| 18 | 18 | ||
| 19 | let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); | 19 | let ch1 = PwmPin::new(p.PE9, OutputType::PushPull); |
| 20 | let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); | 20 | let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); |
| 21 | let mut pwm = ComplementaryPwm::new( | 21 | let mut pwm = ComplementaryPwm::new( |
| 22 | p.TIM1, | 22 | p.TIM1, |
| 23 | Some(ch1), | 23 | Some(ch1), |
diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 465cbe4f5..e8bfa524f 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs | |||
| @@ -36,9 +36,9 @@ async fn main(spawner: Spawner) { | |||
| 36 | let p = embassy_stm32::init(Default::default()); | 36 | let p = embassy_stm32::init(Default::default()); |
| 37 | info!("Hello World!"); | 37 | info!("Hello World!"); |
| 38 | 38 | ||
| 39 | unwrap!(spawner.spawn(blinky(p.PB2))); | 39 | spawner.spawn(unwrap!(blinky(p.PB2))); |
| 40 | 40 | ||
| 41 | let mut pwm_input = PwmInput::new(p.TIM3, p.PA6, Pull::None, khz(10)); | 41 | let mut pwm_input = PwmInput::new_ch1(p.TIM3, p.PA6, Pull::None, khz(10)); |
| 42 | pwm_input.enable(); | 42 | pwm_input.enable(); |
| 43 | 43 | ||
| 44 | loop { | 44 | loop { |
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 322cb90c7..7abbe8719 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs | |||
| @@ -118,11 +118,11 @@ async fn main(spawner: Spawner) { | |||
| 118 | // Build the builder. | 118 | // Build the builder. |
| 119 | let usb = builder.build(); | 119 | let usb = builder.build(); |
| 120 | 120 | ||
| 121 | unwrap!(spawner.spawn(usb_task(usb))); | 121 | spawner.spawn(unwrap!(usb_task(usb))); |
| 122 | 122 | ||
| 123 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); | 123 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); |
| 124 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); | 124 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); |
| 125 | unwrap!(spawner.spawn(usb_ncm_task(runner))); | 125 | spawner.spawn(unwrap!(usb_ncm_task(runner))); |
| 126 | 126 | ||
| 127 | let config = embassy_net::Config::dhcpv4(Default::default()); | 127 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 128 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 128 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
| @@ -141,7 +141,7 @@ async fn main(spawner: Spawner) { | |||
| 141 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 141 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 142 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 142 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 143 | 143 | ||
| 144 | unwrap!(spawner.spawn(net_task(runner))); | 144 | spawner.spawn(unwrap!(net_task(runner))); |
| 145 | 145 | ||
| 146 | // And now we can use it! | 146 | // And now we can use it! |
| 147 | 147 | ||
diff --git a/examples/stm32f4/src/bin/usb_uac_speaker.rs b/examples/stm32f4/src/bin/usb_uac_speaker.rs index 654bec498..79bd2d914 100644 --- a/examples/stm32f4/src/bin/usb_uac_speaker.rs +++ b/examples/stm32f4/src/bin/usb_uac_speaker.rs | |||
| @@ -375,9 +375,9 @@ async fn main(spawner: Spawner) { | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | // Launch USB audio tasks. | 377 | // Launch USB audio tasks. |
| 378 | unwrap!(spawner.spawn(usb_control_task(control_monitor))); | 378 | spawner.spawn(unwrap!(usb_control_task(control_monitor))); |
| 379 | unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); | 379 | spawner.spawn(unwrap!(usb_streaming_task(stream, sender))); |
| 380 | unwrap!(spawner.spawn(usb_feedback_task(feedback))); | 380 | spawner.spawn(unwrap!(usb_feedback_task(feedback))); |
| 381 | unwrap!(spawner.spawn(usb_task(usb_device))); | 381 | spawner.spawn(unwrap!(usb_task(usb_device))); |
| 382 | unwrap!(spawner.spawn(audio_receiver_task(receiver))); | 382 | spawner.spawn(unwrap!(audio_receiver_task(receiver))); |
| 383 | } | 383 | } |
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs index ca924e181..5153e1cfd 100644 --- a/examples/stm32f4/src/bin/ws2812_pwm.rs +++ b/examples/stm32f4/src/bin/ws2812_pwm.rs | |||
| @@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | let mut ws2812_pwm = SimplePwm::new( | 51 | let mut ws2812_pwm = SimplePwm::new( |
| 52 | dp.TIM3, | 52 | dp.TIM3, |
| 53 | Some(PwmPin::new_ch1(dp.PB4, OutputType::PushPull)), | 53 | Some(PwmPin::new(dp.PB4, OutputType::PushPull)), |
| 54 | None, | 54 | None, |
| 55 | None, | 55 | None, |
| 56 | None, | 56 | None, |
diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 4d403bae8..f1d0e411a 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml | |||
| @@ -3,20 +3,26 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f469-examples" | 3 | name = "embassy-stm32f469-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Specific examples only for stm32f469 | 9 | # Specific examples only for stm32f469 |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 12 | 13 | ||
| 13 | defmt = "0.3" | 14 | defmt = "1.0.1" |
| 14 | defmt-rtt = "0.4" | 15 | defmt-rtt = "1.0.0" |
| 15 | 16 | ||
| 16 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 17 | cortex-m-rt = "0.7.0" | 18 | cortex-m-rt = "0.7.0" |
| 18 | embedded-hal = "1.0.0" | 19 | embedded-hal = "1.0.0" |
| 19 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 20 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 20 | 21 | ||
| 21 | [profile.release] | 22 | [profile.release] |
| 22 | debug = 2 | 23 | debug = 2 |
| 24 | |||
| 25 | [package.metadata.embassy] | ||
| 26 | build = [ | ||
| 27 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f469" } | ||
| 28 | ] | ||
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 1a46931d9..5d7763334 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -3,28 +3,28 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32f7-examples" | 3 | name = "embassy-stm32f7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f777zi to your chip name, if necessary. | 9 | # Change stm32f777zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 14 | embedded-io-async = { version = "0.6.1" } | 15 | embedded-io-async = { version = "0.6.1" } |
| 15 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 16 | embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | 21 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| 23 | embedded-hal = "0.2.6" | 24 | embedded-hal = "0.2.6" |
| 24 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 25 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 25 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 26 | nb = "1.0.0" | 27 | nb = "1.0.0" |
| 27 | rand_core = "0.6.3" | ||
| 28 | critical-section = "1.1" | 28 | critical-section = "1.1" |
| 29 | embedded-storage = "0.3.1" | 29 | embedded-storage = "0.3.1" |
| 30 | static_cell = "2" | 30 | static_cell = "2" |
| @@ -34,3 +34,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "he | |||
| 34 | 34 | ||
| 35 | [profile.release] | 35 | [profile.release] |
| 36 | debug = 2 | 36 | debug = 2 |
| 37 | |||
| 38 | [package.metadata.embassy] | ||
| 39 | build = [ | ||
| 40 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f7" } | ||
| 41 | ] | ||
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index 58ba940a8..9a91ac814 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs | |||
| @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { | |||
| 64 | 64 | ||
| 65 | static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new(); | 65 | static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new(); |
| 66 | let tx = CAN_TX.init(tx); | 66 | let tx = CAN_TX.init(tx); |
| 67 | spawner.spawn(send_can_message(tx)).unwrap(); | 67 | spawner.spawn(send_can_message(tx).unwrap()); |
| 68 | 68 | ||
| 69 | loop { | 69 | loop { |
| 70 | let envelope = rx.read().await.unwrap(); | 70 | let envelope = rx.read().await.unwrap(); |
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs index 235853cb9..a31e9b4f2 100644 --- a/examples/stm32f7/src/bin/cryp.rs +++ b/examples/stm32f7/src/bin/cryp.rs | |||
| @@ -68,7 +68,9 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 68 | ); | 68 | ); |
| 69 | 69 | ||
| 70 | // Decrypt in software using AES-GCM 128-bit | 70 | // Decrypt in software using AES-GCM 128-bit |
| 71 | let _ = cipher.decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec); | 71 | cipher |
| 72 | .decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec) | ||
| 73 | .unwrap(); | ||
| 72 | 74 | ||
| 73 | let sw_end_time = Instant::now(); | 75 | let sw_end_time = Instant::now(); |
| 74 | let sw_execution_time = sw_end_time - sw_start_time; | 76 | let sw_execution_time = sw_end_time - sw_start_time; |
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 17ab7fc00..b13b7bdda 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -12,7 +12,6 @@ use embassy_stm32::time::Hertz; | |||
| 12 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 12 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use embedded_io_async::Write; | 14 | use embedded_io_async::Write; |
| 15 | use rand_core::RngCore; | ||
| 16 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 17 | ||
| @@ -92,7 +91,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 92 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 91 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 93 | 92 | ||
| 94 | // Launch network task | 93 | // Launch network task |
| 95 | unwrap!(spawner.spawn(net_task(runner))); | 94 | spawner.spawn(unwrap!(net_task(runner))); |
| 96 | 95 | ||
| 97 | // Ensure DHCP configuration is up before trying connect | 96 | // Ensure DHCP configuration is up before trying connect |
| 98 | stack.wait_config_up().await; | 97 | stack.wait_config_up().await; |
diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs index bd3287964..80652b865 100644 --- a/examples/stm32f7/src/bin/qspi.rs +++ b/examples/stm32f7/src/bin/qspi.rs | |||
| @@ -273,13 +273,14 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 273 | let p = embassy_stm32::init(config); | 273 | let p = embassy_stm32::init(config); |
| 274 | info!("Embassy initialized"); | 274 | info!("Embassy initialized"); |
| 275 | 275 | ||
| 276 | let config = QspiCfg { | 276 | let mut config = QspiCfg::default(); |
| 277 | memory_size: MemorySize::_8MiB, | 277 | config.memory_size = MemorySize::_8MiB; |
| 278 | address_size: AddressSize::_24bit, | 278 | config.address_size = AddressSize::_24bit; |
| 279 | prescaler: 16, | 279 | config.prescaler = 16; |
| 280 | cs_high_time: ChipSelectHighTime::_1Cycle, | 280 | config.cs_high_time = ChipSelectHighTime::_1Cycle; |
| 281 | fifo_threshold: FIFOThresholdLevel::_16Bytes, | 281 | config.fifo_threshold = FIFOThresholdLevel::_16Bytes; |
| 282 | }; | 282 | config.sample_shifting = SampleShifting::None; |
| 283 | |||
| 283 | let driver = Qspi::new_bank1( | 284 | let driver = Qspi::new_bank1( |
| 284 | p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config, | 285 | p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config, |
| 285 | ); | 286 | ); |
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 319d84179..1c9451469 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32g0-examples" | 3 | name = "embassy-stm32g0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32g0b1re to your chip name, if necessary. | 9 | # Change stm32g0b1re to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | 25 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } |
| 25 | 26 | ||
| @@ -27,3 +28,8 @@ embedded-io-async = { version = "0.6.1" } | |||
| 27 | 28 | ||
| 28 | [profile.release] | 29 | [profile.release] |
| 29 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32g0" } | ||
| 35 | ] | ||
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 6c7f3b48a..7d8653ef2 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, SampleTime}; | 6 | use embassy_stm32::adc::{Adc, Clock, Presc, SampleTime}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_stm32::init(Default::default()); | 12 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 13 | info!("Hello World!"); |
| 14 | 14 | ||
| 15 | let mut adc = Adc::new(p.ADC1); | 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 16 | adc.set_sample_time(SampleTime::CYCLES79_5); | 16 | adc.set_sample_time(SampleTime::CYCLES79_5); |
| 17 | let mut pin = p.PA1; | 17 | let mut pin = p.PA1; |
| 18 | 18 | ||
diff --git a/examples/stm32g0/src/bin/adc_dma.rs b/examples/stm32g0/src/bin/adc_dma.rs index d7515933c..8266a6d83 100644 --- a/examples/stm32g0/src/bin/adc_dma.rs +++ b/examples/stm32g0/src/bin/adc_dma.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; | 6 | use embassy_stm32::adc::{Adc, AdcChannel as _, Clock, Presc, SampleTime}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | 17 | ||
| 18 | info!("Hello World!"); | 18 | info!("Hello World!"); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new(p.ADC1); | 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 21 | 21 | ||
| 22 | let mut dma = p.DMA1_CH1; | 22 | let mut dma = p.DMA1_CH1; |
| 23 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); | 23 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); |
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 9c5dd872a..bc49fac83 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::adc::{Adc, SampleTime}; | 10 | use embassy_stm32::adc::{Adc, Clock, Presc, SampleTime}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let p = embassy_stm32::init(Default::default()); | 16 | let p = embassy_stm32::init(Default::default()); |
| 17 | info!("Adc oversample test"); | 17 | info!("Adc oversample test"); |
| 18 | 18 | ||
| 19 | let mut adc = Adc::new(p.ADC1); | 19 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 20 | adc.set_sample_time(SampleTime::CYCLES1_5); | 20 | adc.set_sample_time(SampleTime::CYCLES1_5); |
| 21 | let mut pin = p.PA1; | 21 | let mut pin = p.PA1; |
| 22 | 22 | ||
diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs index dfb6e0edc..705905f01 100644 --- a/examples/stm32g0/src/bin/hf_timer.rs +++ b/examples/stm32g0/src/bin/hf_timer.rs | |||
| @@ -37,8 +37,8 @@ async fn main(_spawner: Spawner) { | |||
| 37 | } | 37 | } |
| 38 | let p = embassy_stm32::init(config); | 38 | let p = embassy_stm32::init(config); |
| 39 | 39 | ||
| 40 | let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); | 40 | let ch1 = PwmPin::new(p.PA8, OutputType::PushPull); |
| 41 | let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); | 41 | let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); |
| 42 | 42 | ||
| 43 | let mut pwm = ComplementaryPwm::new( | 43 | let mut pwm = ComplementaryPwm::new( |
| 44 | p.TIM1, | 44 | p.TIM1, |
diff --git a/examples/stm32g0/src/bin/i2c_async.rs b/examples/stm32g0/src/bin/i2c_async.rs index 7e3189b05..e62d9266b 100644 --- a/examples/stm32g0/src/bin/i2c_async.rs +++ b/examples/stm32g0/src/bin/i2c_async.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::{self, I2c}; | 6 | use embassy_stm32::i2c::{self, I2c}; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_stm32::{bind_interrupts, peripherals}; | 7 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 9 | use embassy_time::{Duration, Timer}; | 8 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -23,16 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | let p = embassy_stm32::init(Default::default()); | 22 | let p = embassy_stm32::init(Default::default()); |
| 24 | 23 | ||
| 25 | let mut data = [0u8; 2]; | 24 | let mut data = [0u8; 2]; |
| 26 | let mut i2c = I2c::new( | 25 | let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); |
| 27 | p.I2C1, | ||
| 28 | p.PB8, | ||
| 29 | p.PB9, | ||
| 30 | Irqs, | ||
| 31 | p.DMA1_CH1, | ||
| 32 | p.DMA1_CH2, | ||
| 33 | Hertz(100_000), | ||
| 34 | Default::default(), | ||
| 35 | ); | ||
| 36 | 26 | ||
| 37 | loop { | 27 | loop { |
| 38 | match i2c.write_read(TMP117_ADDR, &[TMP117_TEMP_RESULT], &mut data).await { | 28 | match i2c.write_read(TMP117_ADDR, &[TMP117_TEMP_RESULT], &mut data).await { |
diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs index 08df4e043..5501a6941 100644 --- a/examples/stm32g0/src/bin/input_capture.rs +++ b/examples/stm32g0/src/bin/input_capture.rs | |||
| @@ -44,15 +44,15 @@ async fn main(spawner: Spawner) { | |||
| 44 | let p = embassy_stm32::init(Default::default()); | 44 | let p = embassy_stm32::init(Default::default()); |
| 45 | info!("Hello World!"); | 45 | info!("Hello World!"); |
| 46 | 46 | ||
| 47 | unwrap!(spawner.spawn(blinky(p.PB1))); | 47 | spawner.spawn(unwrap!(blinky(p.PB1))); |
| 48 | 48 | ||
| 49 | // Connect PB1 and PA8 with a 1k Ohm resistor | 49 | // Connect PB1 and PA8 with a 1k Ohm resistor |
| 50 | let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); | 50 | let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); |
| 51 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); | 51 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); |
| 52 | pwm.ch1().enable(); | 52 | pwm.ch1().enable(); |
| 53 | pwm.ch1().set_duty_cycle(50); | 53 | pwm.ch1().set_duty_cycle(50); |
| 54 | 54 | ||
| 55 | let ch1 = CapturePin::new_ch1(p.PA0, Pull::None); | 55 | let ch1 = CapturePin::new(p.PA0, Pull::None); |
| 56 | let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default()); | 56 | let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default()); |
| 57 | 57 | ||
| 58 | let mut old_capture = 0; | 58 | let mut old_capture = 0; |
diff --git a/examples/stm32g0/src/bin/pwm_complementary.rs b/examples/stm32g0/src/bin/pwm_complementary.rs index 97b163c40..dbd9194c9 100644 --- a/examples/stm32g0/src/bin/pwm_complementary.rs +++ b/examples/stm32g0/src/bin/pwm_complementary.rs | |||
| @@ -26,10 +26,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 26 | async fn main(_spawner: Spawner) { | 26 | async fn main(_spawner: Spawner) { |
| 27 | let p = embassy_stm32::init(Default::default()); | 27 | let p = embassy_stm32::init(Default::default()); |
| 28 | 28 | ||
| 29 | let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); | 29 | let ch1 = PwmPin::new(p.PA8, OutputType::PushPull); |
| 30 | let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); | 30 | let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); |
| 31 | let ch2 = PwmPin::new_ch2(p.PB3, OutputType::PushPull); | 31 | let ch2 = PwmPin::new(p.PB3, OutputType::PushPull); |
| 32 | let ch2n = ComplementaryPwmPin::new_ch2(p.PB0, OutputType::PushPull); | 32 | let ch2n = ComplementaryPwmPin::new(p.PB0, OutputType::PushPull); |
| 33 | 33 | ||
| 34 | let mut pwm = ComplementaryPwm::new( | 34 | let mut pwm = ComplementaryPwm::new( |
| 35 | p.TIM1, | 35 | p.TIM1, |
diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs index 9d6b5fe97..72aa07c03 100644 --- a/examples/stm32g0/src/bin/pwm_input.rs +++ b/examples/stm32g0/src/bin/pwm_input.rs | |||
| @@ -40,14 +40,14 @@ bind_interrupts!(struct Irqs { | |||
| 40 | async fn main(spawner: Spawner) { | 40 | async fn main(spawner: Spawner) { |
| 41 | let p = embassy_stm32::init(Default::default()); | 41 | let p = embassy_stm32::init(Default::default()); |
| 42 | 42 | ||
| 43 | unwrap!(spawner.spawn(blinky(p.PB1))); | 43 | spawner.spawn(unwrap!(blinky(p.PB1))); |
| 44 | // Connect PA8 and PA6 with a 1k Ohm resistor | 44 | // Connect PA8 and PA6 with a 1k Ohm resistor |
| 45 | let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); | 45 | let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); |
| 46 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); | 46 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); |
| 47 | pwm.ch1().set_duty_cycle_fraction(1, 4); | 47 | pwm.ch1().set_duty_cycle_fraction(1, 4); |
| 48 | pwm.ch1().enable(); | 48 | pwm.ch1().enable(); |
| 49 | 49 | ||
| 50 | let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); | 50 | let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(1000)); |
| 51 | pwm_input.enable(); | 51 | pwm_input.enable(); |
| 52 | 52 | ||
| 53 | loop { | 53 | loop { |
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index aa01d84e2..102960980 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml | |||
| @@ -3,27 +3,33 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32g4-examples" | 3 | name = "embassy-stm32g4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32g491re to your chip name, if necessary. | 9 | # Change stm32g491re to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | usbd-hid = "0.8.1" | 16 | usbd-hid = "0.8.1" |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "1.0.1" |
| 18 | defmt-rtt = "0.4" | 19 | defmt-rtt = "1.0.0" |
| 19 | 20 | ||
| 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| 22 | embedded-hal = "0.2.6" | 23 | embedded-hal = "0.2.6" |
| 23 | embedded-can = { version = "0.4" } | 24 | embedded-can = { version = "0.4" } |
| 24 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 25 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 25 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 26 | static_cell = "2.0.0" | 27 | static_cell = "2.0.0" |
| 27 | 28 | ||
| 28 | [profile.release] | 29 | [profile.release] |
| 29 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32g4" } | ||
| 35 | ] | ||
diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs new file mode 100644 index 000000000..65aca1c1b --- /dev/null +++ b/examples/stm32g4/src/bin/i2c_slave.rs | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | //! This example shows how to use an stm32 as both a master and a slave. | ||
| 2 | #![no_std] | ||
| 3 | #![no_main] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind}; | ||
| 8 | use embassy_stm32::mode::Async; | ||
| 9 | use embassy_stm32::time::Hertz; | ||
| 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 11 | use embassy_time::Timer; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 16 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | ||
| 17 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 18 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; | ||
| 19 | }); | ||
| 20 | |||
| 21 | const DEV_ADDR: u8 = 0x42; | ||
| 22 | |||
| 23 | #[embassy_executor::task] | ||
| 24 | async fn device_task(mut dev: i2c::I2c<'static, Async, i2c::MultiMaster>) -> ! { | ||
| 25 | info!("Device start"); | ||
| 26 | |||
| 27 | let mut state = 0; | ||
| 28 | |||
| 29 | loop { | ||
| 30 | let mut buf = [0u8; 128]; | ||
| 31 | match dev.listen().await { | ||
| 32 | Ok(i2c::SlaveCommand { | ||
| 33 | kind: SlaveCommandKind::Read, | ||
| 34 | address: Address::SevenBit(DEV_ADDR), | ||
| 35 | }) => match dev.respond_to_read(&[state]).await { | ||
| 36 | Ok(i2c::SendStatus::LeftoverBytes(x)) => info!("tried to write {} extra bytes", x), | ||
| 37 | Ok(i2c::SendStatus::Done) => {} | ||
| 38 | Err(e) => error!("error while responding {}", e), | ||
| 39 | }, | ||
| 40 | Ok(i2c::SlaveCommand { | ||
| 41 | kind: SlaveCommandKind::Write, | ||
| 42 | address: Address::SevenBit(DEV_ADDR), | ||
| 43 | }) => match dev.respond_to_write(&mut buf).await { | ||
| 44 | Ok(len) => { | ||
| 45 | info!("Device received write: {}", buf[..len]); | ||
| 46 | |||
| 47 | if match buf[0] { | ||
| 48 | // Set the state | ||
| 49 | 0xC2 => { | ||
| 50 | state = buf[1]; | ||
| 51 | true | ||
| 52 | } | ||
| 53 | // Reset State | ||
| 54 | 0xC8 => { | ||
| 55 | state = 0; | ||
| 56 | true | ||
| 57 | } | ||
| 58 | x => { | ||
| 59 | error!("Invalid Write Read {:x}", x); | ||
| 60 | false | ||
| 61 | } | ||
| 62 | } { | ||
| 63 | match dev.respond_to_read(&[state]).await { | ||
| 64 | Ok(read_status) => info!( | ||
| 65 | "This read is part of a write/read transaction. The response read status {}", | ||
| 66 | read_status | ||
| 67 | ), | ||
| 68 | Err(i2c::Error::Timeout) => { | ||
| 69 | info!("The device only performed a write and it not also do a read") | ||
| 70 | } | ||
| 71 | Err(e) => error!("error while responding {}", e), | ||
| 72 | } | ||
| 73 | } | ||
| 74 | } | ||
| 75 | Err(e) => error!("error while receiving {}", e), | ||
| 76 | }, | ||
| 77 | Ok(i2c::SlaveCommand { address, .. }) => { | ||
| 78 | defmt::unreachable!( | ||
| 79 | "The slave matched address: {}, which it was not configured for", | ||
| 80 | address | ||
| 81 | ); | ||
| 82 | } | ||
| 83 | Err(e) => error!("{}", e), | ||
| 84 | } | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | #[embassy_executor::task] | ||
| 89 | async fn controller_task(mut con: i2c::I2c<'static, Async, i2c::Master>) { | ||
| 90 | info!("Controller start"); | ||
| 91 | |||
| 92 | loop { | ||
| 93 | let mut resp_buff = [0u8; 1]; | ||
| 94 | for i in 0..10 { | ||
| 95 | match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await { | ||
| 96 | Ok(_) => { | ||
| 97 | info!("write_read response: {}", resp_buff); | ||
| 98 | defmt::assert_eq!(resp_buff[0], i); | ||
| 99 | } | ||
| 100 | Err(e) => error!("Error writing {}", e), | ||
| 101 | } | ||
| 102 | |||
| 103 | Timer::after_millis(100).await; | ||
| 104 | } | ||
| 105 | match con.read(DEV_ADDR, &mut resp_buff).await { | ||
| 106 | Ok(_) => { | ||
| 107 | info!("read response: {}", resp_buff); | ||
| 108 | // assert that the state is the last index that was written | ||
| 109 | defmt::assert_eq!(resp_buff[0], 9); | ||
| 110 | } | ||
| 111 | Err(e) => error!("Error writing {}", e), | ||
| 112 | } | ||
| 113 | match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await { | ||
| 114 | Ok(_) => { | ||
| 115 | info!("write_read response: {}", resp_buff); | ||
| 116 | // assert that the state has been reset | ||
| 117 | defmt::assert_eq!(resp_buff[0], 0); | ||
| 118 | } | ||
| 119 | Err(e) => error!("Error writing {}", e), | ||
| 120 | } | ||
| 121 | Timer::after_millis(100).await; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | #[embassy_executor::main] | ||
| 126 | async fn main(spawner: Spawner) { | ||
| 127 | let p = embassy_stm32::init(Default::default()); | ||
| 128 | info!("Hello World!"); | ||
| 129 | |||
| 130 | let mut config = i2c::Config::default(); | ||
| 131 | config.frequency = Hertz::khz(400); | ||
| 132 | |||
| 133 | let d_addr_config = i2c::SlaveAddrConfig { | ||
| 134 | addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)), | ||
| 135 | general_call: false, | ||
| 136 | }; | ||
| 137 | let d_sda = p.PA8; | ||
| 138 | let d_scl = p.PA9; | ||
| 139 | let device = | ||
| 140 | i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config).into_slave_multimaster(d_addr_config); | ||
| 141 | |||
| 142 | spawner.spawn(unwrap!(device_task(device))); | ||
| 143 | |||
| 144 | let c_sda = p.PB8; | ||
| 145 | let c_scl = p.PB7; | ||
| 146 | let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, config); | ||
| 147 | |||
| 148 | spawner.spawn(unwrap!(controller_task(controller))); | ||
| 149 | } | ||
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs index 6c965012c..5b4194927 100644 --- a/examples/stm32g4/src/bin/pwm.rs +++ b/examples/stm32g4/src/bin/pwm.rs | |||
| @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 15 | info!("Hello World!"); | 15 | info!("Hello World!"); |
| 16 | 16 | ||
| 17 | let ch1_pin = PwmPin::new_ch1(p.PC0, OutputType::PushPull); | 17 | let ch1_pin = PwmPin::new(p.PC0, OutputType::PushPull); |
| 18 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); | 18 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); |
| 19 | let mut ch1 = pwm.ch1(); | 19 | let mut ch1 = pwm.ch1(); |
| 20 | ch1.enable(); | 20 | ch1.enable(); |
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 5631ff746..66680c027 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml | |||
| @@ -3,19 +3,20 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h5-examples" | 3 | name = "embassy-stm32h5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h563zi to your chip name, if necessary. | 9 | # Change stm32h563zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "1.0.1" |
| 18 | defmt-rtt = "0.4" | 19 | defmt-rtt = "1.0.0" |
| 19 | 20 | ||
| 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| @@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 24 | embedded-hal-async = { version = "1.0" } | 25 | embedded-hal-async = { version = "1.0" } |
| 25 | embedded-io-async = { version = "0.6.1" } | 26 | embedded-io-async = { version = "0.6.1" } |
| 26 | embedded-nal-async = "0.8.0" | 27 | embedded-nal-async = "0.8.0" |
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 28 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 29 | rand_core = "0.6.3" | ||
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.3.0" |
| @@ -70,3 +70,8 @@ incremental = false | |||
| 70 | lto = 'fat' | 70 | lto = 'fat' |
| 71 | opt-level = 3 # <- | 71 | opt-level = 3 # <- |
| 72 | overflow-checks = false # <- | 72 | overflow-checks = false # <- |
| 73 | |||
| 74 | [package.metadata.embassy] | ||
| 75 | build = [ | ||
| 76 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32h5" } | ||
| 77 | ] | ||
diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs new file mode 100644 index 000000000..fb9fcbc5c --- /dev/null +++ b/examples/stm32h5/src/bin/adc_dma.rs | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; | ||
| 7 | use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; | ||
| 8 | use embassy_stm32::{Config, Peri}; | ||
| 9 | use embassy_time::Instant; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(spawner: Spawner) { | ||
| 14 | let mut config = Config::default(); | ||
| 15 | { | ||
| 16 | use embassy_stm32::rcc::*; | ||
| 17 | config.rcc.hsi = Some(HSIPrescaler::DIV1); | ||
| 18 | config.rcc.csi = true; | ||
| 19 | config.rcc.pll1 = Some(Pll { | ||
| 20 | source: PllSource::HSI, | ||
| 21 | prediv: PllPreDiv::DIV4, | ||
| 22 | mul: PllMul::MUL25, | ||
| 23 | divp: Some(PllDiv::DIV2), | ||
| 24 | divq: Some(PllDiv::DIV4), // SPI1 cksel defaults to pll1_q | ||
| 25 | divr: None, | ||
| 26 | }); | ||
| 27 | config.rcc.pll2 = Some(Pll { | ||
| 28 | source: PllSource::HSI, | ||
| 29 | prediv: PllPreDiv::DIV4, | ||
| 30 | mul: PllMul::MUL25, | ||
| 31 | divp: None, | ||
| 32 | divq: None, | ||
| 33 | divr: Some(PllDiv::DIV4), // 100mhz | ||
| 34 | }); | ||
| 35 | config.rcc.sys = Sysclk::PLL1_P; // 200 Mhz | ||
| 36 | config.rcc.ahb_pre = AHBPrescaler::DIV1; // 200 Mhz | ||
| 37 | config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 38 | config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 39 | config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 40 | config.rcc.voltage_scale = VoltageScale::Scale1; | ||
| 41 | config.rcc.mux.adcdacsel = mux::Adcdacsel::PLL2_R; | ||
| 42 | } | ||
| 43 | let p = embassy_stm32::init(config); | ||
| 44 | |||
| 45 | spawner.spawn(unwrap!(adc1_task(p.ADC1, p.GPDMA1_CH0, p.PA0, p.PA2))); | ||
| 46 | spawner.spawn(unwrap!(adc2_task(p.ADC2, p.GPDMA1_CH1, p.PA1, p.PA3))); | ||
| 47 | } | ||
| 48 | |||
| 49 | #[embassy_executor::task] | ||
| 50 | async fn adc1_task( | ||
| 51 | adc: Peri<'static, ADC1>, | ||
| 52 | dma: Peri<'static, GPDMA1_CH0>, | ||
| 53 | pin1: Peri<'static, PA0>, | ||
| 54 | pin2: Peri<'static, PA2>, | ||
| 55 | ) { | ||
| 56 | adc_task(adc, dma, pin1, pin2).await; | ||
| 57 | } | ||
| 58 | |||
| 59 | #[embassy_executor::task] | ||
| 60 | async fn adc2_task( | ||
| 61 | adc: Peri<'static, ADC2>, | ||
| 62 | dma: Peri<'static, GPDMA1_CH1>, | ||
| 63 | pin1: Peri<'static, PA1>, | ||
| 64 | pin2: Peri<'static, PA3>, | ||
| 65 | ) { | ||
| 66 | adc_task(adc, dma, pin1, pin2).await; | ||
| 67 | } | ||
| 68 | |||
| 69 | async fn adc_task<'a, T: adc::Instance>( | ||
| 70 | adc: Peri<'a, T>, | ||
| 71 | mut dma: Peri<'a, impl RxDma<T>>, | ||
| 72 | pin1: impl AdcChannel<T>, | ||
| 73 | pin2: impl AdcChannel<T>, | ||
| 74 | ) { | ||
| 75 | let mut adc = Adc::new(adc); | ||
| 76 | let mut pin1 = pin1.degrade_adc(); | ||
| 77 | let mut pin2 = pin2.degrade_adc(); | ||
| 78 | |||
| 79 | let mut tic = Instant::now(); | ||
| 80 | let mut buffer = [0u16; 512]; | ||
| 81 | loop { | ||
| 82 | // This is not a true continuous read as there is downtime between each | ||
| 83 | // call to `Adc::read` where the ADC is sitting idle. | ||
| 84 | adc.read( | ||
| 85 | dma.reborrow(), | ||
| 86 | [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), | ||
| 87 | &mut buffer, | ||
| 88 | ) | ||
| 89 | .await; | ||
| 90 | let toc = Instant::now(); | ||
| 91 | info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); | ||
| 92 | tic = toc; | ||
| 93 | } | ||
| 94 | } | ||
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 4034b552c..a84fe358b 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -15,7 +15,6 @@ use embassy_stm32::time::Hertz; | |||
| 15 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 15 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| 16 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| 17 | use embedded_io_async::Write; | 17 | use embedded_io_async::Write; |
| 18 | use rand_core::RngCore; | ||
| 19 | use static_cell::StaticCell; | 18 | use static_cell::StaticCell; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 20 | ||
| @@ -95,7 +94,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 95 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 94 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 96 | 95 | ||
| 97 | // Launch network task | 96 | // Launch network task |
| 98 | unwrap!(spawner.spawn(net_task(runner))); | 97 | spawner.spawn(unwrap!(net_task(runner))); |
| 99 | 98 | ||
| 100 | // Ensure DHCP configuration is up before trying connect | 99 | // Ensure DHCP configuration is up before trying connect |
| 101 | stack.wait_config_up().await; | 100 | stack.wait_config_up().await; |
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs index 31e83cbb5..870c57e0f 100644 --- a/examples/stm32h5/src/bin/i2c.rs +++ b/examples/stm32h5/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::{Error, I2c}; | 6 | use embassy_stm32::i2c::{Error, I2c}; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 7 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 9 | ||
| @@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) { | |||
| 28 | Irqs, | 27 | Irqs, |
| 29 | p.GPDMA1_CH4, | 28 | p.GPDMA1_CH4, |
| 30 | p.GPDMA1_CH5, | 29 | p.GPDMA1_CH5, |
| 31 | Hertz(100_000), | ||
| 32 | Default::default(), | 30 | Default::default(), |
| 33 | ); | 31 | ); |
| 34 | 32 | ||
diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs new file mode 100644 index 000000000..0e182f9cf --- /dev/null +++ b/examples/stm32h5/src/bin/sai.rs | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::{sai, Config}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | info!("Hello world."); | ||
| 12 | |||
| 13 | let mut config = Config::default(); | ||
| 14 | { | ||
| 15 | use embassy_stm32::rcc::*; | ||
| 16 | |||
| 17 | config.rcc.pll2 = Some(Pll { | ||
| 18 | source: PllSource::HSI, | ||
| 19 | prediv: PllPreDiv::DIV16, | ||
| 20 | mul: PllMul::MUL32, | ||
| 21 | divp: Some(PllDiv::DIV16), // 8 MHz SAI clock | ||
| 22 | divq: None, | ||
| 23 | divr: None, | ||
| 24 | }); | ||
| 25 | |||
| 26 | config.rcc.mux.sai1sel = mux::Saisel::PLL2_P; | ||
| 27 | } | ||
| 28 | let p = embassy_stm32::init(config); | ||
| 29 | |||
| 30 | let mut write_buffer = [0u16; 1024]; | ||
| 31 | let (_, sai_b) = sai::split_subblocks(p.SAI1); | ||
| 32 | |||
| 33 | let mut sai_b = sai::Sai::new_asynchronous( | ||
| 34 | sai_b, | ||
| 35 | p.PF8, | ||
| 36 | p.PE3, | ||
| 37 | p.PF9, | ||
| 38 | p.GPDMA1_CH0, | ||
| 39 | &mut write_buffer, | ||
| 40 | Default::default(), | ||
| 41 | ); | ||
| 42 | |||
| 43 | // Populate arbitrary data. | ||
| 44 | let mut data = [0u16; 256]; | ||
| 45 | for (index, sample) in data.iter_mut().enumerate() { | ||
| 46 | *sample = index as u16; | ||
| 47 | } | ||
| 48 | |||
| 49 | loop { | ||
| 50 | sai_b.write(&data).await.unwrap(); | ||
| 51 | } | ||
| 52 | } | ||
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs index e650791c5..3c4f49f64 100644 --- a/examples/stm32h5/src/bin/stop.rs +++ b/examples/stm32h5/src/bin/stop.rs | |||
| @@ -18,7 +18,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 18 | #[cortex_m_rt::entry] | 18 | #[cortex_m_rt::entry] |
| 19 | fn main() -> ! { | 19 | fn main() -> ! { |
| 20 | Executor::take().run(|spawner| { | 20 | Executor::take().run(|spawner| { |
| 21 | unwrap!(spawner.spawn(async_main(spawner))); | 21 | spawner.spawn(unwrap!(async_main(spawner))); |
| 22 | }) | 22 | }) |
| 23 | } | 23 | } |
| 24 | 24 | ||
| @@ -43,8 +43,8 @@ async fn async_main(spawner: Spawner) { | |||
| 43 | let rtc = RTC.init(rtc); | 43 | let rtc = RTC.init(rtc); |
| 44 | embassy_stm32::low_power::stop_with_rtc(rtc); | 44 | embassy_stm32::low_power::stop_with_rtc(rtc); |
| 45 | 45 | ||
| 46 | unwrap!(spawner.spawn(blinky(p.PB4.into()))); | 46 | spawner.spawn(unwrap!(blinky(p.PB4.into()))); |
| 47 | unwrap!(spawner.spawn(timeout())); | 47 | spawner.spawn(unwrap!(timeout())); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | #[embassy_executor::task] | 50 | #[embassy_executor::task] |
diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h5/src/bin/usart.rs +++ b/examples/stm32h5/src/bin/usart.rs | |||
| @@ -34,6 +34,6 @@ fn main() -> ! { | |||
| 34 | let executor = EXECUTOR.init(Executor::new()); | 34 | let executor = EXECUTOR.init(Executor::new()); |
| 35 | 35 | ||
| 36 | executor.run(|spawner| { | 36 | executor.run(|spawner| { |
| 37 | unwrap!(spawner.spawn(main_task())); | 37 | spawner.spawn(unwrap!(main_task())); |
| 38 | }) | 38 | }) |
| 39 | } | 39 | } |
diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs index c644e84bd..ea48515d7 100644 --- a/examples/stm32h5/src/bin/usart_dma.rs +++ b/examples/stm32h5/src/bin/usart_dma.rs | |||
| @@ -42,6 +42,6 @@ fn main() -> ! { | |||
| 42 | let executor = EXECUTOR.init(Executor::new()); | 42 | let executor = EXECUTOR.init(Executor::new()); |
| 43 | 43 | ||
| 44 | executor.run(|spawner| { | 44 | executor.run(|spawner| { |
| 45 | unwrap!(spawner.spawn(main_task())); | 45 | spawner.spawn(unwrap!(main_task())); |
| 46 | }) | 46 | }) |
| 47 | } | 47 | } |
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs index d26c5003c..f56c1c57d 100644 --- a/examples/stm32h5/src/bin/usart_split.rs +++ b/examples/stm32h5/src/bin/usart_split.rs | |||
| @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 27 | 27 | ||
| 28 | let (mut tx, rx) = usart.split(); | 28 | let (mut tx, rx) = usart.split(); |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(reader(rx))); | 30 | spawner.spawn(unwrap!(reader(rx))); |
| 31 | 31 | ||
| 32 | loop { | 32 | loop { |
| 33 | let buf = CHANNEL.receive().await; | 33 | let buf = CHANNEL.receive().await; |
diff --git a/examples/stm32h5/src/bin/usb_uac_speaker.rs b/examples/stm32h5/src/bin/usb_uac_speaker.rs index 5d007261c..86873cabd 100644 --- a/examples/stm32h5/src/bin/usb_uac_speaker.rs +++ b/examples/stm32h5/src/bin/usb_uac_speaker.rs | |||
| @@ -366,9 +366,9 @@ async fn main(spawner: Spawner) { | |||
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | // Launch USB audio tasks. | 368 | // Launch USB audio tasks. |
| 369 | unwrap!(spawner.spawn(usb_control_task(control_monitor))); | 369 | spawner.spawn(unwrap!(usb_control_task(control_monitor))); |
| 370 | unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); | 370 | spawner.spawn(unwrap!(usb_streaming_task(stream, sender))); |
| 371 | unwrap!(spawner.spawn(usb_feedback_task(feedback))); | 371 | spawner.spawn(unwrap!(usb_feedback_task(feedback))); |
| 372 | unwrap!(spawner.spawn(usb_task(usb_device))); | 372 | spawner.spawn(unwrap!(usb_task(usb_device))); |
| 373 | unwrap!(spawner.spawn(audio_receiver_task(receiver))); | 373 | spawner.spawn(unwrap!(audio_receiver_task(receiver))); |
| 374 | } | 374 | } |
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 2f98542bb..9a2080013 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml | |||
| @@ -3,20 +3,21 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h7-examples" | 3 | name = "embassy-stm32h7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h743bi to your chip name, if necessary. | 9 | # Change stm32h743bi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 12 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 12 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 13 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 14 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 15 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 16 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | 21 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| @@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 25 | embedded-hal-async = { version = "1.0" } | 26 | embedded-hal-async = { version = "1.0" } |
| 26 | embedded-nal-async = "0.8.0" | 27 | embedded-nal-async = "0.8.0" |
| 27 | embedded-io-async = { version = "0.6.1" } | 28 | embedded-io-async = { version = "0.6.1" } |
| 28 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 29 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 29 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 30 | rand_core = "0.6.3" | ||
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.3.0" |
| @@ -73,3 +73,8 @@ incremental = false | |||
| 73 | lto = 'fat' | 73 | lto = 'fat' |
| 74 | opt-level = 3 # <- | 74 | opt-level = 3 # <- |
| 75 | overflow-checks = false # <- | 75 | overflow-checks = false # <- |
| 76 | |||
| 77 | [package.metadata.embassy] | ||
| 78 | build = [ | ||
| 79 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7" } | ||
| 80 | ] | ||
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 170a5aa28..8f2e265d6 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs | |||
| @@ -6,7 +6,6 @@ use embassy_stm32::dcmi::{self, *}; | |||
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::i2c::I2c; | 7 | use embassy_stm32::i2c::I2c; |
| 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; | 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; |
| 9 | use embassy_stm32::time::khz; | ||
| 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; | 9 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; |
| 11 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 12 | use ov7725::*; | 11 | use ov7725::*; |
| @@ -52,16 +51,7 @@ async fn main(_spawner: Spawner) { | |||
| 52 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); | 51 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); |
| 53 | 52 | ||
| 54 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); | 53 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); |
| 55 | let cam_i2c = I2c::new( | 54 | let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); |
| 56 | p.I2C1, | ||
| 57 | p.PB8, | ||
| 58 | p.PB9, | ||
| 59 | Irqs, | ||
| 60 | p.DMA1_CH1, | ||
| 61 | p.DMA1_CH2, | ||
| 62 | khz(100), | ||
| 63 | Default::default(), | ||
| 64 | ); | ||
| 65 | 55 | ||
| 66 | let mut camera = Ov7725::new(cam_i2c, mco); | 56 | let mut camera = Ov7725::new(cam_i2c, mco); |
| 67 | 57 | ||
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 8314754bc..df37e9d78 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs | |||
| @@ -53,8 +53,8 @@ async fn main(spawner: Spawner) { | |||
| 53 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) | 53 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) |
| 54 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); | 54 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); |
| 55 | 55 | ||
| 56 | spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); | 56 | spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap()); |
| 57 | spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); | 57 | spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap()); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | #[embassy_executor::task] | 60 | #[embassy_executor::task] |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index da7aa4af5..6c215362d 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng; | |||
| 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use embedded_io_async::Write; | 13 | use embedded_io_async::Write; |
| 14 | use rand_core::RngCore; | ||
| 15 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 16 | ||
| @@ -94,7 +93,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 94 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 95 | 94 | ||
| 96 | // Launch network task | 95 | // Launch network task |
| 97 | unwrap!(spawner.spawn(net_task(runner))); | 96 | spawner.spawn(unwrap!(net_task(runner))); |
| 98 | 97 | ||
| 99 | // Ensure DHCP configuration is up before trying connect | 98 | // Ensure DHCP configuration is up before trying connect |
| 100 | stack.wait_config_up().await; | 99 | stack.wait_config_up().await; |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 10485109a..10ac57fc9 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | |||
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 16 | use embedded_nal_async::TcpConnect; | 16 | use embedded_nal_async::TcpConnect; |
| 17 | use rand_core::RngCore; | ||
| 18 | use static_cell::StaticCell; | 17 | use static_cell::StaticCell; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 19 | ||
| @@ -96,7 +95,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 96 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 95 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 97 | 96 | ||
| 98 | // Launch network task | 97 | // Launch network task |
| 99 | unwrap!(spawner.spawn(net_task(runner))); | 98 | spawner.spawn(unwrap!(net_task(runner))); |
| 100 | 99 | ||
| 101 | // Ensure DHCP configuration is up before trying connect | 100 | // Ensure DHCP configuration is up before trying connect |
| 102 | stack.wait_config_up().await; | 101 | stack.wait_config_up().await; |
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index 849173615..c6a108471 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs | |||
| @@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | |||
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 16 | use embedded_nal_async::TcpConnect; | 16 | use embedded_nal_async::TcpConnect; |
| 17 | use rand_core::RngCore; | ||
| 18 | use static_cell::StaticCell; | 17 | use static_cell::StaticCell; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 19 | ||
| @@ -102,7 +101,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 102 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 101 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 103 | 102 | ||
| 104 | // Launch network task | 103 | // Launch network task |
| 105 | unwrap!(spawner.spawn(net_task(runner))); | 104 | spawner.spawn(unwrap!(net_task(runner))); |
| 106 | 105 | ||
| 107 | // Ensure DHCP configuration is up before trying connect | 106 | // Ensure DHCP configuration is up before trying connect |
| 108 | stack.wait_config_up().await; | 107 | stack.wait_config_up().await; |
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs index 3bf39eb44..c40af4935 100644 --- a/examples/stm32h7/src/bin/i2c.rs +++ b/examples/stm32h7/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::{Error, I2c}; | 6 | use embassy_stm32::i2c::{Error, I2c}; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 7 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 9 | ||
| @@ -21,16 +20,7 @@ async fn main(_spawner: Spawner) { | |||
| 21 | info!("Hello world!"); | 20 | info!("Hello world!"); |
| 22 | let p = embassy_stm32::init(Default::default()); | 21 | let p = embassy_stm32::init(Default::default()); |
| 23 | 22 | ||
| 24 | let mut i2c = I2c::new( | 23 | let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); |
| 25 | p.I2C2, | ||
| 26 | p.PB10, | ||
| 27 | p.PB11, | ||
| 28 | Irqs, | ||
| 29 | p.DMA1_CH4, | ||
| 30 | p.DMA1_CH5, | ||
| 31 | Hertz(100_000), | ||
| 32 | Default::default(), | ||
| 33 | ); | ||
| 34 | 24 | ||
| 35 | let mut data = [0u8; 1]; | 25 | let mut data = [0u8; 1]; |
| 36 | 26 | ||
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 136b91eeb..9e45d845f 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs | |||
| @@ -8,7 +8,6 @@ use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; | |||
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::i2c::{self, I2c}; | 9 | use embassy_stm32::i2c::{self, I2c}; |
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::time::Hertz; | ||
| 12 | use embassy_stm32::{bind_interrupts, peripherals}; | 11 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 13 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | 12 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; |
| 14 | use embassy_sync::blocking_mutex::NoopMutex; | 13 | use embassy_sync::blocking_mutex::NoopMutex; |
| @@ -25,7 +24,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17]; | |||
| 25 | const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; | 24 | const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; |
| 26 | const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; | 25 | const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; |
| 27 | 26 | ||
| 28 | static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new(); | 27 | static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async, i2c::Master>>>> = StaticCell::new(); |
| 29 | 28 | ||
| 30 | bind_interrupts!(struct Irqs { | 29 | bind_interrupts!(struct Irqs { |
| 31 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | 30 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; |
| @@ -33,7 +32,7 @@ bind_interrupts!(struct Irqs { | |||
| 33 | }); | 32 | }); |
| 34 | 33 | ||
| 35 | #[embassy_executor::task] | 34 | #[embassy_executor::task] |
| 36 | async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { | 35 | async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) { |
| 37 | let mut data = [0u8; 2]; | 36 | let mut data = [0u8; 2]; |
| 38 | 37 | ||
| 39 | loop { | 38 | loop { |
| @@ -50,7 +49,7 @@ async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Asyn | |||
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | #[embassy_executor::task] | 51 | #[embassy_executor::task] |
| 53 | async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { | 52 | async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) { |
| 54 | let mut data = [0u8; 6]; | 53 | let mut data = [0u8; 6]; |
| 55 | 54 | ||
| 56 | loop { | 55 | loop { |
| @@ -90,24 +89,15 @@ async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>> | |||
| 90 | async fn main(spawner: Spawner) { | 89 | async fn main(spawner: Spawner) { |
| 91 | let p = embassy_stm32::init(Default::default()); | 90 | let p = embassy_stm32::init(Default::default()); |
| 92 | 91 | ||
| 93 | let i2c = I2c::new( | 92 | let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); |
| 94 | p.I2C1, | ||
| 95 | p.PB8, | ||
| 96 | p.PB9, | ||
| 97 | Irqs, | ||
| 98 | p.DMA1_CH4, | ||
| 99 | p.DMA1_CH5, | ||
| 100 | Hertz(100_000), | ||
| 101 | Default::default(), | ||
| 102 | ); | ||
| 103 | let i2c_bus = NoopMutex::new(RefCell::new(i2c)); | 93 | let i2c_bus = NoopMutex::new(RefCell::new(i2c)); |
| 104 | let i2c_bus = I2C_BUS.init(i2c_bus); | 94 | let i2c_bus = I2C_BUS.init(i2c_bus); |
| 105 | 95 | ||
| 106 | // Device 1, using embedded-hal-async compatible driver for TMP117 | 96 | // Device 1, using embedded-hal-async compatible driver for TMP117 |
| 107 | let i2c_dev1 = I2cDevice::new(i2c_bus); | 97 | let i2c_dev1 = I2cDevice::new(i2c_bus); |
| 108 | spawner.spawn(temperature(i2c_dev1)).unwrap(); | 98 | spawner.spawn(temperature(i2c_dev1).unwrap()); |
| 109 | 99 | ||
| 110 | // Device 2, using embedded-hal-async compatible driver for SHTC3 | 100 | // Device 2, using embedded-hal-async compatible driver for SHTC3 |
| 111 | let i2c_dev2 = I2cDevice::new(i2c_bus); | 101 | let i2c_dev2 = I2cDevice::new(i2c_bus); |
| 112 | spawner.spawn(humidity(i2c_dev2)).unwrap(); | 102 | spawner.spawn(humidity(i2c_dev2).unwrap()); |
| 113 | } | 103 | } |
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 8de31ea5b..12abb8693 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; | 6 | use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; |
| 7 | use embassy_stm32::time::{khz, Hertz}; | 7 | use embassy_stm32::time::{khz, Hertz}; |
| 8 | use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; | 8 | use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; |
| 9 | use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; | 9 | use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin}; |
| 10 | use embassy_stm32::{Config, Peri}; | 10 | use embassy_stm32::{Config, Peri}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -67,10 +67,10 @@ pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> { | |||
| 67 | impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { | 67 | impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { |
| 68 | pub fn new( | 68 | pub fn new( |
| 69 | tim: Peri<'d, T>, | 69 | tim: Peri<'d, T>, |
| 70 | ch1: Peri<'d, impl Channel1Pin<T>>, | 70 | ch1: Peri<'d, impl TimerPin<T, Ch1>>, |
| 71 | ch2: Peri<'d, impl Channel2Pin<T>>, | 71 | ch2: Peri<'d, impl TimerPin<T, Ch2>>, |
| 72 | ch3: Peri<'d, impl Channel3Pin<T>>, | 72 | ch3: Peri<'d, impl TimerPin<T, Ch3>>, |
| 73 | ch4: Peri<'d, impl Channel4Pin<T>>, | 73 | ch4: Peri<'d, impl TimerPin<T, Ch4>>, |
| 74 | freq: Hertz, | 74 | freq: Hertz, |
| 75 | ) -> Self { | 75 | ) -> Self { |
| 76 | let af1 = ch1.af_num(); | 76 | let af1 = ch1.af_num(); |
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs | |||
| @@ -135,16 +135,16 @@ fn main() -> ! { | |||
| 135 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 136 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
| 138 | unwrap!(spawner.spawn(run_high())); | 138 | spawner.spawn(unwrap!(run_high())); |
| 139 | 139 | ||
| 140 | // Medium-priority executor: UART5, priority level 7 | 140 | // Medium-priority executor: UART5, priority level 7 |
| 141 | interrupt::UART5.set_priority(Priority::P7); | 141 | interrupt::UART5.set_priority(Priority::P7); |
| 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); | 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); |
| 143 | unwrap!(spawner.spawn(run_med())); | 143 | spawner.spawn(unwrap!(run_med())); |
| 144 | 144 | ||
| 145 | // Low priority executor: runs in thread mode, using WFE/SEV | 145 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 146 | let executor = EXECUTOR_LOW.init(Executor::new()); | 146 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 147 | executor.run(|spawner| { | 147 | executor.run(|spawner| { |
| 148 | unwrap!(spawner.spawn(run_low())); | 148 | spawner.spawn(unwrap!(run_low())); |
| 149 | }); | 149 | }); |
| 150 | } | 150 | } |
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index a1c53fc3f..73b43be69 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs | |||
| @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { | |||
| 36 | let p = embassy_stm32::init(config); | 36 | let p = embassy_stm32::init(config); |
| 37 | info!("Hello World!"); | 37 | info!("Hello World!"); |
| 38 | 38 | ||
| 39 | let ch1_pin = PwmPin::new_ch1(p.PA6, OutputType::PushPull); | 39 | let ch1_pin = PwmPin::new(p.PA6, OutputType::PushPull); |
| 40 | let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); | 40 | let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); |
| 41 | let mut ch1 = pwm.ch1(); | 41 | let mut ch1 = pwm.ch1(); |
| 42 | ch1.enable(); | 42 | ch1.enable(); |
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs index 01937593a..847b70c85 100644 --- a/examples/stm32h7/src/bin/sai.rs +++ b/examples/stm32h7/src/bin/sai.rs | |||
| @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { | |||
| 63 | tx_config.tx_rx = TxRx::Transmitter; | 63 | tx_config.tx_rx = TxRx::Transmitter; |
| 64 | tx_config.sync_output = true; | 64 | tx_config.sync_output = true; |
| 65 | tx_config.clock_strobe = ClockStrobe::Falling; | 65 | tx_config.clock_strobe = ClockStrobe::Falling; |
| 66 | tx_config.master_clock_divider = mclk_div; | 66 | tx_config.master_clock_divider = Some(mclk_div); |
| 67 | tx_config.stereo_mono = StereoMono::Stereo; | 67 | tx_config.stereo_mono = StereoMono::Stereo; |
| 68 | tx_config.data_size = DataSize::Data24; | 68 | tx_config.data_size = DataSize::Data24; |
| 69 | tx_config.bit_order = BitOrder::MsbFirst; | 69 | tx_config.bit_order = BitOrder::MsbFirst; |
| @@ -119,71 +119,7 @@ async fn main(_spawner: Spawner) { | |||
| 119 | } | 119 | } |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | const fn mclk_div_from_u8(v: u8) -> MasterClockDivider { | 122 | fn mclk_div_from_u8(v: u8) -> MasterClockDivider { |
| 123 | match v { | 123 | assert!((1..=63).contains(&v)); |
| 124 | 1 => MasterClockDivider::Div1, | 124 | MasterClockDivider::from_bits(v) |
| 125 | 2 => MasterClockDivider::Div2, | ||
| 126 | 3 => MasterClockDivider::Div3, | ||
| 127 | 4 => MasterClockDivider::Div4, | ||
| 128 | 5 => MasterClockDivider::Div5, | ||
| 129 | 6 => MasterClockDivider::Div6, | ||
| 130 | 7 => MasterClockDivider::Div7, | ||
| 131 | 8 => MasterClockDivider::Div8, | ||
| 132 | 9 => MasterClockDivider::Div9, | ||
| 133 | 10 => MasterClockDivider::Div10, | ||
| 134 | 11 => MasterClockDivider::Div11, | ||
| 135 | 12 => MasterClockDivider::Div12, | ||
| 136 | 13 => MasterClockDivider::Div13, | ||
| 137 | 14 => MasterClockDivider::Div14, | ||
| 138 | 15 => MasterClockDivider::Div15, | ||
| 139 | 16 => MasterClockDivider::Div16, | ||
| 140 | 17 => MasterClockDivider::Div17, | ||
| 141 | 18 => MasterClockDivider::Div18, | ||
| 142 | 19 => MasterClockDivider::Div19, | ||
| 143 | 20 => MasterClockDivider::Div20, | ||
| 144 | 21 => MasterClockDivider::Div21, | ||
| 145 | 22 => MasterClockDivider::Div22, | ||
| 146 | 23 => MasterClockDivider::Div23, | ||
| 147 | 24 => MasterClockDivider::Div24, | ||
| 148 | 25 => MasterClockDivider::Div25, | ||
| 149 | 26 => MasterClockDivider::Div26, | ||
| 150 | 27 => MasterClockDivider::Div27, | ||
| 151 | 28 => MasterClockDivider::Div28, | ||
| 152 | 29 => MasterClockDivider::Div29, | ||
| 153 | 30 => MasterClockDivider::Div30, | ||
| 154 | 31 => MasterClockDivider::Div31, | ||
| 155 | 32 => MasterClockDivider::Div32, | ||
| 156 | 33 => MasterClockDivider::Div33, | ||
| 157 | 34 => MasterClockDivider::Div34, | ||
| 158 | 35 => MasterClockDivider::Div35, | ||
| 159 | 36 => MasterClockDivider::Div36, | ||
| 160 | 37 => MasterClockDivider::Div37, | ||
| 161 | 38 => MasterClockDivider::Div38, | ||
| 162 | 39 => MasterClockDivider::Div39, | ||
| 163 | 40 => MasterClockDivider::Div40, | ||
| 164 | 41 => MasterClockDivider::Div41, | ||
| 165 | 42 => MasterClockDivider::Div42, | ||
| 166 | 43 => MasterClockDivider::Div43, | ||
| 167 | 44 => MasterClockDivider::Div44, | ||
| 168 | 45 => MasterClockDivider::Div45, | ||
| 169 | 46 => MasterClockDivider::Div46, | ||
| 170 | 47 => MasterClockDivider::Div47, | ||
| 171 | 48 => MasterClockDivider::Div48, | ||
| 172 | 49 => MasterClockDivider::Div49, | ||
| 173 | 50 => MasterClockDivider::Div50, | ||
| 174 | 51 => MasterClockDivider::Div51, | ||
| 175 | 52 => MasterClockDivider::Div52, | ||
| 176 | 53 => MasterClockDivider::Div53, | ||
| 177 | 54 => MasterClockDivider::Div54, | ||
| 178 | 55 => MasterClockDivider::Div55, | ||
| 179 | 56 => MasterClockDivider::Div56, | ||
| 180 | 57 => MasterClockDivider::Div57, | ||
| 181 | 58 => MasterClockDivider::Div58, | ||
| 182 | 59 => MasterClockDivider::Div59, | ||
| 183 | 60 => MasterClockDivider::Div60, | ||
| 184 | 61 => MasterClockDivider::Div61, | ||
| 185 | 62 => MasterClockDivider::Div62, | ||
| 186 | 63 => MasterClockDivider::Div63, | ||
| 187 | _ => panic!(), | ||
| 188 | } | ||
| 189 | } | 125 | } |
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs index b73360f32..97309798e 100644 --- a/examples/stm32h7/src/bin/signal.rs +++ b/examples/stm32h7/src/bin/signal.rs | |||
| @@ -26,7 +26,7 @@ async fn my_sending_task() { | |||
| 26 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 27 | async fn main(spawner: Spawner) { | 27 | async fn main(spawner: Spawner) { |
| 28 | let _p = embassy_stm32::init(Default::default()); | 28 | let _p = embassy_stm32::init(Default::default()); |
| 29 | unwrap!(spawner.spawn(my_sending_task())); | 29 | spawner.spawn(unwrap!(my_sending_task())); |
| 30 | 30 | ||
| 31 | loop { | 31 | loop { |
| 32 | let received_counter = SIGNAL.wait().await; | 32 | let received_counter = SIGNAL.wait().await; |
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index ad4a8aaf7..dce30a4a7 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs | |||
| @@ -66,6 +66,6 @@ fn main() -> ! { | |||
| 66 | let executor = EXECUTOR.init(Executor::new()); | 66 | let executor = EXECUTOR.init(Executor::new()); |
| 67 | 67 | ||
| 68 | executor.run(|spawner| { | 68 | executor.run(|spawner| { |
| 69 | unwrap!(spawner.spawn(main_task(spi))); | 69 | spawner.spawn(unwrap!(main_task(spi))); |
| 70 | }) | 70 | }) |
| 71 | } | 71 | } |
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs index 5a7dff572..828f687b8 100644 --- a/examples/stm32h7/src/bin/spi_bdma.rs +++ b/examples/stm32h7/src/bin/spi_bdma.rs | |||
| @@ -80,6 +80,6 @@ fn main() -> ! { | |||
| 80 | let executor = EXECUTOR.init(Executor::new()); | 80 | let executor = EXECUTOR.init(Executor::new()); |
| 81 | 81 | ||
| 82 | executor.run(|spawner| { | 82 | executor.run(|spawner| { |
| 83 | unwrap!(spawner.spawn(main_task(spi))); | 83 | spawner.spawn(unwrap!(main_task(spi))); |
| 84 | }) | 84 | }) |
| 85 | } | 85 | } |
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 731c7fef5..2197fabce 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs | |||
| @@ -63,6 +63,6 @@ fn main() -> ! { | |||
| 63 | let executor = EXECUTOR.init(Executor::new()); | 63 | let executor = EXECUTOR.init(Executor::new()); |
| 64 | 64 | ||
| 65 | executor.run(|spawner| { | 65 | executor.run(|spawner| { |
| 66 | unwrap!(spawner.spawn(main_task(spi))); | 66 | spawner.spawn(unwrap!(main_task(spi))); |
| 67 | }) | 67 | }) |
| 68 | } | 68 | } |
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h7/src/bin/usart.rs +++ b/examples/stm32h7/src/bin/usart.rs | |||
| @@ -34,6 +34,6 @@ fn main() -> ! { | |||
| 34 | let executor = EXECUTOR.init(Executor::new()); | 34 | let executor = EXECUTOR.init(Executor::new()); |
| 35 | 35 | ||
| 36 | executor.run(|spawner| { | 36 | executor.run(|spawner| { |
| 37 | unwrap!(spawner.spawn(main_task())); | 37 | spawner.spawn(unwrap!(main_task())); |
| 38 | }) | 38 | }) |
| 39 | } | 39 | } |
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs index 6f340d40a..23d7f193a 100644 --- a/examples/stm32h7/src/bin/usart_dma.rs +++ b/examples/stm32h7/src/bin/usart_dma.rs | |||
| @@ -42,6 +42,6 @@ fn main() -> ! { | |||
| 42 | let executor = EXECUTOR.init(Executor::new()); | 42 | let executor = EXECUTOR.init(Executor::new()); |
| 43 | 43 | ||
| 44 | executor.run(|spawner| { | 44 | executor.run(|spawner| { |
| 45 | unwrap!(spawner.spawn(main_task())); | 45 | spawner.spawn(unwrap!(main_task())); |
| 46 | }) | 46 | }) |
| 47 | } | 47 | } |
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs index 2bb58be5e..464ce8d72 100644 --- a/examples/stm32h7/src/bin/usart_split.rs +++ b/examples/stm32h7/src/bin/usart_split.rs | |||
| @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 27 | 27 | ||
| 28 | let (mut tx, rx) = usart.split(); | 28 | let (mut tx, rx) = usart.split(); |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(reader(rx))); | 30 | spawner.spawn(unwrap!(reader(rx))); |
| 31 | 31 | ||
| 32 | loop { | 32 | loop { |
| 33 | let buf = CHANNEL.receive().await; | 33 | let buf = CHANNEL.receive().await; |
diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 749fd78ae..7e4ccc528 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml | |||
| @@ -3,17 +3,18 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h723-examples" | 3 | name = "embassy-stm32h723-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h723zg to your chip name, if necessary. | 9 | # Change stm32h723zg to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | 18 | ||
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| @@ -22,9 +23,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 22 | embedded-hal-async = { version = "1.0" } | 23 | embedded-hal-async = { version = "1.0" } |
| 23 | embedded-nal-async = "0.8.0" | 24 | embedded-nal-async = "0.8.0" |
| 24 | embedded-io-async = { version = "0.6.1" } | 25 | embedded-io-async = { version = "0.6.1" } |
| 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 26 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 26 | heapless = { version = "0.8", default-features = false } | 27 | heapless = { version = "0.8", default-features = false } |
| 27 | rand_core = "0.6.3" | ||
| 28 | critical-section = "1.1" | 28 | critical-section = "1.1" |
| 29 | static_cell = "2" | 29 | static_cell = "2" |
| 30 | chrono = { version = "^0.4", default-features = false } | 30 | chrono = { version = "^0.4", default-features = false } |
| @@ -67,3 +67,8 @@ incremental = false | |||
| 67 | lto = 'fat' | 67 | lto = 'fat' |
| 68 | opt-level = 3 # <- | 68 | opt-level = 3 # <- |
| 69 | overflow-checks = false # <- | 69 | overflow-checks = false # <- |
| 70 | |||
| 71 | [package.metadata.embassy] | ||
| 72 | build = [ | ||
| 73 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h723" } | ||
| 74 | ] | ||
diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs index a04d7cb34..b75a03ae8 100644 --- a/examples/stm32h723/src/bin/spdifrx.rs +++ b/examples/stm32h723/src/bin/spdifrx.rs | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::{info, trace}; | 8 | use defmt::{info, trace}; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_futures::select::{self, select, Either}; | 10 | use embassy_futures::select::{select, Either}; |
| 11 | use embassy_stm32::spdifrx::{self, Spdifrx}; | 11 | use embassy_stm32::spdifrx::{self, Spdifrx}; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, sai}; | 12 | use embassy_stm32::{bind_interrupts, peripherals, sai, Peri}; |
| 13 | use grounded::uninit::GroundedArrayCell; | 13 | use grounded::uninit::GroundedArrayCell; |
| 14 | use hal::sai::*; | 14 | use hal::sai::*; |
| 15 | use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; | 15 | use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; |
| @@ -25,10 +25,10 @@ const DMA_BUFFER_LENGTH: usize = HALF_DMA_BUFFER_LENGTH * 2; // 2 half-blocks | |||
| 25 | 25 | ||
| 26 | // DMA buffers must be in special regions. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions | 26 | // DMA buffers must be in special regions. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions |
| 27 | #[unsafe(link_section = ".sram1")] | 27 | #[unsafe(link_section = ".sram1")] |
| 28 | static mut SPDIFRX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); | 28 | static SPDIFRX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); |
| 29 | 29 | ||
| 30 | #[unsafe(link_section = ".sram4")] | 30 | #[unsafe(link_section = ".sram4")] |
| 31 | static mut SAI_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); | 31 | static SAI_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); |
| 32 | 32 | ||
| 33 | #[embassy_executor::main] | 33 | #[embassy_executor::main] |
| 34 | async fn main(_spawner: Spawner) { | 34 | async fn main(_spawner: Spawner) { |
| @@ -144,9 +144,9 @@ async fn main(_spawner: Spawner) { | |||
| 144 | /// | 144 | /// |
| 145 | /// Used (again) after dropping the SPDIFRX instance, in case of errors (e.g. source disconnect). | 145 | /// Used (again) after dropping the SPDIFRX instance, in case of errors (e.g. source disconnect). |
| 146 | fn new_spdif_receiver<'d>( | 146 | fn new_spdif_receiver<'d>( |
| 147 | spdifrx: &'d mut peripherals::SPDIFRX1, | 147 | spdifrx: Peri<'d, peripherals::SPDIFRX1>, |
| 148 | input_pin: &'d mut peripherals::PD7, | 148 | input_pin: Peri<'d, peripherals::PD7>, |
| 149 | dma: &'d mut peripherals::DMA2_CH7, | 149 | dma: Peri<'d, peripherals::DMA2_CH7>, |
| 150 | buf: &'d mut [u32], | 150 | buf: &'d mut [u32], |
| 151 | ) -> Spdifrx<'d, peripherals::SPDIFRX1> { | 151 | ) -> Spdifrx<'d, peripherals::SPDIFRX1> { |
| 152 | Spdifrx::new(spdifrx, Irqs, spdifrx::Config::default(), input_pin, dma, buf) | 152 | Spdifrx::new(spdifrx, Irqs, spdifrx::Config::default(), input_pin, dma, buf) |
| @@ -156,11 +156,11 @@ fn new_spdif_receiver<'d>( | |||
| 156 | /// | 156 | /// |
| 157 | /// Used (again) after dropping the SAI4 instance, in case of errors (e.g. buffer overrun). | 157 | /// Used (again) after dropping the SAI4 instance, in case of errors (e.g. buffer overrun). |
| 158 | fn new_sai_transmitter<'d>( | 158 | fn new_sai_transmitter<'d>( |
| 159 | sai: &'d mut peripherals::SAI4, | 159 | sai: Peri<'d, peripherals::SAI4>, |
| 160 | sck: &'d mut peripherals::PD13, | 160 | sck: Peri<'d, peripherals::PD13>, |
| 161 | sd: &'d mut peripherals::PC1, | 161 | sd: Peri<'d, peripherals::PC1>, |
| 162 | fs: &'d mut peripherals::PD12, | 162 | fs: Peri<'d, peripherals::PD12>, |
| 163 | dma: &'d mut peripherals::BDMA_CH0, | 163 | dma: Peri<'d, peripherals::BDMA_CH0>, |
| 164 | buf: &'d mut [u32], | 164 | buf: &'d mut [u32], |
| 165 | ) -> Sai<'d, peripherals::SAI4, u32> { | 165 | ) -> Sai<'d, peripherals::SAI4, u32> { |
| 166 | let mut sai_config = hal::sai::Config::default(); | 166 | let mut sai_config = hal::sai::Config::default(); |
| @@ -168,7 +168,7 @@ fn new_sai_transmitter<'d>( | |||
| 168 | sai_config.slot_enable = 0xFFFF; // All slots | 168 | sai_config.slot_enable = 0xFFFF; // All slots |
| 169 | sai_config.data_size = sai::DataSize::Data32; | 169 | sai_config.data_size = sai::DataSize::Data32; |
| 170 | sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; | 170 | sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; |
| 171 | sai_config.master_clock_divider = hal::sai::MasterClockDivider::MasterClockDisabled; | 171 | sai_config.master_clock_divider = None; |
| 172 | 172 | ||
| 173 | let (sub_block_tx, _) = hal::sai::split_subblocks(sai); | 173 | let (sub_block_tx, _) = hal::sai::split_subblocks(sai); |
| 174 | Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) | 174 | Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) |
diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 4d31dedf1..22b7ad96a 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml | |||
| @@ -3,21 +3,22 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h735-examples" | 3 | name = "embassy-stm32h735-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 11 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | 18 | ||
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | heapless = { version = "0.8", default-features = false } | 22 | heapless = { version = "0.8", default-features = false } |
| 22 | embedded-graphics = { version = "0.8.1" } | 23 | embedded-graphics = { version = "0.8.1" } |
| 23 | tinybmp = { version = "0.5" } | 24 | tinybmp = { version = "0.5" } |
| @@ -59,3 +60,8 @@ incremental = false | |||
| 59 | lto = 'fat' | 60 | lto = 'fat' |
| 60 | opt-level = 3 # <- | 61 | opt-level = 3 # <- |
| 61 | overflow-checks = false # <- | 62 | overflow-checks = false # <- |
| 63 | |||
| 64 | [package.metadata.embassy] | ||
| 65 | build = [ | ||
| 66 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h735" } | ||
| 67 | ] | ||
diff --git a/examples/stm32h735/src/bin/ltdc.rs b/examples/stm32h735/src/bin/ltdc.rs index a36fdef2c..8a99f745d 100644 --- a/examples/stm32h735/src/bin/ltdc.rs +++ b/examples/stm32h735/src/bin/ltdc.rs | |||
| @@ -47,7 +47,7 @@ async fn main(spawner: Spawner) { | |||
| 47 | 47 | ||
| 48 | // blink the led on another task | 48 | // blink the led on another task |
| 49 | let led = Output::new(p.PC3, Level::High, Speed::Low); | 49 | let led = Output::new(p.PC3, Level::High, Speed::Low); |
| 50 | unwrap!(spawner.spawn(led_task(led))); | 50 | spawner.spawn(unwrap!(led_task(led))); |
| 51 | 51 | ||
| 52 | // numbers from STMicroelectronics/STM32CubeH7 STM32H735G-DK C-based example | 52 | // numbers from STMicroelectronics/STM32CubeH7 STM32H735G-DK C-based example |
| 53 | const RK043FN48H_HSYNC: u16 = 41; // Horizontal synchronization | 53 | const RK043FN48H_HSYNC: u16 = 41; // Horizontal synchronization |
diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index e2e0094b8..c76340b5f 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2021" |
| 3 | name = "embassy-stm32f7-examples" | 3 | name = "embassy-stm32h742-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32f777zi to your chip name, if necessary. | 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ | ||
| 10 | "defmt", | 10 | "defmt", |
| 11 | "stm32h742vi", | 11 | "stm32h742vi", |
| 12 | "memory-x", | 12 | "memory-x", |
| @@ -14,33 +14,33 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ | |||
| 14 | "time-driver-any", | 14 | "time-driver-any", |
| 15 | "exti", | 15 | "exti", |
| 16 | ] } | 16 | ] } |
| 17 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ | 17 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ |
| 18 | "defmt", | 18 | "defmt", |
| 19 | ] } | 19 | ] } |
| 20 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ | 20 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ |
| 21 | "arch-cortex-m", | 21 | "arch-cortex-m", |
| 22 | "executor-thread", | 22 | "executor-thread", |
| 23 | "defmt", | 23 | "defmt", |
| 24 | ] } | 24 | ] } |
| 25 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ | 25 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ |
| 26 | "defmt", | 26 | "defmt", |
| 27 | "defmt-timestamp-uptime", | 27 | "defmt-timestamp-uptime", |
| 28 | "tick-hz-32_768", | 28 | "tick-hz-32_768", |
| 29 | ] } | 29 | ] } |
| 30 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = [ | 30 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = [ |
| 31 | "defmt", | 31 | "defmt", |
| 32 | "tcp", | 32 | "tcp", |
| 33 | "dhcpv4", | 33 | "dhcpv4", |
| 34 | "medium-ethernet", | 34 | "medium-ethernet", |
| 35 | ] } | 35 | ] } |
| 36 | embedded-io-async = { version = "0.6.1" } | 36 | embedded-io-async = { version = "0.6.1" } |
| 37 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = [ | 37 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = [ |
| 38 | "defmt", | 38 | "defmt", |
| 39 | ] } | 39 | ] } |
| 40 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 40 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 41 | 41 | ||
| 42 | defmt = "0.3" | 42 | defmt = "1.0.1" |
| 43 | defmt-rtt = "0.4" | 43 | defmt-rtt = "1.0.0" |
| 44 | 44 | ||
| 45 | cortex-m = { version = "0.7.6", features = [ | 45 | cortex-m = { version = "0.7.6", features = [ |
| 46 | "inline-asm", | 46 | "inline-asm", |
| @@ -48,10 +48,9 @@ cortex-m = { version = "0.7.6", features = [ | |||
| 48 | ] } | 48 | ] } |
| 49 | cortex-m-rt = "0.7.0" | 49 | cortex-m-rt = "0.7.0" |
| 50 | embedded-hal = "0.2.6" | 50 | embedded-hal = "0.2.6" |
| 51 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 51 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 52 | heapless = { version = "0.8", default-features = false } | 52 | heapless = { version = "0.8", default-features = false } |
| 53 | nb = "1.0.0" | 53 | nb = "1.0.0" |
| 54 | rand_core = "0.6.3" | ||
| 55 | critical-section = "1.1" | 54 | critical-section = "1.1" |
| 56 | embedded-storage = "0.3.1" | 55 | embedded-storage = "0.3.1" |
| 57 | static_cell = "2" | 56 | static_cell = "2" |
| @@ -64,3 +63,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = [ | |||
| 64 | 63 | ||
| 65 | [profile.release] | 64 | [profile.release] |
| 66 | debug = 2 | 65 | debug = 2 |
| 66 | |||
| 67 | [package.metadata.embassy] | ||
| 68 | build = [ | ||
| 69 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h742" } | ||
| 70 | ] | ||
diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs index aee07f3f2..9e79d7089 100644 --- a/examples/stm32h742/src/bin/qspi.rs +++ b/examples/stm32h742/src/bin/qspi.rs | |||
| @@ -266,13 +266,14 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 266 | let p = embassy_stm32::init(config); | 266 | let p = embassy_stm32::init(config); |
| 267 | info!("Embassy initialized"); | 267 | info!("Embassy initialized"); |
| 268 | 268 | ||
| 269 | let config = QspiCfg { | 269 | let mut config = QspiCfg::default(); |
| 270 | memory_size: MemorySize::_8MiB, | 270 | config.memory_size = MemorySize::_8MiB; |
| 271 | address_size: AddressSize::_24bit, | 271 | config.address_size = AddressSize::_24bit; |
| 272 | prescaler: 16, | 272 | config.prescaler = 16; |
| 273 | cs_high_time: ChipSelectHighTime::_1Cycle, | 273 | config.cs_high_time = ChipSelectHighTime::_1Cycle; |
| 274 | fifo_threshold: FIFOThresholdLevel::_16Bytes, | 274 | config.fifo_threshold = FIFOThresholdLevel::_16Bytes; |
| 275 | }; | 275 | config.sample_shifting = SampleShifting::None; |
| 276 | |||
| 276 | let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config); | 277 | let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config); |
| 277 | let mut flash = FlashMemory::new(driver); | 278 | let mut flash = FlashMemory::new(driver); |
| 278 | let flash_id = flash.read_id(); | 279 | let flash_id = flash.read_id(); |
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 7c17bc766..c73f9df79 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml | |||
| @@ -3,20 +3,21 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h755cm4-examples" | 3 | name = "embassy-stm32h755cm4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h755zi-cm4 to your chip name, if necessary. | 9 | # Change stm32h755zi-cm4 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 12 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 12 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 13 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 14 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 15 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 16 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | 21 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| @@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 25 | embedded-hal-async = { version = "1.0" } | 26 | embedded-hal-async = { version = "1.0" } |
| 26 | embedded-nal-async = "0.8.0" | 27 | embedded-nal-async = "0.8.0" |
| 27 | embedded-io-async = { version = "0.6.1" } | 28 | embedded-io-async = { version = "0.6.1" } |
| 28 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 29 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 29 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 30 | rand_core = "0.6.3" | ||
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.3.0" |
| @@ -37,13 +37,6 @@ chrono = { version = "^0.4", default-features = false } | |||
| 37 | grounded = "0.2.0" | 37 | grounded = "0.2.0" |
| 38 | 38 | ||
| 39 | # cargo build/run | 39 | # cargo build/run |
| 40 | [profile.dev] | ||
| 41 | codegen-units = 1 | ||
| 42 | debug = 2 | ||
| 43 | debug-assertions = true # <- | ||
| 44 | incremental = false | ||
| 45 | opt-level = 3 # <- | ||
| 46 | overflow-checks = true # <- | ||
| 47 | 40 | ||
| 48 | # cargo test | 41 | # cargo test |
| 49 | [profile.test] | 42 | [profile.test] |
| @@ -56,11 +49,10 @@ overflow-checks = true # <- | |||
| 56 | 49 | ||
| 57 | # cargo build/run --release | 50 | # cargo build/run --release |
| 58 | [profile.release] | 51 | [profile.release] |
| 59 | codegen-units = 1 | 52 | codegen-units = 16 |
| 60 | debug = 2 | 53 | debug = 2 |
| 61 | debug-assertions = false # <- | 54 | debug-assertions = false # <- |
| 62 | incremental = false | 55 | incremental = false |
| 63 | lto = 'fat' | ||
| 64 | opt-level = 3 # <- | 56 | opt-level = 3 # <- |
| 65 | overflow-checks = false # <- | 57 | overflow-checks = false # <- |
| 66 | 58 | ||
| @@ -73,3 +65,8 @@ incremental = false | |||
| 73 | lto = 'fat' | 65 | lto = 'fat' |
| 74 | opt-level = 3 # <- | 66 | opt-level = 3 # <- |
| 75 | overflow-checks = false # <- | 67 | overflow-checks = false # <- |
| 68 | |||
| 69 | [package.metadata.embassy] | ||
| 70 | build = [ | ||
| 71 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm4" } | ||
| 72 | ] | ||
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs new file mode 100644 index 000000000..f584e31e9 --- /dev/null +++ b/examples/stm32h755cm4/src/bin/intercore.rs | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | //! STM32H7 Secondary Core (CM4) Intercore Communication Example | ||
| 5 | //! | ||
| 6 | //! This example demonstrates reliable communication between the Cortex-M7 and | ||
| 7 | //! Cortex-M4 cores. This secondary core monitors shared memory for LED state | ||
| 8 | //! changes and updates the physical LEDs accordingly. | ||
| 9 | //! | ||
| 10 | //! The CM4 core handles: | ||
| 11 | //! - Responding to state changes from CM7 | ||
| 12 | //! - Controlling the physical green and yellow LEDs | ||
| 13 | //! - Providing visual feedback via a heartbeat on the red LED | ||
| 14 | //! | ||
| 15 | //! Usage: | ||
| 16 | //! 1. Flash this CM4 (secondary) core binary first | ||
| 17 | //! 2. Then flash the CM7 (primary) core binary | ||
| 18 | //! 3. The red LED should blink continuously as a heartbeat | ||
| 19 | //! 4. Green and yellow LEDs should toggle according to CM7 core signals | ||
| 20 | |||
| 21 | /// Module providing shared memory constructs for intercore communication | ||
| 22 | mod shared { | ||
| 23 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 24 | |||
| 25 | /// State shared between CM7 and CM4 cores for LED control | ||
| 26 | #[repr(C, align(4))] | ||
| 27 | pub struct SharedLedState { | ||
| 28 | pub magic: AtomicU32, | ||
| 29 | pub counter: AtomicU32, | ||
| 30 | pub led_states: AtomicU32, | ||
| 31 | } | ||
| 32 | |||
| 33 | // Bit positions in led_states | ||
| 34 | pub const GREEN_LED_BIT: u32 = 0; | ||
| 35 | pub const YELLOW_LED_BIT: u32 = 1; | ||
| 36 | |||
| 37 | impl SharedLedState { | ||
| 38 | pub const fn new() -> Self { | ||
| 39 | Self { | ||
| 40 | magic: AtomicU32::new(0xDEADBEEF), | ||
| 41 | counter: AtomicU32::new(0), | ||
| 42 | led_states: AtomicU32::new(0), | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | /// Set LED state by manipulating the appropriate bit in the led_states field | ||
| 47 | #[inline(never)] | ||
| 48 | #[allow(dead_code)] | ||
| 49 | pub fn set_led(&self, is_green: bool, state: bool) { | ||
| 50 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | ||
| 51 | let current = self.led_states.load(Ordering::SeqCst); | ||
| 52 | |||
| 53 | let new_value = if state { | ||
| 54 | current | (1 << bit) // Set bit | ||
| 55 | } else { | ||
| 56 | current & !(1 << bit) // Clear bit | ||
| 57 | }; | ||
| 58 | self.led_states.store(new_value, Ordering::SeqCst); | ||
| 59 | } | ||
| 60 | |||
| 61 | /// Get current LED state | ||
| 62 | #[inline(never)] | ||
| 63 | pub fn get_led(&self, is_green: bool) -> bool { | ||
| 64 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | ||
| 65 | |||
| 66 | let value = self.led_states.load(Ordering::SeqCst); | ||
| 67 | (value & (1 << bit)) != 0 | ||
| 68 | } | ||
| 69 | |||
| 70 | /// Increment counter and return new value | ||
| 71 | #[inline(never)] | ||
| 72 | #[allow(dead_code)] | ||
| 73 | pub fn increment_counter(&self) -> u32 { | ||
| 74 | let current = self.counter.load(Ordering::SeqCst); | ||
| 75 | let new_value = current.wrapping_add(1); | ||
| 76 | self.counter.store(new_value, Ordering::SeqCst); | ||
| 77 | new_value | ||
| 78 | } | ||
| 79 | |||
| 80 | /// Get current counter value | ||
| 81 | #[inline(never)] | ||
| 82 | pub fn get_counter(&self) -> u32 { | ||
| 83 | let value = self.counter.load(Ordering::SeqCst); | ||
| 84 | value | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | #[link_section = ".ram_d3"] | ||
| 89 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); | ||
| 90 | } | ||
| 91 | |||
| 92 | use core::mem::MaybeUninit; | ||
| 93 | |||
| 94 | use defmt::*; | ||
| 95 | use embassy_executor::Spawner; | ||
| 96 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 97 | use embassy_stm32::SharedData; | ||
| 98 | use embassy_time::Timer; | ||
| 99 | use shared::SHARED_LED_STATE; | ||
| 100 | use {defmt_rtt as _, panic_probe as _}; | ||
| 101 | |||
| 102 | #[link_section = ".ram_d3"] | ||
| 103 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 104 | |||
| 105 | /// Task that continuously blinks the red LED as a heartbeat indicator | ||
| 106 | #[embassy_executor::task] | ||
| 107 | async fn blink_heartbeat(mut led: Output<'static>) { | ||
| 108 | loop { | ||
| 109 | led.toggle(); | ||
| 110 | info!("CM4 heartbeat"); | ||
| 111 | Timer::after_millis(500).await; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | #[embassy_executor::main] | ||
| 116 | async fn main(spawner: Spawner) -> ! { | ||
| 117 | // Initialize the secondary core | ||
| 118 | let p = embassy_stm32::init_secondary(&SHARED_DATA); | ||
| 119 | info!("CM4 core initialized!"); | ||
| 120 | |||
| 121 | // Verify shared memory is accessible | ||
| 122 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); | ||
| 123 | info!("CM4: Magic value = 0x{:X}", magic); | ||
| 124 | |||
| 125 | // Set up LEDs | ||
| 126 | let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 | ||
| 127 | let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 | ||
| 128 | let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) | ||
| 129 | |||
| 130 | // Start heartbeat task | ||
| 131 | spawner.spawn(unwrap!(blink_heartbeat(red_led))); | ||
| 132 | |||
| 133 | // Track previous values to detect changes | ||
| 134 | let mut prev_green = false; | ||
| 135 | let mut prev_yellow = false; | ||
| 136 | let mut prev_counter = 0; | ||
| 137 | |||
| 138 | info!("CM4: Starting main loop"); | ||
| 139 | loop { | ||
| 140 | // Read current values from shared memory | ||
| 141 | let green_state = SHARED_LED_STATE.get_led(true); | ||
| 142 | let yellow_state = SHARED_LED_STATE.get_led(false); | ||
| 143 | let counter = SHARED_LED_STATE.get_counter(); | ||
| 144 | |||
| 145 | // Detect changes | ||
| 146 | let green_changed = green_state != prev_green; | ||
| 147 | let yellow_changed = yellow_state != prev_yellow; | ||
| 148 | let counter_changed = counter != prev_counter; | ||
| 149 | |||
| 150 | // Update LEDs and logs when values change | ||
| 151 | if green_changed || yellow_changed || counter_changed { | ||
| 152 | if counter_changed { | ||
| 153 | info!("CM4: Counter = {}", counter); | ||
| 154 | prev_counter = counter; | ||
| 155 | } | ||
| 156 | |||
| 157 | if green_changed { | ||
| 158 | if green_state { | ||
| 159 | green_led.set_high(); | ||
| 160 | info!("CM4: Green LED ON"); | ||
| 161 | } else { | ||
| 162 | green_led.set_low(); | ||
| 163 | info!("CM4: Green LED OFF"); | ||
| 164 | } | ||
| 165 | prev_green = green_state; | ||
| 166 | } | ||
| 167 | |||
| 168 | if yellow_changed { | ||
| 169 | if yellow_state { | ||
| 170 | yellow_led.set_high(); | ||
| 171 | info!("CM4: Yellow LED ON"); | ||
| 172 | } else { | ||
| 173 | yellow_led.set_low(); | ||
| 174 | info!("CM4: Yellow LED OFF"); | ||
| 175 | } | ||
| 176 | prev_yellow = yellow_state; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | Timer::after_millis(10).await; | ||
| 181 | } | ||
| 182 | } | ||
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 3186929a8..c34d4e45c 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml | |||
| @@ -3,20 +3,21 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h755cm7-examples" | 3 | name = "embassy-stm32h755cm7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h743bi to your chip name, if necessary. | 9 | # Change stm32h743bi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 12 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 12 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 13 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 14 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 15 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 16 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | 21 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| @@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 25 | embedded-hal-async = { version = "1.0" } | 26 | embedded-hal-async = { version = "1.0" } |
| 26 | embedded-nal-async = "0.8.0" | 27 | embedded-nal-async = "0.8.0" |
| 27 | embedded-io-async = { version = "0.6.1" } | 28 | embedded-io-async = { version = "0.6.1" } |
| 28 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 29 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 29 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 30 | rand_core = "0.6.3" | ||
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.3.0" |
| @@ -36,15 +36,6 @@ static_cell = "2" | |||
| 36 | chrono = { version = "^0.4", default-features = false } | 36 | chrono = { version = "^0.4", default-features = false } |
| 37 | grounded = "0.2.0" | 37 | grounded = "0.2.0" |
| 38 | 38 | ||
| 39 | # cargo build/run | ||
| 40 | [profile.dev] | ||
| 41 | codegen-units = 1 | ||
| 42 | debug = 2 | ||
| 43 | debug-assertions = true # <- | ||
| 44 | incremental = false | ||
| 45 | opt-level = 3 # <- | ||
| 46 | overflow-checks = true # <- | ||
| 47 | |||
| 48 | # cargo test | 39 | # cargo test |
| 49 | [profile.test] | 40 | [profile.test] |
| 50 | codegen-units = 1 | 41 | codegen-units = 1 |
| @@ -56,11 +47,10 @@ overflow-checks = true # <- | |||
| 56 | 47 | ||
| 57 | # cargo build/run --release | 48 | # cargo build/run --release |
| 58 | [profile.release] | 49 | [profile.release] |
| 59 | codegen-units = 1 | 50 | codegen-units = 16 |
| 60 | debug = 2 | 51 | debug = 2 |
| 61 | debug-assertions = false # <- | 52 | debug-assertions = false # <- |
| 62 | incremental = false | 53 | incremental = false |
| 63 | lto = 'fat' | ||
| 64 | opt-level = 3 # <- | 54 | opt-level = 3 # <- |
| 65 | overflow-checks = false # <- | 55 | overflow-checks = false # <- |
| 66 | 56 | ||
| @@ -73,3 +63,8 @@ incremental = false | |||
| 73 | lto = 'fat' | 63 | lto = 'fat' |
| 74 | opt-level = 3 # <- | 64 | opt-level = 3 # <- |
| 75 | overflow-checks = false # <- | 65 | overflow-checks = false # <- |
| 66 | |||
| 67 | [package.metadata.embassy] | ||
| 68 | build = [ | ||
| 69 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm7" } | ||
| 70 | ] | ||
diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs new file mode 100644 index 000000000..a4e1b5ff4 --- /dev/null +++ b/examples/stm32h755cm7/src/bin/intercore.rs | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | //! STM32H7 Primary Core (CM7) Intercore Communication Example | ||
| 5 | //! | ||
| 6 | //! This example demonstrates reliable communication between the Cortex-M7 and | ||
| 7 | //! Cortex-M4 cores using a shared memory region configured as non-cacheable | ||
| 8 | //! via MPU settings. | ||
| 9 | //! | ||
| 10 | //! The CM7 core handles: | ||
| 11 | //! - MPU configuration to make shared memory non-cacheable | ||
| 12 | //! - Clock initialization | ||
| 13 | //! - Toggling LED states in shared memory | ||
| 14 | //! | ||
| 15 | //! Usage: | ||
| 16 | //! 1. Flash the CM4 (secondary) core binary first | ||
| 17 | //! 2. Then flash this CM7 (primary) core binary | ||
| 18 | //! 3. The system will start with CM7 toggling LED states and CM4 responding by | ||
| 19 | //! physically toggling the LEDs | ||
| 20 | |||
| 21 | use core::mem::MaybeUninit; | ||
| 22 | |||
| 23 | use cortex_m::asm; | ||
| 24 | use cortex_m::peripheral::MPU; | ||
| 25 | use defmt::*; | ||
| 26 | use embassy_executor::Spawner; | ||
| 27 | use embassy_stm32::{Config, SharedData}; | ||
| 28 | use embassy_time::Timer; | ||
| 29 | use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; | ||
| 30 | use {defmt_rtt as _, panic_probe as _}; | ||
| 31 | |||
| 32 | /// Module providing shared memory constructs for intercore communication | ||
| 33 | mod shared { | ||
| 34 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 35 | |||
| 36 | /// State shared between CM7 and CM4 cores for LED control | ||
| 37 | #[repr(C, align(4))] | ||
| 38 | pub struct SharedLedState { | ||
| 39 | pub magic: AtomicU32, | ||
| 40 | pub counter: AtomicU32, | ||
| 41 | pub led_states: AtomicU32, | ||
| 42 | } | ||
| 43 | |||
| 44 | // Bit positions in led_states | ||
| 45 | pub const GREEN_LED_BIT: u32 = 0; | ||
| 46 | pub const YELLOW_LED_BIT: u32 = 1; | ||
| 47 | |||
| 48 | impl SharedLedState { | ||
| 49 | pub const fn new() -> Self { | ||
| 50 | Self { | ||
| 51 | magic: AtomicU32::new(0xDEADBEEF), | ||
| 52 | counter: AtomicU32::new(0), | ||
| 53 | led_states: AtomicU32::new(0), | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | /// Set LED state by manipulating the appropriate bit in the led_states field | ||
| 58 | #[inline(never)] | ||
| 59 | pub fn set_led(&self, is_green: bool, state: bool) { | ||
| 60 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | ||
| 61 | let current = self.led_states.load(Ordering::SeqCst); | ||
| 62 | |||
| 63 | let new_value = if state { | ||
| 64 | current | (1 << bit) // Set bit | ||
| 65 | } else { | ||
| 66 | current & !(1 << bit) // Clear bit | ||
| 67 | }; | ||
| 68 | |||
| 69 | self.led_states.store(new_value, Ordering::SeqCst); | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Get current LED state | ||
| 73 | #[inline(never)] | ||
| 74 | #[allow(dead_code)] | ||
| 75 | pub fn get_led(&self, is_green: bool) -> bool { | ||
| 76 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | ||
| 77 | |||
| 78 | let value = self.led_states.load(Ordering::SeqCst); | ||
| 79 | (value & (1 << bit)) != 0 | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Increment counter and return new value | ||
| 83 | #[inline(never)] | ||
| 84 | pub fn increment_counter(&self) -> u32 { | ||
| 85 | let current = self.counter.load(Ordering::SeqCst); | ||
| 86 | let new_value = current.wrapping_add(1); | ||
| 87 | self.counter.store(new_value, Ordering::SeqCst); | ||
| 88 | new_value | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Get current counter value | ||
| 92 | #[inline(never)] | ||
| 93 | #[allow(dead_code)] | ||
| 94 | pub fn get_counter(&self) -> u32 { | ||
| 95 | let value = self.counter.load(Ordering::SeqCst); | ||
| 96 | value | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | #[link_section = ".ram_d3"] | ||
| 101 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); | ||
| 102 | |||
| 103 | // Memory region constants for MPU configuration | ||
| 104 | pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; | ||
| 105 | pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) | ||
| 106 | pub const SRAM4_REGION_NUMBER: u8 = 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | #[link_section = ".ram_d3"] | ||
| 110 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 111 | |||
| 112 | /// Configure MPU to make SRAM4 region non-cacheable | ||
| 113 | fn configure_mpu_non_cacheable(mpu: &mut MPU) { | ||
| 114 | asm::dmb(); | ||
| 115 | unsafe { | ||
| 116 | // Disable MPU | ||
| 117 | mpu.ctrl.write(0); | ||
| 118 | |||
| 119 | // Configure SRAM4 as non-cacheable | ||
| 120 | mpu.rnr.write(SRAM4_REGION_NUMBER as u32); | ||
| 121 | |||
| 122 | // Set base address with region number | ||
| 123 | mpu.rbar.write(SRAM4_BASE_ADDRESS | (1 << 4)); | ||
| 124 | |||
| 125 | // Configure region attributes | ||
| 126 | let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB) | ||
| 127 | (1 << 0) | // ENABLE=1 | ||
| 128 | (3 << 24) | // AP=3 (Full access) | ||
| 129 | (1 << 19) | // TEX=1 | ||
| 130 | (1 << 18); // S=1 (Shareable) | ||
| 131 | |||
| 132 | mpu.rasr.write(rasr_value); | ||
| 133 | |||
| 134 | // Enable MPU with default memory map as background | ||
| 135 | mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA | ||
| 136 | } | ||
| 137 | |||
| 138 | asm::dsb(); | ||
| 139 | asm::isb(); | ||
| 140 | |||
| 141 | info!("MPU configured - SRAM4 set as non-cacheable"); | ||
| 142 | } | ||
| 143 | |||
| 144 | #[embassy_executor::main] | ||
| 145 | async fn main(_spawner: Spawner) -> ! { | ||
| 146 | // Set up MPU and cache configuration | ||
| 147 | { | ||
| 148 | let mut cp = cortex_m::Peripherals::take().unwrap(); | ||
| 149 | let scb = &mut cp.SCB; | ||
| 150 | |||
| 151 | // First disable caches | ||
| 152 | scb.disable_icache(); | ||
| 153 | scb.disable_dcache(&mut cp.CPUID); | ||
| 154 | |||
| 155 | // Configure MPU | ||
| 156 | configure_mpu_non_cacheable(&mut cp.MPU); | ||
| 157 | |||
| 158 | // Re-enable caches | ||
| 159 | scb.enable_icache(); | ||
| 160 | scb.enable_dcache(&mut cp.CPUID); | ||
| 161 | asm::dsb(); | ||
| 162 | asm::isb(); | ||
| 163 | } | ||
| 164 | |||
| 165 | // Configure the clock system | ||
| 166 | let mut config = Config::default(); | ||
| 167 | { | ||
| 168 | use embassy_stm32::rcc::*; | ||
| 169 | config.rcc.hsi = Some(HSIPrescaler::DIV1); | ||
| 170 | config.rcc.csi = true; | ||
| 171 | config.rcc.hsi48 = Some(Default::default()); | ||
| 172 | config.rcc.pll1 = Some(Pll { | ||
| 173 | source: PllSource::HSI, | ||
| 174 | prediv: PllPreDiv::DIV4, | ||
| 175 | mul: PllMul::MUL50, | ||
| 176 | divp: Some(PllDiv::DIV2), | ||
| 177 | divq: Some(PllDiv::DIV8), | ||
| 178 | divr: None, | ||
| 179 | }); | ||
| 180 | config.rcc.sys = Sysclk::PLL1_P; | ||
| 181 | config.rcc.ahb_pre = AHBPrescaler::DIV2; | ||
| 182 | config.rcc.apb1_pre = APBPrescaler::DIV2; | ||
| 183 | config.rcc.apb2_pre = APBPrescaler::DIV2; | ||
| 184 | config.rcc.apb3_pre = APBPrescaler::DIV2; | ||
| 185 | config.rcc.apb4_pre = APBPrescaler::DIV2; | ||
| 186 | config.rcc.voltage_scale = VoltageScale::Scale1; | ||
| 187 | config.rcc.supply_config = SupplyConfig::DirectSMPS; | ||
| 188 | } | ||
| 189 | |||
| 190 | // Initialize the CM7 core | ||
| 191 | let _p = embassy_stm32::init_primary(config, &SHARED_DATA); | ||
| 192 | info!("CM7 core initialized with non-cacheable SRAM4!"); | ||
| 193 | |||
| 194 | // Verify shared memory is accessible | ||
| 195 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); | ||
| 196 | info!("CM7: Magic value = 0x{:X}", magic); | ||
| 197 | |||
| 198 | // Initialize LED states | ||
| 199 | SHARED_LED_STATE.set_led(true, false); // Green LED off | ||
| 200 | SHARED_LED_STATE.set_led(false, false); // Yellow LED off | ||
| 201 | |||
| 202 | // Main loop - periodically toggle LED states | ||
| 203 | let mut green_state = false; | ||
| 204 | let mut yellow_state = false; | ||
| 205 | let mut loop_count = 0; | ||
| 206 | |||
| 207 | info!("CM7: Starting main loop"); | ||
| 208 | loop { | ||
| 209 | loop_count += 1; | ||
| 210 | let counter = SHARED_LED_STATE.increment_counter(); | ||
| 211 | |||
| 212 | // Toggle green LED every second | ||
| 213 | if loop_count % 10 == 0 { | ||
| 214 | green_state = !green_state; | ||
| 215 | SHARED_LED_STATE.set_led(true, green_state); | ||
| 216 | info!("CM7: Counter = {}, Set green LED to {}", counter, green_state); | ||
| 217 | } | ||
| 218 | |||
| 219 | // Toggle yellow LED every 3 seconds | ||
| 220 | if loop_count % 30 == 0 { | ||
| 221 | yellow_state = !yellow_state; | ||
| 222 | SHARED_LED_STATE.set_led(false, yellow_state); | ||
| 223 | info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state); | ||
| 224 | } | ||
| 225 | |||
| 226 | Timer::after_millis(100).await; | ||
| 227 | } | ||
| 228 | } | ||
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index e5f2dfe86..1917749c5 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml | |||
| @@ -3,19 +3,20 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h7b0-examples" | 3 | name = "embassy-stm32h7b0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 11 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "1.0.1" |
| 18 | defmt-rtt = "0.4" | 19 | defmt-rtt = "1.0.0" |
| 19 | 20 | ||
| 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| @@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 24 | embedded-hal-async = { version = "1.0" } | 25 | embedded-hal-async = { version = "1.0" } |
| 25 | embedded-nal-async = "0.8.0" | 26 | embedded-nal-async = "0.8.0" |
| 26 | embedded-io-async = { version = "0.6.1" } | 27 | embedded-io-async = { version = "0.6.1" } |
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 28 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 29 | rand_core = "0.6.3" | ||
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.3.0" |
| @@ -72,3 +72,8 @@ incremental = false | |||
| 72 | lto = 'fat' | 72 | lto = 'fat' |
| 73 | opt-level = 3 # <- | 73 | opt-level = 3 # <- |
| 74 | overflow-checks = false # <- | 74 | overflow-checks = false # <- |
| 75 | |||
| 76 | [package.metadata.embassy] | ||
| 77 | build = [ | ||
| 78 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7b0" } | ||
| 79 | ] | ||
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 22d59be04..bfe59b68d 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml | |||
| @@ -3,19 +3,20 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32h7rs-examples" | 3 | name = "embassy-stm32h7rs-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32h743bi to your chip name, if necessary. | 9 | # Change stm32h743bi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "1.0.1" |
| 18 | defmt-rtt = "0.4" | 19 | defmt-rtt = "1.0.0" |
| 19 | 20 | ||
| 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| @@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | |||
| 24 | embedded-hal-async = { version = "1.0" } | 25 | embedded-hal-async = { version = "1.0" } |
| 25 | embedded-nal-async = "0.8.0" | 26 | embedded-nal-async = "0.8.0" |
| 26 | embedded-io-async = { version = "0.6.1" } | 27 | embedded-io-async = { version = "0.6.1" } |
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 28 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 29 | rand_core = "0.6.3" | ||
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.3.0" |
| @@ -71,3 +71,8 @@ incremental = false | |||
| 71 | lto = 'fat' | 71 | lto = 'fat' |
| 72 | opt-level = 3 # <- | 72 | opt-level = 3 # <- |
| 73 | overflow-checks = false # <- | 73 | overflow-checks = false # <- |
| 74 | |||
| 75 | [package.metadata.embassy] | ||
| 76 | build = [ | ||
| 77 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7rs" } | ||
| 78 | ] | ||
diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs index 137c585b7..5fd50fb15 100644 --- a/examples/stm32h7rs/src/bin/blinky.rs +++ b/examples/stm32h7rs/src/bin/blinky.rs | |||
| @@ -25,6 +25,8 @@ async fn main(_spawner: Spawner) { | |||
| 25 | divp: Some(PllDiv::DIV2), | 25 | divp: Some(PllDiv::DIV2), |
| 26 | divq: None, | 26 | divq: None, |
| 27 | divr: None, | 27 | divr: None, |
| 28 | divs: None, | ||
| 29 | divt: None, | ||
| 28 | }); | 30 | }); |
| 29 | config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz | 31 | config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz |
| 30 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz | 32 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz |
diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index f2bd9575e..67f541564 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs | |||
| @@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng; | |||
| 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use heapless::Vec; | 13 | use heapless::Vec; |
| 14 | use rand_core::RngCore; | ||
| 15 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 16 | ||
| @@ -42,6 +41,8 @@ async fn main(spawner: Spawner) -> ! { | |||
| 42 | divp: Some(PllDiv::DIV2), | 41 | divp: Some(PllDiv::DIV2), |
| 43 | divq: None, | 42 | divq: None, |
| 44 | divr: None, | 43 | divr: None, |
| 44 | divs: None, | ||
| 45 | divt: None, | ||
| 45 | }); | 46 | }); |
| 46 | config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz | 47 | config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz |
| 47 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz | 48 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz |
| @@ -93,7 +94,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 93 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 94 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 94 | 95 | ||
| 95 | // Launch network task | 96 | // Launch network task |
| 96 | unwrap!(spawner.spawn(net_task(runner))); | 97 | spawner.spawn(unwrap!(net_task(runner))); |
| 97 | 98 | ||
| 98 | // Ensure DHCP configuration is up before trying connect | 99 | // Ensure DHCP configuration is up before trying connect |
| 99 | //stack.wait_config_up().await; | 100 | //stack.wait_config_up().await; |
diff --git a/examples/stm32h7rs/src/bin/i2c.rs b/examples/stm32h7rs/src/bin/i2c.rs index 31e83cbb5..870c57e0f 100644 --- a/examples/stm32h7rs/src/bin/i2c.rs +++ b/examples/stm32h7rs/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::{Error, I2c}; | 6 | use embassy_stm32::i2c::{Error, I2c}; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 7 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 9 | ||
| @@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) { | |||
| 28 | Irqs, | 27 | Irqs, |
| 29 | p.GPDMA1_CH4, | 28 | p.GPDMA1_CH4, |
| 30 | p.GPDMA1_CH5, | 29 | p.GPDMA1_CH5, |
| 31 | Hertz(100_000), | ||
| 32 | Default::default(), | 30 | Default::default(), |
| 33 | ); | 31 | ); |
| 34 | 32 | ||
diff --git a/examples/stm32h7rs/src/bin/multiprio.rs b/examples/stm32h7rs/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32h7rs/src/bin/multiprio.rs +++ b/examples/stm32h7rs/src/bin/multiprio.rs | |||
| @@ -135,16 +135,16 @@ fn main() -> ! { | |||
| 135 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 136 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
| 138 | unwrap!(spawner.spawn(run_high())); | 138 | spawner.spawn(unwrap!(run_high())); |
| 139 | 139 | ||
| 140 | // Medium-priority executor: UART5, priority level 7 | 140 | // Medium-priority executor: UART5, priority level 7 |
| 141 | interrupt::UART5.set_priority(Priority::P7); | 141 | interrupt::UART5.set_priority(Priority::P7); |
| 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); | 142 | let spawner = EXECUTOR_MED.start(interrupt::UART5); |
| 143 | unwrap!(spawner.spawn(run_med())); | 143 | spawner.spawn(unwrap!(run_med())); |
| 144 | 144 | ||
| 145 | // Low priority executor: runs in thread mode, using WFE/SEV | 145 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 146 | let executor = EXECUTOR_LOW.init(Executor::new()); | 146 | let executor = EXECUTOR_LOW.init(Executor::new()); |
| 147 | executor.run(|spawner| { | 147 | executor.run(|spawner| { |
| 148 | unwrap!(spawner.spawn(run_low())); | 148 | spawner.spawn(unwrap!(run_low())); |
| 149 | }); | 149 | }); |
| 150 | } | 150 | } |
diff --git a/examples/stm32h7rs/src/bin/signal.rs b/examples/stm32h7rs/src/bin/signal.rs index b73360f32..97309798e 100644 --- a/examples/stm32h7rs/src/bin/signal.rs +++ b/examples/stm32h7rs/src/bin/signal.rs | |||
| @@ -26,7 +26,7 @@ async fn my_sending_task() { | |||
| 26 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 27 | async fn main(spawner: Spawner) { | 27 | async fn main(spawner: Spawner) { |
| 28 | let _p = embassy_stm32::init(Default::default()); | 28 | let _p = embassy_stm32::init(Default::default()); |
| 29 | unwrap!(spawner.spawn(my_sending_task())); | 29 | spawner.spawn(unwrap!(my_sending_task())); |
| 30 | 30 | ||
| 31 | loop { | 31 | loop { |
| 32 | let received_counter = SIGNAL.wait().await; | 32 | let received_counter = SIGNAL.wait().await; |
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs index 8d6ccc58b..8c280fdae 100644 --- a/examples/stm32h7rs/src/bin/spi.rs +++ b/examples/stm32h7rs/src/bin/spi.rs | |||
| @@ -44,6 +44,6 @@ fn main() -> ! { | |||
| 44 | let executor = EXECUTOR.init(Executor::new()); | 44 | let executor = EXECUTOR.init(Executor::new()); |
| 45 | 45 | ||
| 46 | executor.run(|spawner| { | 46 | executor.run(|spawner| { |
| 47 | unwrap!(spawner.spawn(main_task(spi))); | 47 | spawner.spawn(unwrap!(main_task(spi))); |
| 48 | }) | 48 | }) |
| 49 | } | 49 | } |
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs index cb305351b..3fa69fd15 100644 --- a/examples/stm32h7rs/src/bin/spi_dma.rs +++ b/examples/stm32h7rs/src/bin/spi_dma.rs | |||
| @@ -41,6 +41,6 @@ fn main() -> ! { | |||
| 41 | let executor = EXECUTOR.init(Executor::new()); | 41 | let executor = EXECUTOR.init(Executor::new()); |
| 42 | 42 | ||
| 43 | executor.run(|spawner| { | 43 | executor.run(|spawner| { |
| 44 | unwrap!(spawner.spawn(main_task(spi))); | 44 | spawner.spawn(unwrap!(main_task(spi))); |
| 45 | }) | 45 | }) |
| 46 | } | 46 | } |
diff --git a/examples/stm32h7rs/src/bin/usart.rs b/examples/stm32h7rs/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h7rs/src/bin/usart.rs +++ b/examples/stm32h7rs/src/bin/usart.rs | |||
| @@ -34,6 +34,6 @@ fn main() -> ! { | |||
| 34 | let executor = EXECUTOR.init(Executor::new()); | 34 | let executor = EXECUTOR.init(Executor::new()); |
| 35 | 35 | ||
| 36 | executor.run(|spawner| { | 36 | executor.run(|spawner| { |
| 37 | unwrap!(spawner.spawn(main_task())); | 37 | spawner.spawn(unwrap!(main_task())); |
| 38 | }) | 38 | }) |
| 39 | } | 39 | } |
diff --git a/examples/stm32h7rs/src/bin/usart_dma.rs b/examples/stm32h7rs/src/bin/usart_dma.rs index c644e84bd..ea48515d7 100644 --- a/examples/stm32h7rs/src/bin/usart_dma.rs +++ b/examples/stm32h7rs/src/bin/usart_dma.rs | |||
| @@ -42,6 +42,6 @@ fn main() -> ! { | |||
| 42 | let executor = EXECUTOR.init(Executor::new()); | 42 | let executor = EXECUTOR.init(Executor::new()); |
| 43 | 43 | ||
| 44 | executor.run(|spawner| { | 44 | executor.run(|spawner| { |
| 45 | unwrap!(spawner.spawn(main_task())); | 45 | spawner.spawn(unwrap!(main_task())); |
| 46 | }) | 46 | }) |
| 47 | } | 47 | } |
diff --git a/examples/stm32h7rs/src/bin/usart_split.rs b/examples/stm32h7rs/src/bin/usart_split.rs index d26c5003c..f56c1c57d 100644 --- a/examples/stm32h7rs/src/bin/usart_split.rs +++ b/examples/stm32h7rs/src/bin/usart_split.rs | |||
| @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 27 | 27 | ||
| 28 | let (mut tx, rx) = usart.split(); | 28 | let (mut tx, rx) = usart.split(); |
| 29 | 29 | ||
| 30 | unwrap!(spawner.spawn(reader(rx))); | 30 | spawner.spawn(unwrap!(reader(rx))); |
| 31 | 31 | ||
| 32 | loop { | 32 | loop { |
| 33 | let buf = CHANNEL.receive().await; | 33 | let buf = CHANNEL.receive().await; |
diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs index 56a9884af..23abc3e2f 100644 --- a/examples/stm32h7rs/src/bin/usb_serial.rs +++ b/examples/stm32h7rs/src/bin/usb_serial.rs | |||
| @@ -40,6 +40,8 @@ async fn main(_spawner: Spawner) { | |||
| 40 | divp: Some(PllDiv::DIV1), //600 MHz | 40 | divp: Some(PllDiv::DIV1), //600 MHz |
| 41 | divq: Some(PllDiv::DIV2), // 300 MHz | 41 | divq: Some(PllDiv::DIV2), // 300 MHz |
| 42 | divr: Some(PllDiv::DIV2), // 300 MHz | 42 | divr: Some(PllDiv::DIV2), // 300 MHz |
| 43 | divs: None, | ||
| 44 | divt: None, | ||
| 43 | }); | 45 | }); |
| 44 | config.rcc.sys = Sysclk::PLL1_P; // 600 MHz | 46 | config.rcc.sys = Sysclk::PLL1_P; // 600 MHz |
| 45 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz | 47 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz |
diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs index 88d914180..4c1b450b4 100644 --- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs +++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | //! For Nucleo STM32H7S3L8 MB1737, has MX25UW25645GXDI00 | 4 | //! For Nucleo STM32H7S3L8 MB1737, has MX25UW25645GXDI00 |
| 5 | //! | 5 | //! |
| 6 | //! TODO: Currently this only uses single SPI, pending flash chip documentation for octo SPI. | 6 | |
| 7 | use core::cmp::min; | ||
| 7 | 8 | ||
| 8 | use defmt::info; | 9 | use defmt::info; |
| 9 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| @@ -35,6 +36,8 @@ async fn main(_spawner: Spawner) { | |||
| 35 | divp: Some(PllDiv::DIV2), | 36 | divp: Some(PllDiv::DIV2), |
| 36 | divq: None, | 37 | divq: None, |
| 37 | divr: None, | 38 | divr: None, |
| 39 | divs: None, | ||
| 40 | divt: None, | ||
| 38 | }); | 41 | }); |
| 39 | config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz | 42 | config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz |
| 40 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz | 43 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz |
| @@ -52,14 +55,16 @@ async fn main(_spawner: Spawner) { | |||
| 52 | fifo_threshold: FIFOThresholdLevel::_4Bytes, | 55 | fifo_threshold: FIFOThresholdLevel::_4Bytes, |
| 53 | memory_type: MemoryType::Macronix, | 56 | memory_type: MemoryType::Macronix, |
| 54 | delay_hold_quarter_cycle: true, | 57 | delay_hold_quarter_cycle: true, |
| 55 | // memory_type: MemoryType::Micron, | ||
| 56 | // delay_hold_quarter_cycle: false, | ||
| 57 | device_size: MemorySize::_32MiB, | 58 | device_size: MemorySize::_32MiB, |
| 58 | chip_select_high_time: ChipSelectHighTime::_2Cycle, | 59 | chip_select_high_time: ChipSelectHighTime::_2Cycle, |
| 59 | free_running_clock: false, | 60 | free_running_clock: false, |
| 60 | clock_mode: false, | 61 | clock_mode: false, |
| 61 | wrap_size: WrapSize::None, | 62 | wrap_size: WrapSize::None, |
| 62 | // 300mhz / (4+1) = 60mhz. Unsure the limit, need to find a MX25UW25645GXDI00 datasheet. | 63 | // 300 MHz clock / (3 + 1) = 75 MHz. This is above the max for READ instructions so the |
| 64 | // FAST READ must be used. The nucleo board's flash can run at up to 133 MHz in SPI mode | ||
| 65 | // and 200 MHz in OPI mode. This clock prescaler must be even otherwise the clock will not | ||
| 66 | // have symmetric high and low times. | ||
| 67 | // The clock can also be fed by one of the PLLs to allow for more flexible clock rates. | ||
| 63 | clock_prescaler: 3, | 68 | clock_prescaler: 3, |
| 64 | sample_shifting: false, | 69 | sample_shifting: false, |
| 65 | chip_select_boundary: 0, | 70 | chip_select_boundary: 0, |
| @@ -71,28 +76,41 @@ async fn main(_spawner: Spawner) { | |||
| 71 | 76 | ||
| 72 | // Not necessary, but recommended if using XIP | 77 | // Not necessary, but recommended if using XIP |
| 73 | cor.SCB.enable_icache(); | 78 | cor.SCB.enable_icache(); |
| 79 | // Note: Enabling data cache can cause issues with DMA transfers. | ||
| 74 | cor.SCB.enable_dcache(&mut cor.CPUID); | 80 | cor.SCB.enable_dcache(&mut cor.CPUID); |
| 75 | 81 | ||
| 76 | let xspi = embassy_stm32::xspi::Xspi::new_blocking_xspi( | 82 | let xspi = embassy_stm32::xspi::Xspi::new_blocking_xspi( |
| 77 | p.XSPI2, p.PN6, p.PN2, p.PN3, p.PN4, p.PN5, p.PN8, p.PN9, p.PN10, p.PN11, p.PN1, spi_config, | 83 | p.XSPI2, p.PN6, p.PN2, p.PN3, p.PN4, p.PN5, p.PN8, p.PN9, p.PN10, p.PN11, p.PN1, spi_config, |
| 78 | ); | 84 | ); |
| 79 | 85 | ||
| 80 | let mut flash = FlashMemory::new(xspi).await; | 86 | let mut flash = SpiFlashMemory::new(xspi); |
| 81 | 87 | ||
| 82 | let flash_id = flash.read_id(); | 88 | let flash_id = flash.read_id(); |
| 83 | info!("FLASH ID: {=[u8]:x}", flash_id); | 89 | info!("FLASH ID: {=[u8]:x}", flash_id); |
| 84 | 90 | ||
| 85 | let mut wr_buf = [0u8; 8]; | 91 | // Erase the first sector |
| 86 | for i in 0..8 { | 92 | flash.erase_sector(0); |
| 87 | wr_buf[i] = 0x90 + i as u8; | 93 | |
| 88 | } | 94 | // Write some data into the flash. This writes more than one page to test that functionality. |
| 89 | let mut rd_buf = [0u8; 8]; | 95 | let mut wr_buf = [0u8; 512]; |
| 90 | flash.erase_sector(0).await; | 96 | let base_number: u8 = 0x90; |
| 91 | flash.write_memory(0, &wr_buf, true).await; | 97 | for i in 0..512 { |
| 92 | flash.read_memory(0, &mut rd_buf, true); | 98 | wr_buf[i] = base_number.wrapping_add(i as u8); |
| 93 | info!("WRITE BUF: {=[u8]:#X}", wr_buf); | 99 | } |
| 94 | info!("READ BUF: {=[u8]:#X}", rd_buf); | 100 | flash.write_memory(0, &wr_buf); |
| 95 | flash.enable_mm().await; | 101 | |
| 102 | // Read the data back and verify it. | ||
| 103 | let mut rd_buf = [0u8; 512]; | ||
| 104 | let start_time = embassy_time::Instant::now(); | ||
| 105 | flash.read_memory(0, &mut rd_buf); | ||
| 106 | let elapsed = start_time.elapsed(); | ||
| 107 | info!("Read 512 bytes in {} us in SPI mode", elapsed.as_micros()); | ||
| 108 | info!("WRITE BUF: {=[u8]:#X}", wr_buf[0..32]); | ||
| 109 | info!("READ BUF: {=[u8]:#X}", rd_buf[0..32]); | ||
| 110 | |||
| 111 | assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer"); | ||
| 112 | |||
| 113 | flash.enable_mm(); | ||
| 96 | info!("Enabled memory mapped mode"); | 114 | info!("Enabled memory mapped mode"); |
| 97 | 115 | ||
| 98 | let first_u32 = unsafe { *(0x70000000 as *const u32) }; | 116 | let first_u32 = unsafe { *(0x70000000 as *const u32) }; |
| @@ -103,10 +121,53 @@ async fn main(_spawner: Spawner) { | |||
| 103 | assert_eq!(second_u32, 0x97969594); | 121 | assert_eq!(second_u32, 0x97969594); |
| 104 | info!("second_u32 {:08x}", first_u32); | 122 | info!("second_u32 {:08x}", first_u32); |
| 105 | 123 | ||
| 106 | flash.disable_mm().await; | 124 | flash.disable_mm(); |
| 107 | info!("Disabled memory mapped mode"); | 125 | info!("Disabled memory mapped mode"); |
| 108 | 126 | ||
| 127 | let flash_id = flash.read_id(); | ||
| 128 | info!("FLASH ID: {=[u8]:x}", flash_id); | ||
| 129 | |||
| 130 | let mut flash = flash.into_octo(); | ||
| 131 | |||
| 132 | Timer::after_millis(100).await; | ||
| 133 | |||
| 134 | let flash_id = flash.read_id(); | ||
| 135 | info!("FLASH ID in OPI mode: {=[u8]:x}", flash_id); | ||
| 136 | |||
| 137 | flash.erase_sector(0); | ||
| 138 | |||
| 139 | let mut rd_buf = [0u8; 512]; | ||
| 140 | flash.read_memory(0, &mut rd_buf); | ||
| 141 | info!("READ BUF after erase: {=[u8]:#X}", rd_buf[0..32]); | ||
| 142 | |||
| 143 | assert_eq!(rd_buf, [0xFF; 512], "Read buffer is not all 0xFF after erase"); | ||
| 144 | |||
| 145 | flash.write_memory(0, &wr_buf); | ||
| 146 | let start = embassy_time::Instant::now(); | ||
| 147 | flash.read_memory(0, &mut rd_buf); | ||
| 148 | let elapsed = start.elapsed(); | ||
| 149 | info!("Read 512 bytes in {} us in OPI mode", elapsed.as_micros()); | ||
| 150 | info!("READ BUF after write: {=[u8]:#X}", rd_buf[0..32]); | ||
| 151 | assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer in OPI mode"); | ||
| 152 | |||
| 153 | flash.enable_mm(); | ||
| 154 | info!("Enabled memory mapped mode in OPI mode"); | ||
| 155 | let first_u32 = unsafe { *(0x70000000 as *const u32) }; | ||
| 156 | assert_eq!(first_u32, 0x93929190); | ||
| 157 | info!("first_u32 {:08x}", first_u32); | ||
| 158 | let second_u32 = unsafe { *(0x70000004 as *const u32) }; | ||
| 159 | assert_eq!(second_u32, 0x97969594); | ||
| 160 | info!("second_u32 {:08x}", first_u32); | ||
| 161 | flash.disable_mm(); | ||
| 162 | info!("Disabled memory mapped mode in OPI mode"); | ||
| 163 | |||
| 164 | // Reset back to SPI mode | ||
| 165 | let mut flash = flash.into_spi(); | ||
| 166 | let flash_id = flash.read_id(); | ||
| 167 | info!("FLASH ID back in SPI mode: {=[u8]:x}", flash_id); | ||
| 168 | |||
| 109 | info!("DONE"); | 169 | info!("DONE"); |
| 170 | |||
| 110 | // Output pin PE3 | 171 | // Output pin PE3 |
| 111 | let mut led = Output::new(p.PE3, Level::Low, Speed::Low); | 172 | let mut led = Output::new(p.PE3, Level::Low, Speed::Low); |
| 112 | 173 | ||
| @@ -116,80 +177,268 @@ async fn main(_spawner: Spawner) { | |||
| 116 | } | 177 | } |
| 117 | } | 178 | } |
| 118 | 179 | ||
| 119 | const MEMORY_PAGE_SIZE: usize = 8; | 180 | const MEMORY_PAGE_SIZE: usize = 256; |
| 120 | |||
| 121 | const CMD_READ: u8 = 0x0B; | ||
| 122 | const _CMD_QUAD_READ: u8 = 0x6B; | ||
| 123 | |||
| 124 | const CMD_WRITE_PG: u8 = 0x02; | ||
| 125 | const _CMD_QUAD_WRITE_PG: u8 = 0x32; | ||
| 126 | |||
| 127 | const CMD_READ_ID: u8 = 0x9F; | ||
| 128 | const CMD_READ_ID_OCTO: u16 = 0x9F60; | ||
| 129 | 181 | ||
| 130 | const CMD_ENABLE_RESET: u8 = 0x66; | 182 | /// Implementation of access to flash chip using SPI. |
| 131 | const CMD_RESET: u8 = 0x99; | 183 | /// |
| 132 | 184 | /// Chip commands are hardcoded as it depends on used chip. | |
| 133 | const CMD_WRITE_ENABLE: u8 = 0x06; | 185 | /// This targets a MX25UW25645GXDI00. |
| 134 | 186 | pub struct SpiFlashMemory<I: Instance> { | |
| 135 | const CMD_CHIP_ERASE: u8 = 0xC7; | 187 | xspi: Xspi<'static, I, Blocking>, |
| 136 | const CMD_SECTOR_ERASE: u8 = 0x20; | 188 | } |
| 137 | const CMD_BLOCK_ERASE_32K: u8 = 0x52; | ||
| 138 | const CMD_BLOCK_ERASE_64K: u8 = 0xD8; | ||
| 139 | |||
| 140 | const CMD_READ_SR: u8 = 0x05; | ||
| 141 | const CMD_READ_CR: u8 = 0x35; | ||
| 142 | |||
| 143 | const CMD_WRITE_SR: u8 = 0x01; | ||
| 144 | const CMD_WRITE_CR: u8 = 0x31; | ||
| 145 | 189 | ||
| 146 | /// Implementation of access to flash chip. | 190 | /// Implementation of access to flash chip using Octo SPI. |
| 147 | /// | 191 | /// |
| 148 | /// Chip commands are hardcoded as it depends on used chip. | 192 | /// Chip commands are hardcoded as it depends on used chip. |
| 149 | /// This targets a MX25UW25645GXDI00. | 193 | /// This targets a MX25UW25645GXDI00. |
| 150 | pub struct FlashMemory<I: Instance> { | 194 | pub struct OpiFlashMemory<I: Instance> { |
| 151 | xspi: Xspi<'static, I, Blocking>, | 195 | xspi: Xspi<'static, I, Blocking>, |
| 152 | } | 196 | } |
| 153 | 197 | ||
| 154 | impl<I: Instance> FlashMemory<I> { | 198 | /// SPI mode commands for MX25UW25645G flash memory |
| 155 | pub async fn new(xspi: Xspi<'static, I, Blocking>) -> Self { | 199 | #[allow(dead_code)] |
| 156 | let mut memory = Self { xspi }; | 200 | #[repr(u8)] |
| 201 | enum SpiCommand { | ||
| 202 | // Array access commands | ||
| 203 | /// Read data bytes using 3-byte address (up to 50 MHz) | ||
| 204 | Read3B = 0x03, | ||
| 205 | /// Fast read data bytes using 3-byte address with 8 dummy cycles (up to 133 MHz) | ||
| 206 | FastRead3B = 0x0B, | ||
| 207 | /// Program 1-256 bytes of data using 3-byte address | ||
| 208 | PageProgram3B = 0x02, | ||
| 209 | /// Erase 4KB sector using 3-byte address | ||
| 210 | SectorErase3B = 0x20, | ||
| 211 | /// Erase 64KB block using 3-byte address | ||
| 212 | BlockErase3B = 0xD8, | ||
| 213 | /// Read data bytes using 4-byte address (up to 50 MHz) | ||
| 214 | Read4B = 0x13, | ||
| 215 | /// Fast read data bytes using 4-byte address with 8 dummy cycles (up to 133 MHz) | ||
| 216 | FastRead4B = 0x0C, | ||
| 217 | /// Program 1-256 bytes of data using 4-byte address | ||
| 218 | PageProgram4B = 0x12, | ||
| 219 | /// Erase 4KB sector using 4-byte address | ||
| 220 | SectorErase4B = 0x21, | ||
| 221 | /// Erase 64KB block using 4-byte address | ||
| 222 | BlockErase4B = 0xDC, | ||
| 223 | /// Erase entire chip (only if no blocks are protected) | ||
| 224 | ChipErase = 0x60, | ||
| 225 | |||
| 226 | // Write Buffer Access commands | ||
| 227 | /// Read data from the 256-byte page buffer | ||
| 228 | ReadBuffer = 0x25, | ||
| 229 | /// Initialize write-to-buffer sequence, clears buffer and writes initial data | ||
| 230 | WriteBufferInitial = 0x22, | ||
| 231 | /// Continue writing data to buffer (used between WRBI and WRCF) | ||
| 232 | WriteBufferContinue = 0x24, | ||
| 233 | /// Confirm write operation, programs buffer contents to flash array | ||
| 234 | WriteBufferConfirm = 0x31, | ||
| 235 | |||
| 236 | // Device operation commands | ||
| 237 | /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations | ||
| 238 | WriteEnable = 0x06, | ||
| 239 | /// Clear Write Enable Latch (WEL) bit | ||
| 240 | WriteDisable = 0x04, | ||
| 241 | /// Select write protection mode (BP mode or Advanced Sector Protection) | ||
| 242 | WriteProtectSelection = 0x68, | ||
| 243 | /// Suspend ongoing program or erase operation to allow read access | ||
| 244 | ProgramEraseSuspend = 0xB0, | ||
| 245 | /// Resume suspended program or erase operation | ||
| 246 | ProgramEraseResume = 0x30, | ||
| 247 | /// Enter deep power-down mode for minimum power consumption | ||
| 248 | DeepPowerDown = 0xB9, | ||
| 249 | /// Exit deep power-down mode and return to standby | ||
| 250 | ReleaseFromDeepPowerDown = 0xAB, | ||
| 251 | /// No operation, can terminate Reset Enable command | ||
| 252 | NoOperation = 0x00, | ||
| 253 | /// Enable reset operation (must precede Reset Memory command) | ||
| 254 | ResetEnable = 0x66, | ||
| 255 | /// Reset device to power-on state (requires prior Reset Enable) | ||
| 256 | ResetMemory = 0x99, | ||
| 257 | /// Protect all sectors using Dynamic Protection Bits (DPB) | ||
| 258 | GangBlockLock = 0x7E, | ||
| 259 | /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB) | ||
| 260 | GangBlockUnlock = 0x98, | ||
| 261 | |||
| 262 | // Register Access commands | ||
| 263 | /// Read 3-byte device identification (manufacturer ID + device ID) | ||
| 264 | ReadIdentification = 0x9F, | ||
| 265 | /// Read Serial Flash Discoverable Parameters (SFDP) table | ||
| 266 | ReadSFDP = 0x5A, | ||
| 267 | /// Read 8-bit Status Register (WIP, WEL, BP bits, etc.) | ||
| 268 | ReadStatusRegister = 0x05, | ||
| 269 | /// Read 8-bit Configuration Register (ODS, TB, PBE bits) | ||
| 270 | ReadConfigurationRegister = 0x15, | ||
| 271 | /// Write Status and/or Configuration Register (1-2 bytes) | ||
| 272 | WriteStatusConfigurationRegister = 0x01, | ||
| 273 | /// Read Configuration Register 2 from specified 4-byte address | ||
| 274 | ReadConfigurationRegister2 = 0x71, | ||
| 275 | /// Write Configuration Register 2 to specified 4-byte address | ||
| 276 | WriteConfigurationRegister2 = 0x72, | ||
| 277 | /// Read 8-bit Security Register (protection status, suspend bits) | ||
| 278 | ReadSecurityRegister = 0x2B, | ||
| 279 | /// Write Security Register to set customer lock-down bit | ||
| 280 | WriteSecurityRegister = 0x2F, | ||
| 281 | /// Read 32-bit Fast Boot Register (boot address and configuration) | ||
| 282 | ReadFastBootRegister = 0x16, | ||
| 283 | /// Write 32-bit Fast Boot Register | ||
| 284 | WriteFastBootRegister = 0x17, | ||
| 285 | /// Erase Fast Boot Register (disable fast boot feature) | ||
| 286 | EraseFastBootRegister = 0x18, | ||
| 287 | /// Set burst/wrap length for read operations (16/32/64 bytes) | ||
| 288 | SetBurstLength = 0xC0, | ||
| 289 | /// Enter 8K-bit secured OTP mode for programming unique identifiers | ||
| 290 | EnterSecuredOTP = 0xB1, | ||
| 291 | /// Exit secured OTP mode and return to main array access | ||
| 292 | ExitSecuredOTP = 0xC1, | ||
| 293 | /// Write Lock Register to control SPB protection mode | ||
| 294 | WriteLockRegister = 0x2C, | ||
| 295 | /// Read Lock Register status | ||
| 296 | ReadLockRegister = 0x2D, | ||
| 297 | /// Program Solid Protection Bit (SPB) for specified sector/block | ||
| 298 | WriteSPB = 0xE3, | ||
| 299 | /// Erase all Solid Protection Bits (SPB) | ||
| 300 | EraseSPB = 0xE4, | ||
| 301 | /// Read Solid Protection Bit (SPB) status for specified sector/block | ||
| 302 | ReadSPB = 0xE2, | ||
| 303 | /// Write Dynamic Protection Bit (DPB) for specified sector | ||
| 304 | WriteDPB = 0xE1, | ||
| 305 | /// Read Dynamic Protection Bit (DPB) status for specified sector | ||
| 306 | ReadDPB = 0xE0, | ||
| 307 | /// Read 64-bit password register (only in Solid Protection mode) | ||
| 308 | ReadPassword = 0x27, | ||
| 309 | /// Write 64-bit password register | ||
| 310 | WritePassword = 0x28, | ||
| 311 | /// Unlock SPB operations using 64-bit password | ||
| 312 | PasswordUnlock = 0x29, | ||
| 313 | } | ||
| 157 | 314 | ||
| 158 | memory.reset_memory().await; | 315 | /// OPI mode commands for MX25UW25645G flash memory |
| 159 | memory.enable_octo(); | 316 | #[allow(dead_code)] |
| 160 | memory | 317 | #[repr(u16)] |
| 161 | } | 318 | enum OpiCommand { |
| 319 | // Array access commands | ||
| 320 | /// Read data using 8 I/O lines in STR mode with configurable dummy cycles (up to 200 MHz) | ||
| 321 | OctaRead = 0xEC13, | ||
| 322 | /// Read data using 8 I/O lines in DTR mode with configurable dummy cycles (up to 200 MHz) | ||
| 323 | OctaDTRRead = 0xEE11, | ||
| 324 | /// Program 1-256 bytes using 4-byte address and 8 I/O lines | ||
| 325 | PageProgram4B = 0x12ED, | ||
| 326 | /// Erase 4KB sector using 4-byte address | ||
| 327 | SectorErase4B = 0x21DE, | ||
| 328 | /// Erase 64KB block using 4-byte address | ||
| 329 | BlockErase4B = 0xDC23, | ||
| 330 | /// Erase entire chip (only if no blocks are protected) | ||
| 331 | ChipErase = 0x609F, | ||
| 332 | |||
| 333 | // Write Buffer Access commands | ||
| 334 | /// Read data from the 256-byte page buffer using 4-byte address | ||
| 335 | ReadBuffer = 0x25DA, | ||
| 336 | /// Initialize interruptible write-to-buffer sequence with 4-byte address | ||
| 337 | WriteBufferInitial = 0x22DD, | ||
| 338 | /// Continue writing data to buffer during interruptible sequence | ||
| 339 | WriteBufferContinue = 0x24DB, | ||
| 340 | /// Confirm and execute write operation from buffer to flash array | ||
| 341 | WriteBufferConfirm = 0x31CE, | ||
| 342 | |||
| 343 | // Device operation commands | ||
| 344 | /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations | ||
| 345 | WriteEnable = 0x06F9, | ||
| 346 | /// Clear Write Enable Latch (WEL) bit, aborts write-to-buffer sequence | ||
| 347 | WriteDisable = 0x04FB, | ||
| 348 | /// Select write protection mode (BP mode or Advanced Sector Protection) - OTP bit | ||
| 349 | WriteProtectSelection = 0x6897, | ||
| 350 | /// Suspend ongoing program or erase operation to allow read from other banks | ||
| 351 | ProgramEraseSuspend = 0xB04F, | ||
| 352 | /// Resume suspended program or erase operation | ||
| 353 | ProgramEraseResume = 0x30CF, | ||
| 354 | /// Enter deep power-down mode for minimum power consumption | ||
| 355 | DeepPowerDown = 0xB946, | ||
| 356 | /// Exit deep power-down mode and return to standby | ||
| 357 | ReleaseFromDeepPowerDown = 0xAB54, | ||
| 358 | /// No operation, can terminate Reset Enable command | ||
| 359 | NoOperation = 0x00FF, | ||
| 360 | /// Enable reset operation (must precede Reset Memory command) | ||
| 361 | ResetEnable = 0x6699, | ||
| 362 | /// Reset device to power-on state, clears volatile settings | ||
| 363 | ResetMemory = 0x9966, | ||
| 364 | /// Protect all sectors using Dynamic Protection Bits (DPB) | ||
| 365 | GangBlockLock = 0x7E81, | ||
| 366 | /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB) | ||
| 367 | GangBlockUnlock = 0x9867, | ||
| 368 | |||
| 369 | // Register Access commands | ||
| 370 | /// Read 3-byte device identification with 4-byte dummy address | ||
| 371 | ReadIdentification = 0x9F60, | ||
| 372 | /// Read Serial Flash Discoverable Parameters (SFDP) table with 4-byte address | ||
| 373 | ReadSFDP = 0x5AA5, | ||
| 374 | /// Read 8-bit Status Register with 4-byte dummy address | ||
| 375 | ReadStatusRegister = 0x05FA, | ||
| 376 | /// Read 8-bit Configuration Register with specific address (00000001h) | ||
| 377 | ReadConfigurationRegister = 0x15EA, | ||
| 378 | /// Write 8-bit Status Register with specific address (00000000h) or Configuration Register with address (00000001h) | ||
| 379 | WriteStatusConfigurationRegister = 0x01FE, | ||
| 380 | /// Read Configuration Register 2 from specified 4-byte address | ||
| 381 | ReadConfigurationRegister2 = 0x718E, | ||
| 382 | /// Write Configuration Register 2 to specified 4-byte address | ||
| 383 | WriteConfigurationRegister2 = 0x728D, | ||
| 384 | /// Read 8-bit Security Register with 4-byte dummy address | ||
| 385 | ReadSecurityRegister = 0x2BD4, | ||
| 386 | /// Write Security Register to set customer lock-down bit | ||
| 387 | WriteSecurityRegister = 0x2FD0, | ||
| 388 | /// Set burst/wrap length for read operations with 4-byte dummy address | ||
| 389 | SetBurstLength = 0xC03F, | ||
| 390 | /// Read 32-bit Fast Boot Register with 4-byte dummy address | ||
| 391 | ReadFastBootRegister = 0x16E9, | ||
| 392 | /// Write 32-bit Fast Boot Register with 4-byte dummy address | ||
| 393 | WriteFastBootRegister = 0x17E8, | ||
| 394 | /// Erase Fast Boot Register (disable fast boot feature) | ||
| 395 | EraseFastBootRegister = 0x18E7, | ||
| 396 | /// Enter 8K-bit secured OTP mode for programming unique identifiers | ||
| 397 | EnterSecuredOTP = 0xB14E, | ||
| 398 | /// Exit secured OTP mode and return to main array access | ||
| 399 | ExitSecuredOTP = 0xC13E, | ||
| 400 | /// Write Lock Register to control SPB protection mode with 4-byte dummy address | ||
| 401 | WriteLockRegister = 0x2CD3, | ||
| 402 | /// Read Lock Register status with 4-byte dummy address | ||
| 403 | ReadLockRegister = 0x2DD2, | ||
| 404 | /// Program Solid Protection Bit (SPB) for specified 4-byte address | ||
| 405 | WriteSPB = 0xE31C, | ||
| 406 | /// Erase all Solid Protection Bits (SPB) | ||
| 407 | EraseSPB = 0xE41B, | ||
| 408 | /// Read Solid Protection Bit (SPB) status for specified 4-byte address | ||
| 409 | ReadSPB = 0xE21D, | ||
| 410 | /// Write Dynamic Protection Bit (DPB) for specified 4-byte address | ||
| 411 | WriteDPB = 0xE11E, | ||
| 412 | /// Read Dynamic Protection Bit (DPB) status for specified 4-byte address | ||
| 413 | ReadDPB = 0xE01F, | ||
| 414 | /// Read 64-bit password register with 4-byte dummy address and 20 dummy cycles | ||
| 415 | ReadPassword = 0x27D8, | ||
| 416 | /// Write 64-bit password register with 4-byte dummy address | ||
| 417 | WritePassword = 0x28D7, | ||
| 418 | /// Unlock SPB operations using 64-bit password with 4-byte dummy address | ||
| 419 | PasswordUnlock = 0x29D6, | ||
| 420 | } | ||
| 162 | 421 | ||
| 163 | async fn qpi_mode(&mut self) { | 422 | impl<I: Instance> SpiFlashMemory<I> { |
| 164 | // Enter qpi mode | 423 | pub fn new(xspi: Xspi<'static, I, Blocking>) -> Self { |
| 165 | self.exec_command(0x38).await; | 424 | let mut memory = Self { xspi }; |
| 166 | 425 | ||
| 167 | // Set read param | 426 | memory.reset_memory(); |
| 168 | let transaction = TransferConfig { | 427 | memory |
| 169 | iwidth: XspiWidth::QUAD, | ||
| 170 | dwidth: XspiWidth::QUAD, | ||
| 171 | instruction: Some(0xC0), | ||
| 172 | ..Default::default() | ||
| 173 | }; | ||
| 174 | self.enable_write().await; | ||
| 175 | self.xspi.blocking_write(&[0x30_u8], transaction).unwrap(); | ||
| 176 | self.wait_write_finish(); | ||
| 177 | } | 428 | } |
| 178 | 429 | ||
| 179 | pub async fn disable_mm(&mut self) { | 430 | pub fn disable_mm(&mut self) { |
| 180 | self.xspi.disable_memory_mapped_mode(); | 431 | self.xspi.disable_memory_mapped_mode(); |
| 181 | } | 432 | } |
| 182 | 433 | ||
| 183 | pub async fn enable_mm(&mut self) { | 434 | pub fn enable_mm(&mut self) { |
| 184 | self.qpi_mode().await; | ||
| 185 | |||
| 186 | let read_config = TransferConfig { | 435 | let read_config = TransferConfig { |
| 187 | iwidth: XspiWidth::SING, | 436 | iwidth: XspiWidth::SING, |
| 188 | isize: AddressSize::_8bit, | 437 | isize: AddressSize::_8bit, |
| 189 | adwidth: XspiWidth::SING, | 438 | adwidth: XspiWidth::SING, |
| 190 | adsize: AddressSize::_24bit, | 439 | adsize: AddressSize::_32bit, |
| 191 | dwidth: XspiWidth::SING, | 440 | dwidth: XspiWidth::SING, |
| 192 | instruction: Some(CMD_READ as u32), | 441 | instruction: Some(SpiCommand::FastRead4B as u32), |
| 193 | dummy: DummyCycles::_8, | 442 | dummy: DummyCycles::_8, |
| 194 | ..Default::default() | 443 | ..Default::default() |
| 195 | }; | 444 | }; |
| @@ -198,42 +447,28 @@ impl<I: Instance> FlashMemory<I> { | |||
| 198 | iwidth: XspiWidth::SING, | 447 | iwidth: XspiWidth::SING, |
| 199 | isize: AddressSize::_8bit, | 448 | isize: AddressSize::_8bit, |
| 200 | adwidth: XspiWidth::SING, | 449 | adwidth: XspiWidth::SING, |
| 201 | adsize: AddressSize::_24bit, | 450 | adsize: AddressSize::_32bit, |
| 202 | dwidth: XspiWidth::SING, | 451 | dwidth: XspiWidth::SING, |
| 203 | instruction: Some(CMD_WRITE_PG as u32), | 452 | instruction: Some(SpiCommand::PageProgram4B as u32), |
| 204 | dummy: DummyCycles::_0, | 453 | dummy: DummyCycles::_0, |
| 205 | ..Default::default() | 454 | ..Default::default() |
| 206 | }; | 455 | }; |
| 207 | self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); | 456 | self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); |
| 208 | } | 457 | } |
| 209 | 458 | ||
| 210 | fn enable_octo(&mut self) { | 459 | fn into_octo(mut self) -> OpiFlashMemory<I> { |
| 211 | let cr = self.read_cr(); | 460 | self.enable_opi_mode(); |
| 212 | // info!("Read cr: {:x}", cr); | 461 | OpiFlashMemory { xspi: self.xspi } |
| 213 | self.write_cr(cr | 0x02); | ||
| 214 | // info!("Read cr after writing: {:x}", cr); | ||
| 215 | } | 462 | } |
| 216 | 463 | ||
| 217 | pub fn disable_octo(&mut self) { | 464 | fn enable_opi_mode(&mut self) { |
| 218 | let cr = self.read_cr(); | 465 | let cr2_0 = self.read_cr2(0); |
| 219 | self.write_cr(cr & (!(0x02))); | 466 | info!("Read CR2 at 0x0: {:x}", cr2_0); |
| 220 | } | 467 | self.enable_write(); |
| 221 | 468 | self.write_cr2(0, cr2_0 | 0x01); // Set bit 0 to enable octo SPI in STR | |
| 222 | async fn exec_command_4(&mut self, cmd: u8) { | ||
| 223 | let transaction = TransferConfig { | ||
| 224 | iwidth: XspiWidth::QUAD, | ||
| 225 | adwidth: XspiWidth::NONE, | ||
| 226 | // adsize: AddressSize::_24bit, | ||
| 227 | dwidth: XspiWidth::NONE, | ||
| 228 | instruction: Some(cmd as u32), | ||
| 229 | address: None, | ||
| 230 | dummy: DummyCycles::_0, | ||
| 231 | ..Default::default() | ||
| 232 | }; | ||
| 233 | self.xspi.blocking_command(&transaction).unwrap(); | ||
| 234 | } | 469 | } |
| 235 | 470 | ||
| 236 | async fn exec_command(&mut self, cmd: u8) { | 471 | fn exec_command(&mut self, cmd: u8) { |
| 237 | let transaction = TransferConfig { | 472 | let transaction = TransferConfig { |
| 238 | iwidth: XspiWidth::SING, | 473 | iwidth: XspiWidth::SING, |
| 239 | adwidth: XspiWidth::NONE, | 474 | adwidth: XspiWidth::NONE, |
| @@ -248,16 +483,14 @@ impl<I: Instance> FlashMemory<I> { | |||
| 248 | self.xspi.blocking_command(&transaction).unwrap(); | 483 | self.xspi.blocking_command(&transaction).unwrap(); |
| 249 | } | 484 | } |
| 250 | 485 | ||
| 251 | pub async fn reset_memory(&mut self) { | 486 | pub fn reset_memory(&mut self) { |
| 252 | self.exec_command_4(CMD_ENABLE_RESET).await; | 487 | self.exec_command(SpiCommand::ResetEnable as u8); |
| 253 | self.exec_command_4(CMD_RESET).await; | 488 | self.exec_command(SpiCommand::ResetMemory as u8); |
| 254 | self.exec_command(CMD_ENABLE_RESET).await; | ||
| 255 | self.exec_command(CMD_RESET).await; | ||
| 256 | self.wait_write_finish(); | 489 | self.wait_write_finish(); |
| 257 | } | 490 | } |
| 258 | 491 | ||
| 259 | pub async fn enable_write(&mut self) { | 492 | pub fn enable_write(&mut self) { |
| 260 | self.exec_command(CMD_WRITE_ENABLE).await; | 493 | self.exec_command(SpiCommand::WriteEnable as u8); |
| 261 | } | 494 | } |
| 262 | 495 | ||
| 263 | pub fn read_id(&mut self) -> [u8; 3] { | 496 | pub fn read_id(&mut self) -> [u8; 3] { |
| @@ -266,92 +499,64 @@ impl<I: Instance> FlashMemory<I> { | |||
| 266 | iwidth: XspiWidth::SING, | 499 | iwidth: XspiWidth::SING, |
| 267 | isize: AddressSize::_8bit, | 500 | isize: AddressSize::_8bit, |
| 268 | adwidth: XspiWidth::NONE, | 501 | adwidth: XspiWidth::NONE, |
| 269 | // adsize: AddressSize::_24bit, | ||
| 270 | dwidth: XspiWidth::SING, | 502 | dwidth: XspiWidth::SING, |
| 271 | instruction: Some(CMD_READ_ID as u32), | 503 | instruction: Some(SpiCommand::ReadIdentification as u32), |
| 272 | ..Default::default() | 504 | ..Default::default() |
| 273 | }; | 505 | }; |
| 274 | // info!("Reading id: 0x{:X}", transaction.instruction); | ||
| 275 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | 506 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); |
| 276 | buffer | 507 | buffer |
| 277 | } | 508 | } |
| 278 | 509 | ||
| 279 | pub fn read_id_8(&mut self) -> [u8; 3] { | 510 | pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) { |
| 280 | let mut buffer = [0; 3]; | ||
| 281 | let transaction: TransferConfig = TransferConfig { | ||
| 282 | iwidth: XspiWidth::OCTO, | ||
| 283 | isize: AddressSize::_16bit, | ||
| 284 | adwidth: XspiWidth::OCTO, | ||
| 285 | address: Some(0), | ||
| 286 | adsize: AddressSize::_32bit, | ||
| 287 | dwidth: XspiWidth::OCTO, | ||
| 288 | instruction: Some(CMD_READ_ID_OCTO as u32), | ||
| 289 | dummy: DummyCycles::_4, | ||
| 290 | ..Default::default() | ||
| 291 | }; | ||
| 292 | info!("Reading id: {:#X}", transaction.instruction); | ||
| 293 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | ||
| 294 | buffer | ||
| 295 | } | ||
| 296 | |||
| 297 | pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8], use_dma: bool) { | ||
| 298 | let transaction = TransferConfig { | 511 | let transaction = TransferConfig { |
| 299 | iwidth: XspiWidth::SING, | 512 | iwidth: XspiWidth::SING, |
| 300 | adwidth: XspiWidth::SING, | 513 | adwidth: XspiWidth::SING, |
| 301 | adsize: AddressSize::_24bit, | 514 | adsize: AddressSize::_32bit, |
| 302 | dwidth: XspiWidth::SING, | 515 | dwidth: XspiWidth::SING, |
| 303 | instruction: Some(CMD_READ as u32), | 516 | instruction: Some(SpiCommand::FastRead4B as u32), |
| 304 | dummy: DummyCycles::_8, | 517 | dummy: DummyCycles::_8, |
| 305 | // dwidth: XspiWidth::QUAD, | ||
| 306 | // instruction: Some(CMD_QUAD_READ as u32), | ||
| 307 | // dummy: DummyCycles::_8, | ||
| 308 | address: Some(addr), | 518 | address: Some(addr), |
| 309 | ..Default::default() | 519 | ..Default::default() |
| 310 | }; | 520 | }; |
| 311 | if use_dma { | 521 | |
| 312 | self.xspi.blocking_read(buffer, transaction).unwrap(); | 522 | self.xspi.blocking_read(buffer, transaction).unwrap(); |
| 313 | } else { | ||
| 314 | self.xspi.blocking_read(buffer, transaction).unwrap(); | ||
| 315 | } | ||
| 316 | } | 523 | } |
| 317 | 524 | ||
| 318 | fn wait_write_finish(&mut self) { | 525 | fn wait_write_finish(&mut self) { |
| 319 | while (self.read_sr() & 0x01) != 0 {} | 526 | while (self.read_sr() & 0x01) != 0 {} |
| 320 | } | 527 | } |
| 321 | 528 | ||
| 322 | async fn perform_erase(&mut self, addr: u32, cmd: u8) { | 529 | fn perform_erase(&mut self, addr: u32, cmd: u8) { |
| 323 | let transaction = TransferConfig { | 530 | let transaction = TransferConfig { |
| 324 | iwidth: XspiWidth::SING, | 531 | iwidth: XspiWidth::SING, |
| 325 | adwidth: XspiWidth::SING, | 532 | adwidth: XspiWidth::SING, |
| 326 | adsize: AddressSize::_24bit, | 533 | adsize: AddressSize::_32bit, |
| 327 | dwidth: XspiWidth::NONE, | 534 | dwidth: XspiWidth::NONE, |
| 328 | instruction: Some(cmd as u32), | 535 | instruction: Some(cmd as u32), |
| 329 | address: Some(addr), | 536 | address: Some(addr), |
| 330 | dummy: DummyCycles::_0, | 537 | dummy: DummyCycles::_0, |
| 331 | ..Default::default() | 538 | ..Default::default() |
| 332 | }; | 539 | }; |
| 333 | self.enable_write().await; | 540 | self.enable_write(); |
| 334 | self.xspi.blocking_command(&transaction).unwrap(); | 541 | self.xspi.blocking_command(&transaction).unwrap(); |
| 335 | self.wait_write_finish(); | 542 | self.wait_write_finish(); |
| 336 | } | 543 | } |
| 337 | 544 | ||
| 338 | pub async fn erase_sector(&mut self, addr: u32) { | 545 | pub fn erase_sector(&mut self, addr: u32) { |
| 339 | self.perform_erase(addr, CMD_SECTOR_ERASE).await; | 546 | self.perform_erase(addr, SpiCommand::SectorErase4B as u8); |
| 340 | } | 547 | } |
| 341 | 548 | ||
| 342 | pub async fn erase_block_32k(&mut self, addr: u32) { | 549 | pub fn erase_block_64k(&mut self, addr: u32) { |
| 343 | self.perform_erase(addr, CMD_BLOCK_ERASE_32K).await; | 550 | self.perform_erase(addr, SpiCommand::BlockErase4B as u8); |
| 344 | } | 551 | } |
| 345 | 552 | ||
| 346 | pub async fn erase_block_64k(&mut self, addr: u32) { | 553 | pub fn erase_chip(&mut self) { |
| 347 | self.perform_erase(addr, CMD_BLOCK_ERASE_64K).await; | 554 | self.enable_write(); |
| 348 | } | 555 | self.exec_command(SpiCommand::ChipErase as u8); |
| 349 | 556 | self.wait_write_finish(); | |
| 350 | pub async fn erase_chip(&mut self) { | ||
| 351 | self.exec_command(CMD_CHIP_ERASE).await; | ||
| 352 | } | 557 | } |
| 353 | 558 | ||
| 354 | async fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize, use_dma: bool) { | 559 | fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) { |
| 355 | assert!( | 560 | assert!( |
| 356 | (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, | 561 | (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, |
| 357 | "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}", | 562 | "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}", |
| @@ -361,48 +566,43 @@ impl<I: Instance> FlashMemory<I> { | |||
| 361 | 566 | ||
| 362 | let transaction = TransferConfig { | 567 | let transaction = TransferConfig { |
| 363 | iwidth: XspiWidth::SING, | 568 | iwidth: XspiWidth::SING, |
| 364 | adsize: AddressSize::_24bit, | 569 | adsize: AddressSize::_32bit, |
| 365 | adwidth: XspiWidth::SING, | 570 | adwidth: XspiWidth::SING, |
| 366 | dwidth: XspiWidth::SING, | 571 | dwidth: XspiWidth::SING, |
| 367 | instruction: Some(CMD_WRITE_PG as u32), | 572 | instruction: Some(SpiCommand::PageProgram4B as u32), |
| 368 | // dwidth: XspiWidth::QUAD, | ||
| 369 | // instruction: Some(CMD_QUAD_WRITE_PG as u32), | ||
| 370 | address: Some(addr), | 573 | address: Some(addr), |
| 371 | dummy: DummyCycles::_0, | 574 | dummy: DummyCycles::_0, |
| 372 | ..Default::default() | 575 | ..Default::default() |
| 373 | }; | 576 | }; |
| 374 | self.enable_write().await; | 577 | self.enable_write(); |
| 375 | if use_dma { | 578 | self.xspi.blocking_write(buffer, transaction).unwrap(); |
| 376 | self.xspi.blocking_write(buffer, transaction).unwrap(); | ||
| 377 | } else { | ||
| 378 | self.xspi.blocking_write(buffer, transaction).unwrap(); | ||
| 379 | } | ||
| 380 | self.wait_write_finish(); | 579 | self.wait_write_finish(); |
| 381 | } | 580 | } |
| 382 | 581 | ||
| 383 | pub async fn write_memory(&mut self, addr: u32, buffer: &[u8], use_dma: bool) { | 582 | pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) { |
| 384 | let mut left = buffer.len(); | 583 | let mut left = buffer.len(); |
| 385 | let mut place = addr; | 584 | let mut place = addr; |
| 386 | let mut chunk_start = 0; | 585 | let mut chunk_start = 0; |
| 387 | 586 | ||
| 388 | while left > 0 { | 587 | while left > 0 { |
| 389 | let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; | 588 | let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; |
| 390 | let chunk_size = if left >= max_chunk_size { max_chunk_size } else { left }; | 589 | let chunk_size = min(max_chunk_size, left); |
| 391 | let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; | 590 | let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; |
| 392 | self.write_page(place, chunk, chunk_size, use_dma).await; | 591 | self.write_page(place, chunk, chunk_size); |
| 393 | place += chunk_size as u32; | 592 | place += chunk_size as u32; |
| 394 | left -= chunk_size; | 593 | left -= chunk_size; |
| 395 | chunk_start += chunk_size; | 594 | chunk_start += chunk_size; |
| 396 | } | 595 | } |
| 397 | } | 596 | } |
| 398 | 597 | ||
| 598 | // Note: read_register cannot be used to read the configuration register 2 since there is an | ||
| 599 | // address required for that read. | ||
| 399 | fn read_register(&mut self, cmd: u8) -> u8 { | 600 | fn read_register(&mut self, cmd: u8) -> u8 { |
| 400 | let mut buffer = [0; 1]; | 601 | let mut buffer = [0; 1]; |
| 401 | let transaction: TransferConfig = TransferConfig { | 602 | let transaction: TransferConfig = TransferConfig { |
| 402 | iwidth: XspiWidth::SING, | 603 | iwidth: XspiWidth::SING, |
| 403 | isize: AddressSize::_8bit, | 604 | isize: AddressSize::_8bit, |
| 404 | adwidth: XspiWidth::NONE, | 605 | adwidth: XspiWidth::NONE, |
| 405 | adsize: AddressSize::_24bit, | ||
| 406 | dwidth: XspiWidth::SING, | 606 | dwidth: XspiWidth::SING, |
| 407 | instruction: Some(cmd as u32), | 607 | instruction: Some(cmd as u32), |
| 408 | address: None, | 608 | address: None, |
| @@ -410,39 +610,345 @@ impl<I: Instance> FlashMemory<I> { | |||
| 410 | ..Default::default() | 610 | ..Default::default() |
| 411 | }; | 611 | }; |
| 412 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | 612 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); |
| 413 | // info!("Read w25q64 register: 0x{:x}", buffer[0]); | ||
| 414 | buffer[0] | 613 | buffer[0] |
| 415 | } | 614 | } |
| 416 | 615 | ||
| 417 | fn write_register(&mut self, cmd: u8, value: u8) { | 616 | pub fn read_sr(&mut self) -> u8 { |
| 418 | let buffer = [value; 1]; | 617 | self.read_register(SpiCommand::ReadStatusRegister as u8) |
| 618 | } | ||
| 619 | |||
| 620 | pub fn read_cr(&mut self) -> u8 { | ||
| 621 | self.read_register(SpiCommand::ReadConfigurationRegister as u8) | ||
| 622 | } | ||
| 623 | |||
| 624 | pub fn write_sr_cr(&mut self, sr: u8, cr: u8) { | ||
| 625 | let buffer = [sr, cr]; | ||
| 419 | let transaction: TransferConfig = TransferConfig { | 626 | let transaction: TransferConfig = TransferConfig { |
| 420 | iwidth: XspiWidth::SING, | 627 | iwidth: XspiWidth::SING, |
| 421 | isize: AddressSize::_8bit, | 628 | isize: AddressSize::_8bit, |
| 422 | instruction: Some(cmd as u32), | 629 | instruction: Some(SpiCommand::WriteStatusConfigurationRegister as u32), |
| 423 | adsize: AddressSize::_24bit, | ||
| 424 | adwidth: XspiWidth::NONE, | 630 | adwidth: XspiWidth::NONE, |
| 425 | dwidth: XspiWidth::SING, | 631 | dwidth: XspiWidth::SING, |
| 426 | address: None, | 632 | address: None, |
| 427 | dummy: DummyCycles::_0, | 633 | dummy: DummyCycles::_0, |
| 428 | ..Default::default() | 634 | ..Default::default() |
| 429 | }; | 635 | }; |
| 636 | self.enable_write(); | ||
| 637 | self.xspi.blocking_write(&buffer, transaction).unwrap(); | ||
| 638 | self.wait_write_finish(); | ||
| 639 | } | ||
| 640 | |||
| 641 | pub fn read_cr2(&mut self, address: u32) -> u8 { | ||
| 642 | let mut buffer = [0; 1]; | ||
| 643 | let transaction: TransferConfig = TransferConfig { | ||
| 644 | iwidth: XspiWidth::SING, | ||
| 645 | isize: AddressSize::_8bit, | ||
| 646 | instruction: Some(SpiCommand::ReadConfigurationRegister2 as u32), | ||
| 647 | adsize: AddressSize::_32bit, | ||
| 648 | adwidth: XspiWidth::SING, | ||
| 649 | dwidth: XspiWidth::SING, | ||
| 650 | address: Some(address), | ||
| 651 | dummy: DummyCycles::_0, | ||
| 652 | ..Default::default() | ||
| 653 | }; | ||
| 654 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | ||
| 655 | buffer[0] | ||
| 656 | } | ||
| 657 | |||
| 658 | pub fn write_cr2(&mut self, address: u32, value: u8) { | ||
| 659 | let buffer = [value; 1]; | ||
| 660 | let transaction: TransferConfig = TransferConfig { | ||
| 661 | iwidth: XspiWidth::SING, | ||
| 662 | isize: AddressSize::_8bit, | ||
| 663 | instruction: Some(SpiCommand::WriteConfigurationRegister2 as u32), | ||
| 664 | adsize: AddressSize::_32bit, | ||
| 665 | adwidth: XspiWidth::SING, | ||
| 666 | dwidth: XspiWidth::SING, | ||
| 667 | address: Some(address), | ||
| 668 | dummy: DummyCycles::_0, | ||
| 669 | ..Default::default() | ||
| 670 | }; | ||
| 430 | self.xspi.blocking_write(&buffer, transaction).unwrap(); | 671 | self.xspi.blocking_write(&buffer, transaction).unwrap(); |
| 672 | self.wait_write_finish(); | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | impl<I: Instance> OpiFlashMemory<I> { | ||
| 677 | pub fn into_spi(mut self) -> SpiFlashMemory<I> { | ||
| 678 | self.disable_opi_mode(); | ||
| 679 | SpiFlashMemory { xspi: self.xspi } | ||
| 680 | } | ||
| 681 | |||
| 682 | /// Disable OPI mode and return to SPI | ||
| 683 | pub fn disable_opi_mode(&mut self) { | ||
| 684 | // Clear SOPI and DOPI bits in CR2 volatile register | ||
| 685 | let cr2_0 = self.read_cr2(0x00000000); | ||
| 686 | self.write_cr2(0x00000000, cr2_0 & 0xFC); // Clear bits 0 and 1 | ||
| 687 | } | ||
| 688 | |||
| 689 | /// Enable memory-mapped mode for OPI | ||
| 690 | pub fn enable_mm(&mut self) { | ||
| 691 | let read_config = TransferConfig { | ||
| 692 | iwidth: XspiWidth::OCTO, | ||
| 693 | isize: AddressSize::_16bit, // 2-byte command for OPI | ||
| 694 | adwidth: XspiWidth::OCTO, | ||
| 695 | adsize: AddressSize::_32bit, | ||
| 696 | dwidth: XspiWidth::OCTO, | ||
| 697 | instruction: Some(OpiCommand::OctaRead as u32), | ||
| 698 | dummy: DummyCycles::_20, // Default dummy cycles for OPI | ||
| 699 | ..Default::default() | ||
| 700 | }; | ||
| 701 | |||
| 702 | let write_config = TransferConfig { | ||
| 703 | iwidth: XspiWidth::OCTO, | ||
| 704 | isize: AddressSize::_16bit, | ||
| 705 | adwidth: XspiWidth::OCTO, | ||
| 706 | adsize: AddressSize::_32bit, | ||
| 707 | dwidth: XspiWidth::OCTO, | ||
| 708 | instruction: Some(OpiCommand::PageProgram4B as u32), | ||
| 709 | dummy: DummyCycles::_0, | ||
| 710 | ..Default::default() | ||
| 711 | }; | ||
| 712 | |||
| 713 | self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); | ||
| 714 | } | ||
| 715 | |||
| 716 | pub fn disable_mm(&mut self) { | ||
| 717 | self.xspi.disable_memory_mapped_mode(); | ||
| 718 | } | ||
| 719 | |||
| 720 | /// Execute OPI command (2-byte command) | ||
| 721 | fn exec_command(&mut self, cmd: OpiCommand) { | ||
| 722 | let transaction = TransferConfig { | ||
| 723 | iwidth: XspiWidth::OCTO, | ||
| 724 | isize: AddressSize::_16bit, // 2-byte command | ||
| 725 | adwidth: XspiWidth::NONE, | ||
| 726 | dwidth: XspiWidth::NONE, | ||
| 727 | instruction: Some(cmd as u32), | ||
| 728 | address: None, | ||
| 729 | dummy: DummyCycles::_0, | ||
| 730 | ..Default::default() | ||
| 731 | }; | ||
| 732 | self.xspi.blocking_command(&transaction).unwrap(); | ||
| 733 | } | ||
| 734 | |||
| 735 | /// Reset memory using OPI commands | ||
| 736 | pub fn reset_memory(&mut self) { | ||
| 737 | self.exec_command(OpiCommand::ResetEnable); | ||
| 738 | self.exec_command(OpiCommand::ResetMemory); | ||
| 739 | self.wait_write_finish(); | ||
| 431 | } | 740 | } |
| 432 | 741 | ||
| 742 | /// Enable write using OPI command | ||
| 743 | pub fn enable_write(&mut self) { | ||
| 744 | self.exec_command(OpiCommand::WriteEnable); | ||
| 745 | } | ||
| 746 | |||
| 747 | /// Read device ID in OPI mode | ||
| 748 | pub fn read_id(&mut self) -> [u8; 3] { | ||
| 749 | let mut buffer = [0; 3]; | ||
| 750 | let transaction = TransferConfig { | ||
| 751 | iwidth: XspiWidth::OCTO, | ||
| 752 | isize: AddressSize::_16bit, | ||
| 753 | adwidth: XspiWidth::OCTO, | ||
| 754 | adsize: AddressSize::_32bit, | ||
| 755 | dwidth: XspiWidth::OCTO, | ||
| 756 | instruction: Some(OpiCommand::ReadIdentification as u32), | ||
| 757 | address: Some(0x00000000), // Dummy address required | ||
| 758 | dummy: DummyCycles::_4, | ||
| 759 | ..Default::default() | ||
| 760 | }; | ||
| 761 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | ||
| 762 | buffer | ||
| 763 | } | ||
| 764 | |||
| 765 | /// Read memory using OPI mode | ||
| 766 | pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) { | ||
| 767 | let transaction = TransferConfig { | ||
| 768 | iwidth: XspiWidth::OCTO, | ||
| 769 | isize: AddressSize::_16bit, | ||
| 770 | adwidth: XspiWidth::OCTO, | ||
| 771 | adsize: AddressSize::_32bit, | ||
| 772 | dwidth: XspiWidth::OCTO, | ||
| 773 | instruction: Some(OpiCommand::OctaRead as u32), | ||
| 774 | address: Some(addr), | ||
| 775 | dummy: DummyCycles::_20, // Default for 200MHz operation | ||
| 776 | ..Default::default() | ||
| 777 | }; | ||
| 778 | self.xspi.blocking_read(buffer, transaction).unwrap(); | ||
| 779 | } | ||
| 780 | |||
| 781 | /// Wait for write completion using OPI status read | ||
| 782 | fn wait_write_finish(&mut self) { | ||
| 783 | while (self.read_sr() & 0x01) != 0 {} | ||
| 784 | } | ||
| 785 | |||
| 786 | /// Perform erase operation using OPI command | ||
| 787 | fn perform_erase(&mut self, addr: u32, cmd: OpiCommand) { | ||
| 788 | let transaction = TransferConfig { | ||
| 789 | iwidth: XspiWidth::OCTO, | ||
| 790 | isize: AddressSize::_16bit, | ||
| 791 | adwidth: XspiWidth::OCTO, | ||
| 792 | adsize: AddressSize::_32bit, | ||
| 793 | dwidth: XspiWidth::NONE, | ||
| 794 | instruction: Some(cmd as u32), | ||
| 795 | address: Some(addr), | ||
| 796 | dummy: DummyCycles::_0, | ||
| 797 | ..Default::default() | ||
| 798 | }; | ||
| 799 | self.enable_write(); | ||
| 800 | self.xspi.blocking_command(&transaction).unwrap(); | ||
| 801 | self.wait_write_finish(); | ||
| 802 | } | ||
| 803 | |||
| 804 | /// Erase 4KB sector using OPI | ||
| 805 | pub fn erase_sector(&mut self, addr: u32) { | ||
| 806 | self.perform_erase(addr, OpiCommand::SectorErase4B); | ||
| 807 | } | ||
| 808 | |||
| 809 | /// Erase 64KB block using OPI | ||
| 810 | pub fn erase_block_64k(&mut self, addr: u32) { | ||
| 811 | self.perform_erase(addr, OpiCommand::BlockErase4B); | ||
| 812 | } | ||
| 813 | |||
| 814 | /// Erase entire chip using OPI | ||
| 815 | pub fn erase_chip(&mut self) { | ||
| 816 | self.enable_write(); | ||
| 817 | self.exec_command(OpiCommand::ChipErase); | ||
| 818 | self.wait_write_finish(); | ||
| 819 | } | ||
| 820 | |||
| 821 | /// Write single page using OPI | ||
| 822 | fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) { | ||
| 823 | assert!( | ||
| 824 | (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, | ||
| 825 | "write_page(): page write length exceeds page boundary (len = {}, addr = {:X})", | ||
| 826 | len, | ||
| 827 | addr | ||
| 828 | ); | ||
| 829 | |||
| 830 | let transaction = TransferConfig { | ||
| 831 | iwidth: XspiWidth::OCTO, | ||
| 832 | isize: AddressSize::_16bit, | ||
| 833 | adwidth: XspiWidth::OCTO, | ||
| 834 | adsize: AddressSize::_32bit, | ||
| 835 | dwidth: XspiWidth::OCTO, | ||
| 836 | instruction: Some(OpiCommand::PageProgram4B as u32), | ||
| 837 | address: Some(addr), | ||
| 838 | dummy: DummyCycles::_0, | ||
| 839 | ..Default::default() | ||
| 840 | }; | ||
| 841 | self.enable_write(); | ||
| 842 | self.xspi.blocking_write(buffer, transaction).unwrap(); | ||
| 843 | self.wait_write_finish(); | ||
| 844 | } | ||
| 845 | |||
| 846 | /// Write memory using OPI (handles page boundaries) | ||
| 847 | pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) { | ||
| 848 | let mut left = buffer.len(); | ||
| 849 | let mut place = addr; | ||
| 850 | let mut chunk_start = 0; | ||
| 851 | |||
| 852 | while left > 0 { | ||
| 853 | let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; | ||
| 854 | let chunk_size = min(max_chunk_size, left); | ||
| 855 | let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; | ||
| 856 | self.write_page(place, chunk, chunk_size); | ||
| 857 | place += chunk_size as u32; | ||
| 858 | left -= chunk_size; | ||
| 859 | chunk_start += chunk_size; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 863 | /// Read register using OPI mode | ||
| 864 | fn read_register(&mut self, cmd: OpiCommand, dummy_addr: u32, dummy_cycles: DummyCycles) -> u8 { | ||
| 865 | let mut buffer = [0; 1]; | ||
| 866 | let transaction = TransferConfig { | ||
| 867 | iwidth: XspiWidth::OCTO, | ||
| 868 | isize: AddressSize::_16bit, | ||
| 869 | adwidth: XspiWidth::OCTO, | ||
| 870 | adsize: AddressSize::_32bit, | ||
| 871 | dwidth: XspiWidth::OCTO, | ||
| 872 | instruction: Some(cmd as u32), | ||
| 873 | address: Some(dummy_addr), | ||
| 874 | dummy: dummy_cycles, | ||
| 875 | ..Default::default() | ||
| 876 | }; | ||
| 877 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | ||
| 878 | buffer[0] | ||
| 879 | } | ||
| 880 | |||
| 881 | /// Read Status Register using OPI | ||
| 433 | pub fn read_sr(&mut self) -> u8 { | 882 | pub fn read_sr(&mut self) -> u8 { |
| 434 | self.read_register(CMD_READ_SR) | 883 | self.read_register( |
| 884 | OpiCommand::ReadStatusRegister, | ||
| 885 | 0x00000000, // Dummy address | ||
| 886 | DummyCycles::_4, | ||
| 887 | ) | ||
| 435 | } | 888 | } |
| 436 | 889 | ||
| 890 | /// Read Configuration Register using OPI | ||
| 437 | pub fn read_cr(&mut self) -> u8 { | 891 | pub fn read_cr(&mut self) -> u8 { |
| 438 | self.read_register(CMD_READ_CR) | 892 | self.read_register( |
| 893 | OpiCommand::ReadConfigurationRegister, | ||
| 894 | 0x00000001, // Address for CR | ||
| 895 | DummyCycles::_4, | ||
| 896 | ) | ||
| 439 | } | 897 | } |
| 440 | 898 | ||
| 441 | pub fn write_sr(&mut self, value: u8) { | 899 | /// Write Status/Configuration Register using OPI |
| 442 | self.write_register(CMD_WRITE_SR, value); | 900 | pub fn write_sr_cr(&mut self, sr: u8, cr: u8) { |
| 901 | let transaction = TransferConfig { | ||
| 902 | iwidth: XspiWidth::OCTO, | ||
| 903 | isize: AddressSize::_16bit, | ||
| 904 | adwidth: XspiWidth::OCTO, | ||
| 905 | adsize: AddressSize::_32bit, | ||
| 906 | dwidth: XspiWidth::OCTO, | ||
| 907 | instruction: Some(OpiCommand::WriteStatusConfigurationRegister as u32), | ||
| 908 | address: Some(0x00000000), | ||
| 909 | dummy: DummyCycles::_0, | ||
| 910 | ..Default::default() | ||
| 911 | }; | ||
| 912 | |||
| 913 | self.enable_write(); | ||
| 914 | self.xspi.blocking_write(&[sr, cr], transaction).unwrap(); | ||
| 915 | self.wait_write_finish(); | ||
| 916 | } | ||
| 917 | |||
| 918 | /// Read Configuration Register 2 using OPI | ||
| 919 | pub fn read_cr2(&mut self, address: u32) -> u8 { | ||
| 920 | let mut buffer = [0; 1]; | ||
| 921 | let transaction = TransferConfig { | ||
| 922 | iwidth: XspiWidth::OCTO, | ||
| 923 | isize: AddressSize::_16bit, | ||
| 924 | adwidth: XspiWidth::OCTO, | ||
| 925 | adsize: AddressSize::_32bit, | ||
| 926 | dwidth: XspiWidth::OCTO, | ||
| 927 | instruction: Some(OpiCommand::ReadConfigurationRegister2 as u32), | ||
| 928 | address: Some(address), | ||
| 929 | dummy: DummyCycles::_4, | ||
| 930 | ..Default::default() | ||
| 931 | }; | ||
| 932 | self.xspi.blocking_read(&mut buffer, transaction).unwrap(); | ||
| 933 | buffer[0] | ||
| 443 | } | 934 | } |
| 444 | 935 | ||
| 445 | pub fn write_cr(&mut self, value: u8) { | 936 | /// Write Configuration Register 2 using OPI |
| 446 | self.write_register(CMD_WRITE_CR, value); | 937 | pub fn write_cr2(&mut self, address: u32, value: u8) { |
| 938 | let transaction = TransferConfig { | ||
| 939 | iwidth: XspiWidth::OCTO, | ||
| 940 | isize: AddressSize::_16bit, | ||
| 941 | adwidth: XspiWidth::OCTO, | ||
| 942 | adsize: AddressSize::_32bit, | ||
| 943 | dwidth: XspiWidth::OCTO, | ||
| 944 | instruction: Some(OpiCommand::WriteConfigurationRegister2 as u32), | ||
| 945 | address: Some(address), | ||
| 946 | dummy: DummyCycles::_0, | ||
| 947 | ..Default::default() | ||
| 948 | }; | ||
| 949 | |||
| 950 | self.enable_write(); | ||
| 951 | self.xspi.blocking_write(&[value], transaction).unwrap(); | ||
| 952 | self.wait_write_finish(); | ||
| 447 | } | 953 | } |
| 448 | } | 954 | } |
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 189b0e8d4..d42cdac15 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -3,16 +3,19 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32l0-examples" | 3 | name = "embassy-stm32l0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32l072cz to your chip name, if necessary. | 9 | # Change stm32l072cz to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | ||
| 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 13 | 16 | ||
| 14 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 16 | 19 | ||
| 17 | embedded-storage = "0.3.1" | 20 | embedded-storage = "0.3.1" |
| 18 | embedded-io = { version = "0.6.0" } | 21 | embedded-io = { version = "0.6.0" } |
| @@ -20,7 +23,7 @@ embedded-io-async = { version = "0.6.1" } | |||
| 20 | 23 | ||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 22 | cortex-m-rt = "0.7.0" | 25 | cortex-m-rt = "0.7.0" |
| 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 26 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 24 | heapless = { version = "0.8", default-features = false } | 27 | heapless = { version = "0.8", default-features = false } |
| 25 | embedded-hal = "0.2.6" | 28 | embedded-hal = "0.2.6" |
| 26 | static_cell = { version = "2" } | 29 | static_cell = { version = "2" } |
| @@ -28,3 +31,8 @@ portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | |||
| 28 | 31 | ||
| 29 | [profile.release] | 32 | [profile.release] |
| 30 | debug = 2 | 33 | debug = 2 |
| 34 | |||
| 35 | [package.metadata.embassy] | ||
| 36 | build = [ | ||
| 37 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32l0" } | ||
| 38 | ] | ||
diff --git a/examples/stm32l0/src/bin/dds.rs b/examples/stm32l0/src/bin/dds.rs index a54b28a93..eaa7a61a8 100644 --- a/examples/stm32l0/src/bin/dds.rs +++ b/examples/stm32l0/src/bin/dds.rs | |||
| @@ -11,7 +11,7 @@ use embassy_stm32::rcc::*; | |||
| 11 | use embassy_stm32::time::hz; | 11 | use embassy_stm32::time::hz; |
| 12 | use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; | 12 | use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; |
| 13 | use embassy_stm32::timer::simple_pwm::PwmPin; | 13 | use embassy_stm32::timer::simple_pwm::PwmPin; |
| 14 | use embassy_stm32::timer::Channel; | 14 | use embassy_stm32::timer::{Ch3, Channel}; |
| 15 | use embassy_stm32::{interrupt, pac, Config}; | 15 | use embassy_stm32::{interrupt, pac, Config}; |
| 16 | use panic_probe as _; | 16 | use panic_probe as _; |
| 17 | 17 | ||
| @@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) { | |||
| 70 | let p = embassy_stm32::init(config); | 70 | let p = embassy_stm32::init(config); |
| 71 | 71 | ||
| 72 | // setup PWM pin in AF mode | 72 | // setup PWM pin in AF mode |
| 73 | let _ch3 = PwmPin::new_ch3(p.PA2, OutputType::PushPull); | 73 | let _ch3 = PwmPin::<_, Ch3>::new(p.PA2, OutputType::PushPull); |
| 74 | 74 | ||
| 75 | // initialize timer | 75 | // initialize timer |
| 76 | // we cannot use SimplePWM here because the Time is privately encapsulated | 76 | // we cannot use SimplePWM here because the Time is privately encapsulated |
diff --git a/examples/stm32l0/src/bin/eeprom.rs b/examples/stm32l0/src/bin/eeprom.rs new file mode 100644 index 000000000..370246644 --- /dev/null +++ b/examples/stm32l0/src/bin/eeprom.rs | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_stm32::init(Default::default()); | ||
| 12 | |||
| 13 | info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE); | ||
| 14 | |||
| 15 | const ADDR: u32 = 0x0; | ||
| 16 | |||
| 17 | let mut f = Flash::new_blocking(p.FLASH); | ||
| 18 | |||
| 19 | info!("Reading..."); | ||
| 20 | let mut buf = [0u8; 8]; | ||
| 21 | unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); | ||
| 22 | info!("Read: {=[u8]:x}", buf); | ||
| 23 | |||
| 24 | info!("Writing..."); | ||
| 25 | unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); | ||
| 26 | |||
| 27 | info!("Reading..."); | ||
| 28 | let mut buf = [0u8; 8]; | ||
| 29 | unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); | ||
| 30 | info!("Read: {=[u8]:x}", buf); | ||
| 31 | assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); | ||
| 32 | } | ||
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs index 29c7e0dc7..6385e3c8f 100644 --- a/examples/stm32l0/src/bin/raw_spawn.rs +++ b/examples/stm32l0/src/bin/raw_spawn.rs | |||
| @@ -42,8 +42,8 @@ fn main() -> ! { | |||
| 42 | let run2_task = unsafe { make_static(&run2_task) }; | 42 | let run2_task = unsafe { make_static(&run2_task) }; |
| 43 | 43 | ||
| 44 | executor.run(|spawner| { | 44 | executor.run(|spawner| { |
| 45 | unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); | 45 | spawner.spawn(unwrap!(run1_task.spawn(|| run1()))); |
| 46 | unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); | 46 | spawner.spawn(unwrap!(run2_task.spawn(|| run2()))); |
| 47 | }); | 47 | }); |
| 48 | } | 48 | } |
| 49 | 49 | ||
diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs new file mode 100644 index 000000000..fdb1aeb59 --- /dev/null +++ b/examples/stm32l0/src/bin/usb_serial.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{panic, *}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_futures::join::join; | ||
| 7 | use embassy_stm32::usb::{self, Driver, Instance}; | ||
| 8 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 10 | use embassy_usb::driver::EndpointError; | ||
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | USB => usb::InterruptHandler<peripherals::USB>; | ||
| 16 | }); | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | let mut config = embassy_stm32::Config::default(); | ||
| 21 | { | ||
| 22 | use embassy_stm32::rcc::*; | ||
| 23 | config.rcc.hsi = true; | ||
| 24 | config.rcc.pll = Some(Pll { | ||
| 25 | source: PllSource::HSI, | ||
| 26 | mul: PllMul::MUL6, // PLLVCO = 16*6 = 96Mhz | ||
| 27 | div: PllDiv::DIV3, // 32Mhz clock (16 * 6 / 3) | ||
| 28 | }); | ||
| 29 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 30 | } | ||
| 31 | |||
| 32 | let p = embassy_stm32::init(config); | ||
| 33 | |||
| 34 | info!("Hello World!"); | ||
| 35 | |||
| 36 | let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); | ||
| 37 | |||
| 38 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); | ||
| 39 | config.manufacturer = Some("Embassy"); | ||
| 40 | config.product = Some("USB-Serial Example"); | ||
| 41 | config.serial_number = Some("123456"); | ||
| 42 | |||
| 43 | let mut config_descriptor = [0; 256]; | ||
| 44 | let mut bos_descriptor = [0; 256]; | ||
| 45 | let mut control_buf = [0; 64]; | ||
| 46 | |||
| 47 | let mut state = State::new(); | ||
| 48 | |||
| 49 | let mut builder = Builder::new( | ||
| 50 | driver, | ||
| 51 | config, | ||
| 52 | &mut config_descriptor, | ||
| 53 | &mut bos_descriptor, | ||
| 54 | &mut [], // no msos descriptors | ||
| 55 | &mut control_buf, | ||
| 56 | ); | ||
| 57 | |||
| 58 | let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); | ||
| 59 | |||
| 60 | let mut usb = builder.build(); | ||
| 61 | |||
| 62 | let usb_fut = usb.run(); | ||
| 63 | |||
| 64 | let echo_fut = async { | ||
| 65 | loop { | ||
| 66 | class.wait_connection().await; | ||
| 67 | info!("Connected"); | ||
| 68 | let _ = echo(&mut class).await; | ||
| 69 | info!("Disconnected"); | ||
| 70 | } | ||
| 71 | }; | ||
| 72 | |||
| 73 | join(usb_fut, echo_fut).await; | ||
| 74 | } | ||
| 75 | |||
| 76 | struct Disconnected {} | ||
| 77 | |||
| 78 | impl From<EndpointError> for Disconnected { | ||
| 79 | fn from(val: EndpointError) -> Self { | ||
| 80 | match val { | ||
| 81 | EndpointError::BufferOverflow => panic!("Buffer overflow"), | ||
| 82 | EndpointError::Disabled => Disconnected {}, | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { | ||
| 88 | let mut buf = [0; 64]; | ||
| 89 | loop { | ||
| 90 | let n = class.read_packet(&mut buf).await?; | ||
| 91 | let data = &buf[..n]; | ||
| 92 | info!("data: {:x}", data); | ||
| 93 | class.write_packet(data).await?; | ||
| 94 | } | ||
| 95 | } | ||
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 6066b6dc7..76ceade9c 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml | |||
| @@ -3,24 +3,30 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32l1-examples" | 3 | name = "embassy-stm32l1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 10 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } | 12 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } |
| 12 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | 18 | ||
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 20 | embedded-hal = "0.2.6" | 21 | embedded-hal = "0.2.6" |
| 21 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 22 | heapless = { version = "0.8", default-features = false } | 23 | heapless = { version = "0.8", default-features = false } |
| 23 | embedded-storage = "0.3.1" | 24 | embedded-storage = "0.3.1" |
| 24 | 25 | ||
| 25 | [profile.release] | 26 | [profile.release] |
| 26 | debug = 2 | 27 | debug = 2 |
| 28 | |||
| 29 | [package.metadata.embassy] | ||
| 30 | build = [ | ||
| 31 | { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32l1" } | ||
| 32 | ] | ||
diff --git a/examples/stm32l1/src/bin/eeprom.rs b/examples/stm32l1/src/bin/eeprom.rs new file mode 100644 index 000000000..370246644 --- /dev/null +++ b/examples/stm32l1/src/bin/eeprom.rs | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_stm32::init(Default::default()); | ||
| 12 | |||
| 13 | info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE); | ||
| 14 | |||
| 15 | const ADDR: u32 = 0x0; | ||
| 16 | |||
| 17 | let mut f = Flash::new_blocking(p.FLASH); | ||
| 18 | |||
| 19 | info!("Reading..."); | ||
| 20 | let mut buf = [0u8; 8]; | ||
| 21 | unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); | ||
| 22 | info!("Read: {=[u8]:x}", buf); | ||
| 23 | |||
| 24 | info!("Writing..."); | ||
| 25 | unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); | ||
| 26 | |||
| 27 | info!("Reading..."); | ||
| 28 | let mut buf = [0u8; 8]; | ||
| 29 | unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); | ||
| 30 | info!("Read: {=[u8]:x}", buf); | ||
| 31 | assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); | ||
| 32 | } | ||
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 239bfcd79..1b7f15b1d 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32l4-examples" | 3 | name = "embassy-stm32l4-examples" |
| 4 | version = "0.1.1" | 4 | version = "0.1.1" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32l4s5vi to your chip name, if necessary. | 9 | # Change stm32l4s5vi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 14 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } | 16 | embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" } |
| 16 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } | 17 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } |
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 18 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | 19 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } |
| 19 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | 20 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } |
| 20 | 21 | ||
| 21 | defmt = "0.3" | 22 | defmt = "1.0.1" |
| 22 | defmt-rtt = "0.4" | 23 | defmt-rtt = "1.0.0" |
| 23 | 24 | ||
| 24 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 25 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 25 | cortex-m-rt = "0.7.0" | 26 | cortex-m-rt = "0.7.0" |
| @@ -27,13 +28,17 @@ embedded-hal = "0.2.6" | |||
| 27 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 28 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 28 | embedded-hal-async = { version = "1.0" } | 29 | embedded-hal-async = { version = "1.0" } |
| 29 | embedded-hal-bus = { version = "0.1", features = ["async"] } | 30 | embedded-hal-bus = { version = "0.1", features = ["async"] } |
| 30 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 31 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 31 | heapless = { version = "0.8", default-features = false } | 32 | heapless = { version = "0.8", default-features = false } |
| 32 | chrono = { version = "^0.4", default-features = false } | 33 | chrono = { version = "^0.4", default-features = false } |
| 33 | rand = { version = "0.8.5", default-features = false } | ||
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | 35 | ||
| 36 | micromath = "2.0.0" | 36 | micromath = "2.0.0" |
| 37 | 37 | ||
| 38 | [profile.release] | 38 | [profile.release] |
| 39 | debug = 2 | 39 | debug = 2 |
| 40 | |||
| 41 | [package.metadata.embassy] | ||
| 42 | build = [ | ||
| 43 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l4" } | ||
| 44 | ] | ||
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index cde24f411..44edec728 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs | |||
| @@ -24,8 +24,8 @@ async fn main(spawner: Spawner) { | |||
| 24 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) | 24 | // Obtain two independent channels (p.DAC1 can only be consumed once, though!) |
| 25 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); | 25 | let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); |
| 26 | 26 | ||
| 27 | spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); | 27 | spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap()); |
| 28 | spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); | 28 | spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap()); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | #[embassy_executor::task] | 31 | #[embassy_executor::task] |
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs index 2861bc091..3c42ba8f5 100644 --- a/examples/stm32l4/src/bin/i2c.rs +++ b/examples/stm32l4/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::I2c; | 6 | use embassy_stm32::i2c::I2c; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 8 | ||
| 10 | const ADDRESS: u8 = 0x5F; | 9 | const ADDRESS: u8 = 0x5F; |
| @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; | |||
| 13 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 13 | async fn main(_spawner: Spawner) { |
| 15 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 16 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); | 15 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); |
| 17 | 16 | ||
| 18 | let mut data = [0u8; 1]; | 17 | let mut data = [0u8; 1]; |
| 19 | unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); | 18 | unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); |
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs index a014b23e0..62153bfc8 100644 --- a/examples/stm32l4/src/bin/i2c_blocking_async.rs +++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs | |||
| @@ -5,7 +5,6 @@ use defmt::*; | |||
| 5 | use embassy_embedded_hal::adapter::BlockingAsync; | 5 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::i2c::I2c; | 7 | use embassy_stm32::i2c::I2c; |
| 8 | use embassy_stm32::time::Hertz; | ||
| 9 | use embedded_hal_async::i2c::I2c as I2cTrait; | 8 | use embedded_hal_async::i2c::I2c as I2cTrait; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 10 | ||
| @@ -15,7 +14,7 @@ const WHOAMI: u8 = 0x0F; | |||
| 15 | #[embassy_executor::main] | 14 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 15 | async fn main(_spawner: Spawner) { |
| 17 | let p = embassy_stm32::init(Default::default()); | 16 | let p = embassy_stm32::init(Default::default()); |
| 18 | let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); | 17 | let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); |
| 19 | let mut i2c = BlockingAsync::new(i2c); | 18 | let mut i2c = BlockingAsync::new(i2c); |
| 20 | 19 | ||
| 21 | let mut data = [0u8; 1]; | 20 | let mut data = [0u8; 1]; |
diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs index 794972a33..0f5690e37 100644 --- a/examples/stm32l4/src/bin/i2c_dma.rs +++ b/examples/stm32l4/src/bin/i2c_dma.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::I2c; | 6 | use embassy_stm32::i2c::I2c; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | 7 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 9 | ||
| @@ -19,16 +18,7 @@ bind_interrupts!(struct Irqs { | |||
| 19 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 20 | async fn main(_spawner: Spawner) { | 19 | async fn main(_spawner: Spawner) { |
| 21 | let p = embassy_stm32::init(Default::default()); | 20 | let p = embassy_stm32::init(Default::default()); |
| 22 | let mut i2c = I2c::new( | 21 | let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); |
| 23 | p.I2C2, | ||
| 24 | p.PB10, | ||
| 25 | p.PB11, | ||
| 26 | Irqs, | ||
| 27 | p.DMA1_CH4, | ||
| 28 | p.DMA1_CH5, | ||
| 29 | Hertz(100_000), | ||
| 30 | Default::default(), | ||
| 31 | ); | ||
| 32 | 22 | ||
| 33 | let mut data = [0u8; 1]; | 23 | let mut data = [0u8; 1]; |
| 34 | unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); | 24 | unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 4a7c01f9f..24efe526f 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -38,7 +38,6 @@ use embedded_io::Write as bWrite; | |||
| 38 | use embedded_io_async::Write; | 38 | use embedded_io_async::Write; |
| 39 | use heapless::Vec; | 39 | use heapless::Vec; |
| 40 | use panic_probe as _; | 40 | use panic_probe as _; |
| 41 | use rand::RngCore; | ||
| 42 | use static_cell::StaticCell; | 41 | use static_cell::StaticCell; |
| 43 | 42 | ||
| 44 | bind_interrupts!(struct Irqs { | 43 | bind_interrupts!(struct Irqs { |
| @@ -60,7 +59,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; | |||
| 60 | pub type SpeInt = exti::ExtiInput<'static>; | 59 | pub type SpeInt = exti::ExtiInput<'static>; |
| 61 | pub type SpeRst = Output<'static>; | 60 | pub type SpeRst = Output<'static>; |
| 62 | pub type Adin1110T = ADIN1110<SpeSpiCs>; | 61 | pub type Adin1110T = ADIN1110<SpeSpiCs>; |
| 63 | pub type TempSensI2c = I2c<'static, Async>; | 62 | pub type TempSensI2c = I2c<'static, Async, i2c::Master>; |
| 64 | 63 | ||
| 65 | static TEMP: AtomicI32 = AtomicI32::new(0); | 64 | static TEMP: AtomicI32 = AtomicI32::new(0); |
| 66 | 65 | ||
| @@ -116,7 +115,6 @@ async fn main(spawner: Spawner) { | |||
| 116 | Irqs, | 115 | Irqs, |
| 117 | dp.DMA1_CH6, | 116 | dp.DMA1_CH6, |
| 118 | dp.DMA1_CH7, | 117 | dp.DMA1_CH7, |
| 119 | Hertz(100_000), | ||
| 120 | I2C_Config::default(), | 118 | I2C_Config::default(), |
| 121 | ); | 119 | ); |
| 122 | 120 | ||
| @@ -183,11 +181,11 @@ async fn main(spawner: Spawner) { | |||
| 183 | .await; | 181 | .await; |
| 184 | 182 | ||
| 185 | // Start task blink_led | 183 | // Start task blink_led |
| 186 | unwrap!(spawner.spawn(heartbeat_led(led_uc3_yellow))); | 184 | spawner.spawn(unwrap!(heartbeat_led(led_uc3_yellow))); |
| 187 | // Start task temperature measurement | 185 | // Start task temperature measurement |
| 188 | unwrap!(spawner.spawn(temp_task(temp_sens_i2c, led_uc4_blue))); | 186 | spawner.spawn(unwrap!(temp_task(temp_sens_i2c, led_uc4_blue))); |
| 189 | // Start ethernet task | 187 | // Start ethernet task |
| 190 | unwrap!(spawner.spawn(ethernet_task(runner))); | 188 | spawner.spawn(unwrap!(ethernet_task(runner))); |
| 191 | 189 | ||
| 192 | let mut rng = Rng::new(dp.RNG, Irqs); | 190 | let mut rng = Rng::new(dp.RNG, Irqs); |
| 193 | // Generate random seed | 191 | // Generate random seed |
| @@ -210,7 +208,7 @@ async fn main(spawner: Spawner) { | |||
| 210 | let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed); | 208 | let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed); |
| 211 | 209 | ||
| 212 | // Launch network task | 210 | // Launch network task |
| 213 | unwrap!(spawner.spawn(net_task(runner))); | 211 | spawner.spawn(unwrap!(net_task(runner))); |
| 214 | 212 | ||
| 215 | let cfg = wait_for_config(stack).await; | 213 | let cfg = wait_for_config(stack).await; |
| 216 | let local_addr = cfg.address.address(); | 214 | let local_addr = cfg.address.address(); |
diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index e155b3e66..f173c651e 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml | |||
| @@ -1,17 +1,18 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2021" |
| 3 | name = "embassy-stm32l4-examples" | 3 | name = "embassy-stm32l432-examples" |
| 4 | version = "0.1.1" | 4 | version = "0.1.1" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32l4s5vi to your chip name, if necessary. | 9 | # Change stm32l4s5vi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ "defmt" ] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ "defmt" ] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } |
| 13 | defmt = "0.3" | 14 | defmt = "1.0.1" |
| 14 | defmt-rtt = "0.4" | 15 | defmt-rtt = "1.0.0" |
| 15 | 16 | ||
| 16 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 17 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 17 | cortex-m-rt = "0.7.0" | 18 | cortex-m-rt = "0.7.0" |
| @@ -19,7 +20,7 @@ embedded-hal = "0.2.6" | |||
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 20 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 20 | embedded-hal-async = { version = "1.0" } | 21 | embedded-hal-async = { version = "1.0" } |
| 21 | embedded-hal-bus = { version = "0.1", features = ["async"] } | 22 | embedded-hal-bus = { version = "0.1", features = ["async"] } |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | 24 | ||
| 24 | [profile.release] | 25 | [profile.release] |
| 25 | debug = 2 | 26 | debug = 2 |
| @@ -28,3 +29,8 @@ debug = 2 | |||
| 28 | name = "qspi_mmap" | 29 | name = "qspi_mmap" |
| 29 | path = "src/bin/qspi_mmap.rs" | 30 | path = "src/bin/qspi_mmap.rs" |
| 30 | test = false | 31 | test = false |
| 32 | |||
| 33 | [package.metadata.embassy] | ||
| 34 | build = [ | ||
| 35 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l432" } | ||
| 36 | ] | ||
diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs index 86a20eb3d..feabdd532 100644 --- a/examples/stm32l432/src/bin/qspi_mmap.rs +++ b/examples/stm32l432/src/bin/qspi_mmap.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | use defmt::info; | 7 | use defmt::info; |
| 8 | use embassy_stm32::mode; | 8 | use embassy_stm32::mode; |
| 9 | use embassy_stm32::qspi::enums::{ | 9 | use embassy_stm32::qspi::enums::{ |
| 10 | AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, | 10 | AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, SampleShifting, |
| 11 | }; | 11 | }; |
| 12 | use embassy_stm32::qspi::{self, Instance, TransferConfig}; | 12 | use embassy_stm32::qspi::{self, Instance, TransferConfig}; |
| 13 | pub struct FlashMemory<I: Instance> { | 13 | pub struct FlashMemory<I: Instance> { |
| @@ -246,13 +246,14 @@ const MEMORY_ADDR: u32 = 0x00000000 as u32; | |||
| 246 | async fn main(_spawner: Spawner) { | 246 | async fn main(_spawner: Spawner) { |
| 247 | let p = embassy_stm32::init(Default::default()); | 247 | let p = embassy_stm32::init(Default::default()); |
| 248 | 248 | ||
| 249 | let config = qspi::Config { | 249 | let mut config = qspi::Config::default(); |
| 250 | memory_size: MemorySize::_16MiB, | 250 | config.memory_size = MemorySize::_16MiB; |
| 251 | address_size: AddressSize::_24bit, | 251 | config.address_size = AddressSize::_24bit; |
| 252 | prescaler: 200, | 252 | config.prescaler = 200; |
| 253 | cs_high_time: ChipSelectHighTime::_1Cycle, | 253 | config.cs_high_time = ChipSelectHighTime::_1Cycle; |
| 254 | fifo_threshold: FIFOThresholdLevel::_16Bytes, | 254 | config.fifo_threshold = FIFOThresholdLevel::_16Bytes; |
| 255 | }; | 255 | config.sample_shifting = SampleShifting::None; |
| 256 | |||
| 256 | let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); | 257 | let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); |
| 257 | let mut flash = FlashMemory::new(driver); | 258 | let mut flash = FlashMemory::new(driver); |
| 258 | let mut wr_buf = [0u8; 256]; | 259 | let mut wr_buf = [0u8; 256]; |
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 4c372a554..9999300b8 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml | |||
| @@ -3,27 +3,27 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32l5-examples" | 3 | name = "embassy-stm32l5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32l552ze to your chip name, if necessary. | 9 | # Change stm32l552ze to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 16 | usbd-hid = "0.8.1" | 17 | usbd-hid = "0.8.1" |
| 17 | 18 | ||
| 18 | defmt = "0.3" | 19 | defmt = "1.0.1" |
| 19 | defmt-rtt = "0.4" | 20 | defmt-rtt = "1.0.0" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | 22 | ||
| 22 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 23 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 23 | cortex-m-rt = "0.7.0" | 24 | cortex-m-rt = "0.7.0" |
| 24 | embedded-hal = "0.2.6" | 25 | embedded-hal = "0.2.6" |
| 25 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 26 | rand_core = { version = "0.6.3", default-features = false } | ||
| 27 | embedded-io-async = { version = "0.6.1" } | 27 | embedded-io-async = { version = "0.6.1" } |
| 28 | static_cell = "2" | 28 | static_cell = "2" |
| 29 | 29 | ||
| @@ -33,3 +33,8 @@ debug = 2 | |||
| 33 | [[bin]] | 33 | [[bin]] |
| 34 | name = "stop" | 34 | name = "stop" |
| 35 | default-features = ["embassy-stm32/low-power"] | 35 | default-features = ["embassy-stm32/low-power"] |
| 36 | |||
| 37 | [package.metadata.embassy] | ||
| 38 | build = [ | ||
| 39 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32l5" } | ||
| 40 | ] | ||
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs index d7a1efea9..c34053190 100644 --- a/examples/stm32l5/src/bin/stop.rs +++ b/examples/stm32l5/src/bin/stop.rs | |||
| @@ -15,7 +15,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 15 | #[cortex_m_rt::entry] | 15 | #[cortex_m_rt::entry] |
| 16 | fn main() -> ! { | 16 | fn main() -> ! { |
| 17 | Executor::take().run(|spawner| { | 17 | Executor::take().run(|spawner| { |
| 18 | unwrap!(spawner.spawn(async_main(spawner))); | 18 | spawner.spawn(unwrap!(async_main(spawner))); |
| 19 | }) | 19 | }) |
| 20 | } | 20 | } |
| 21 | 21 | ||
| @@ -34,8 +34,8 @@ async fn async_main(spawner: Spawner) { | |||
| 34 | let rtc = RTC.init(rtc); | 34 | let rtc = RTC.init(rtc); |
| 35 | embassy_stm32::low_power::stop_with_rtc(rtc); | 35 | embassy_stm32::low_power::stop_with_rtc(rtc); |
| 36 | 36 | ||
| 37 | unwrap!(spawner.spawn(blinky(p.PC7.into()))); | 37 | spawner.spawn(unwrap!(blinky(p.PC7.into()))); |
| 38 | unwrap!(spawner.spawn(timeout())); | 38 | spawner.spawn(unwrap!(timeout())); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #[embassy_executor::task] | 41 | #[embassy_executor::task] |
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 809ec6ab1..25aa9ef69 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -12,7 +12,6 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState | |||
| 12 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 12 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 13 | use embassy_usb::{Builder, UsbDevice}; | 13 | use embassy_usb::{Builder, UsbDevice}; |
| 14 | use embedded_io_async::Write; | 14 | use embedded_io_async::Write; |
| 15 | use rand_core::RngCore; | ||
| 16 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 17 | ||
| @@ -97,11 +96,11 @@ async fn main(spawner: Spawner) { | |||
| 97 | // Build the builder. | 96 | // Build the builder. |
| 98 | let usb = builder.build(); | 97 | let usb = builder.build(); |
| 99 | 98 | ||
| 100 | unwrap!(spawner.spawn(usb_task(usb))); | 99 | spawner.spawn(unwrap!(usb_task(usb))); |
| 101 | 100 | ||
| 102 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); | 101 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); |
| 103 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); | 102 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); |
| 104 | unwrap!(spawner.spawn(usb_ncm_task(runner))); | 103 | spawner.spawn(unwrap!(usb_ncm_task(runner))); |
| 105 | 104 | ||
| 106 | let config = embassy_net::Config::dhcpv4(Default::default()); | 105 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 107 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 106 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
| @@ -118,7 +117,7 @@ async fn main(spawner: Spawner) { | |||
| 118 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 117 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 119 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); | 118 | let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); |
| 120 | 119 | ||
| 121 | unwrap!(spawner.spawn(net_task(runner))); | 120 | spawner.spawn(unwrap!(net_task(runner))); |
| 122 | 121 | ||
| 123 | // And now we can use it! | 122 | // And now we can use it! |
| 124 | 123 | ||
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index efcb9bf4d..9318414a5 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32u0-examples" | 3 | name = "embassy-stm32u0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32u083rc to your chip name, if necessary. | 9 | # Change stm32u083rc to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | 25 | ||
| 25 | micromath = "2.0.0" | 26 | micromath = "2.0.0" |
| @@ -27,3 +28,8 @@ chrono = { version = "0.4.38", default-features = false } | |||
| 27 | 28 | ||
| 28 | [profile.release] | 29 | [profile.release] |
| 29 | debug = 2 | 30 | debug = 2 |
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32u0" } | ||
| 35 | ] | ||
diff --git a/examples/stm32u0/src/bin/i2c.rs b/examples/stm32u0/src/bin/i2c.rs index 2861bc091..3c42ba8f5 100644 --- a/examples/stm32u0/src/bin/i2c.rs +++ b/examples/stm32u0/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::I2c; | 6 | use embassy_stm32::i2c::I2c; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 8 | ||
| 10 | const ADDRESS: u8 = 0x5F; | 9 | const ADDRESS: u8 = 0x5F; |
| @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; | |||
| 13 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 13 | async fn main(_spawner: Spawner) { |
| 15 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 16 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); | 15 | let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); |
| 17 | 16 | ||
| 18 | let mut data = [0u8; 1]; | 17 | let mut data = [0u8; 1]; |
| 19 | unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); | 18 | unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); |
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 886c5cb2e..f2ffe52c5 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32u5-examples" | 3 | name = "embassy-stm32u5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32u5g9zj to your chip name, if necessary. | 9 | # Change stm32u5g9zj to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | embedded-graphics = { version = "0.8.1" } | 25 | embedded-graphics = { version = "0.8.1" } |
| 25 | tinybmp = { version = "0.6.0" } | 26 | tinybmp = { version = "0.6.0" } |
| @@ -32,3 +33,8 @@ trustzone-secure = ["embassy-stm32/trustzone-secure"] | |||
| 32 | 33 | ||
| 33 | [profile.release] | 34 | [profile.release] |
| 34 | debug = 2 | 35 | debug = 2 |
| 36 | |||
| 37 | [package.metadata.embassy] | ||
| 38 | build = [ | ||
| 39 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32u5" } | ||
| 40 | ] | ||
diff --git a/examples/stm32u5/src/bin/i2c.rs b/examples/stm32u5/src/bin/i2c.rs index d5f5d6f60..5577f7211 100644 --- a/examples/stm32u5/src/bin/i2c.rs +++ b/examples/stm32u5/src/bin/i2c.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::{info, unwrap}; | 4 | use defmt::{info, unwrap}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::i2c::I2c; | 6 | use embassy_stm32::i2c::I2c; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 8 | ||
| 10 | const HTS221_ADDRESS: u8 = 0x5F; | 9 | const HTS221_ADDRESS: u8 = 0x5F; |
| @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; | |||
| 13 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 13 | async fn main(_spawner: Spawner) { |
| 15 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 16 | let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Hertz(100_000), Default::default()); | 15 | let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Default::default()); |
| 17 | 16 | ||
| 18 | let mut data = [0u8; 1]; | 17 | let mut data = [0u8; 1]; |
| 19 | unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data)); | 18 | unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data)); |
diff --git a/examples/stm32u5/src/bin/ltdc.rs b/examples/stm32u5/src/bin/ltdc.rs index bd59a9148..46d1c120f 100644 --- a/examples/stm32u5/src/bin/ltdc.rs +++ b/examples/stm32u5/src/bin/ltdc.rs | |||
| @@ -50,7 +50,7 @@ async fn main(spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | // blink the led on another task | 51 | // blink the led on another task |
| 52 | let led = Output::new(p.PD2, Level::High, Speed::Low); | 52 | let led = Output::new(p.PD2, Level::High, Speed::Low); |
| 53 | unwrap!(spawner.spawn(led_task(led))); | 53 | spawner.spawn(unwrap!(led_task(led))); |
| 54 | 54 | ||
| 55 | // numbers from STM32U5G9J-DK2.ioc | 55 | // numbers from STM32U5G9J-DK2.ioc |
| 56 | const RK050HR18H_HSYNC: u16 = 5; // Horizontal synchronization | 56 | const RK050HR18H_HSYNC: u16 = 5; // Horizontal synchronization |
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 96f66f3af..7ab13c290 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -3,23 +3,24 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32wb-examples" | 3 | name = "embassy-stm32wb-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32wb55rg to your chip name in both dependencies, if necessary. | 9 | # Change stm32wb55rg to your chip name in both dependencies, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } |
| 10 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } | 11 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } |
| 11 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 13 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 14 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } |
| 15 | 16 | ||
| 16 | defmt = "0.3" | 17 | defmt = "1.0.1" |
| 17 | defmt-rtt = "0.4" | 18 | defmt-rtt = "1.0.0" |
| 18 | 19 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 22 | embedded-hal = "1.0.0" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | static_cell = "2" | 25 | static_cell = "2" |
| 25 | 26 | ||
| @@ -54,3 +55,8 @@ required-features = ["ble"] | |||
| 54 | 55 | ||
| 55 | [profile.release] | 56 | [profile.release] |
| 56 | debug = 2 | 57 | debug = 2 |
| 58 | |||
| 59 | [package.metadata.embassy] | ||
| 60 | build = [ | ||
| 61 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wb" } | ||
| 62 | ] | ||
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 041dc0cf5..5d927bc00 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs | |||
| @@ -27,6 +27,7 @@ use embassy_stm32_wpan::hci::vendor::event::{self, AttributeHandle, VendorEvent} | |||
| 27 | use embassy_stm32_wpan::hci::{BdAddr, Event}; | 27 | use embassy_stm32_wpan::hci::{BdAddr, Event}; |
| 28 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; | 28 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; |
| 29 | use embassy_stm32_wpan::sub::ble::Ble; | 29 | use embassy_stm32_wpan::sub::ble::Ble; |
| 30 | use embassy_stm32_wpan::sub::mm; | ||
| 30 | use embassy_stm32_wpan::TlMbox; | 31 | use embassy_stm32_wpan::TlMbox; |
| 31 | use {defmt_rtt as _, panic_probe as _}; | 32 | use {defmt_rtt as _, panic_probe as _}; |
| 32 | 33 | ||
| @@ -38,7 +39,7 @@ bind_interrupts!(struct Irqs{ | |||
| 38 | const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; | 39 | const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; |
| 39 | 40 | ||
| 40 | #[embassy_executor::main] | 41 | #[embassy_executor::main] |
| 41 | async fn main(_spawner: Spawner) { | 42 | async fn main(spawner: Spawner) { |
| 42 | /* | 43 | /* |
| 43 | How to make this work: | 44 | How to make this work: |
| 44 | 45 | ||
| @@ -70,6 +71,7 @@ async fn main(_spawner: Spawner) { | |||
| 70 | let config = Config::default(); | 71 | let config = Config::default(); |
| 71 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); | 72 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 72 | 73 | ||
| 74 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | ||
| 73 | let sys_event = mbox.sys_subsystem.read().await; | 75 | let sys_event = mbox.sys_subsystem.read().await; |
| 74 | info!("sys event: {}", sys_event.payload()); | 76 | info!("sys event: {}", sys_event.payload()); |
| 75 | 77 | ||
| @@ -221,6 +223,11 @@ async fn main(_spawner: Spawner) { | |||
| 221 | } | 223 | } |
| 222 | } | 224 | } |
| 223 | 225 | ||
| 226 | #[embassy_executor::task] | ||
| 227 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 228 | memory_manager.run_queue().await; | ||
| 229 | } | ||
| 230 | |||
| 224 | fn get_bd_addr() -> BdAddr { | 231 | fn get_bd_addr() -> BdAddr { |
| 225 | let mut bytes = [0u8; 6]; | 232 | let mut bytes = [0u8; 6]; |
| 226 | 233 | ||
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index d139aa61b..ede6cf4b9 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs | |||
| @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) { | |||
| 56 | let config = Config::default(); | 56 | let config = Config::default(); |
| 57 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 57 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 58 | 58 | ||
| 59 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | 59 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 60 | 60 | ||
| 61 | let sys_event = mbox.sys_subsystem.read().await; | 61 | let sys_event = mbox.sys_subsystem.read().await; |
| 62 | info!("sys event: {}", sys_event.payload()); | 62 | info!("sys event: {}", sys_event.payload()); |
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 6a97daf4d..cc3b21e2e 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs | |||
| @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { | |||
| 62 | let config = Config::default(); | 62 | let config = Config::default(); |
| 63 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 63 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 64 | 64 | ||
| 65 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | 65 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 66 | 66 | ||
| 67 | let sys_event = mbox.sys_subsystem.read().await; | 67 | let sys_event = mbox.sys_subsystem.read().await; |
| 68 | info!("sys event: {}", sys_event.payload()); | 68 | info!("sys event: {}", sys_event.payload()); |
| @@ -168,7 +168,7 @@ async fn main(spawner: Spawner) { | |||
| 168 | static RUNNER: StaticCell<Runner> = StaticCell::new(); | 168 | static RUNNER: StaticCell<Runner> = StaticCell::new(); |
| 169 | let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); | 169 | let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); |
| 170 | 170 | ||
| 171 | spawner.spawn(run_mac(runner)).unwrap(); | 171 | spawner.spawn(run_mac(runner).unwrap()); |
| 172 | 172 | ||
| 173 | let (driver, control) = mac::new(runner).await; | 173 | let (driver, control) = mac::new(runner).await; |
| 174 | 174 | ||
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 9062bdcd2..d872104a8 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs | |||
| @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) { | |||
| 58 | let config = Config::default(); | 58 | let config = Config::default(); |
| 59 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 59 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 60 | 60 | ||
| 61 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | 61 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 62 | 62 | ||
| 63 | let sys_event = mbox.sys_subsystem.read().await; | 63 | let sys_event = mbox.sys_subsystem.read().await; |
| 64 | info!("sys event: {}", sys_event.payload()); | 64 | info!("sys event: {}", sys_event.payload()); |
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 9224e626d..95c73872b 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs | |||
| @@ -53,7 +53,7 @@ async fn main(spawner: Spawner) { | |||
| 53 | let config = Config::default(); | 53 | let config = Config::default(); |
| 54 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 54 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 55 | 55 | ||
| 56 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | 56 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 57 | 57 | ||
| 58 | let sys_event = mbox.sys_subsystem.read().await; | 58 | let sys_event = mbox.sys_subsystem.read().await; |
| 59 | info!("sys event: {}", sys_event.payload()); | 59 | info!("sys event: {}", sys_event.payload()); |
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 60b09adb4..e1196614a 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml | |||
| @@ -3,23 +3,29 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32wba-examples" | 3 | name = "embassy-stm32wba-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } | 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } |
| 9 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 11 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 12 | embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } | 13 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } |
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "1.0.1" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "1.0.0" |
| 16 | 17 | ||
| 17 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 18 | cortex-m-rt = "0.7.0" | 19 | cortex-m-rt = "0.7.0" |
| 19 | embedded-hal = "0.2.6" | 20 | embedded-hal = "1.0.0" |
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 21 | heapless = { version = "0.8", default-features = false } | 22 | heapless = { version = "0.8", default-features = false } |
| 22 | static_cell = "2" | 23 | static_cell = "2" |
| 23 | 24 | ||
| 24 | [profile.release] | 25 | [profile.release] |
| 25 | debug = 2 | 26 | debug = 2 |
| 27 | |||
| 28 | [package.metadata.embassy] | ||
| 29 | build = [ | ||
| 30 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba" } | ||
| 31 | ] | ||
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs new file mode 100644 index 000000000..a9651d57e --- /dev/null +++ b/examples/stm32wba/src/bin/adc.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_stm32::adc::{adc4, AdcChannel}; | ||
| 6 | use {defmt_rtt as _, panic_probe as _}; | ||
| 7 | |||
| 8 | #[embassy_executor::main] | ||
| 9 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 10 | let config = embassy_stm32::Config::default(); | ||
| 11 | |||
| 12 | let mut p = embassy_stm32::init(config); | ||
| 13 | |||
| 14 | // **** ADC4 init **** | ||
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | ||
| 16 | let mut adc4_pin1 = p.PA0; // A4 | ||
| 17 | let mut adc4_pin2 = p.PA1; // A5 | ||
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | ||
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | ||
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | ||
| 22 | |||
| 23 | // **** ADC4 blocking read **** | ||
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | ||
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | ||
| 26 | info!("Read adc4 pin 1 {}", volt); | ||
| 27 | |||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | ||
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | ||
| 30 | info!("Read adc4 pin 2 {}", volt); | ||
| 31 | |||
| 32 | // **** ADC4 async read **** | ||
| 33 | let mut degraded41 = adc4_pin1.degrade_adc(); | ||
| 34 | let mut degraded42 = adc4_pin2.degrade_adc(); | ||
| 35 | let mut measurements = [0u16; 2]; | ||
| 36 | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | ||
| 38 | adc4.read( | ||
| 39 | p.GPDMA1_CH1.reborrow(), | ||
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | ||
| 41 | &mut measurements, | ||
| 42 | ) | ||
| 43 | .await | ||
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | ||
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | ||
| 47 | info!("Async read 4 pin 1 {}", volt1); | ||
| 48 | info!("Async read 4 pin 2 {}", volt2); | ||
| 49 | } | ||
diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs new file mode 100644 index 000000000..de690fda0 --- /dev/null +++ b/examples/stm32wba/src/bin/pwm.rs | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use defmt_rtt as _; // global logger | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::gpio::OutputType; | ||
| 8 | use embassy_stm32::rcc::{ | ||
| 9 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 10 | }; | ||
| 11 | use embassy_stm32::time::khz; | ||
| 12 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | ||
| 13 | use embassy_stm32::Config; | ||
| 14 | use embassy_time::Timer; | ||
| 15 | use panic_probe as _; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | info!("Hello World!"); | ||
| 20 | |||
| 21 | let mut config = Config::default(); | ||
| 22 | // Fine-tune PLL1 dividers/multipliers | ||
| 23 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 24 | source: PllSource::HSI, | ||
| 25 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 26 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 27 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 28 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 29 | divq: None, | ||
| 30 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 31 | frac: Some(0), // Fractional part (enabled) | ||
| 32 | }); | ||
| 33 | |||
| 34 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 35 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 36 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 37 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 38 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 39 | |||
| 40 | // voltage scale for max performance | ||
| 41 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 42 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 43 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 44 | |||
| 45 | let p = embassy_stm32::init(config); | ||
| 46 | |||
| 47 | let ch1_pin = PwmPin::new(p.PB8, OutputType::PushPull); | ||
| 48 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); | ||
| 49 | let mut ch1 = pwm.ch1(); | ||
| 50 | ch1.enable(); | ||
| 51 | |||
| 52 | info!("PWM initialized"); | ||
| 53 | info!("PWM max duty {}", ch1.max_duty_cycle()); | ||
| 54 | |||
| 55 | loop { | ||
| 56 | ch1.set_duty_cycle_fully_off(); | ||
| 57 | Timer::after_millis(300).await; | ||
| 58 | ch1.set_duty_cycle_fraction(1, 4); | ||
| 59 | Timer::after_millis(300).await; | ||
| 60 | ch1.set_duty_cycle_fraction(1, 2); | ||
| 61 | Timer::after_millis(300).await; | ||
| 62 | ch1.set_duty_cycle(ch1.max_duty_cycle() - 1); | ||
| 63 | Timer::after_millis(300).await; | ||
| 64 | } | ||
| 65 | } | ||
diff --git a/examples/stm32wba6/.cargo/config.toml b/examples/stm32wba6/.cargo/config.toml new file mode 100644 index 000000000..1896068d8 --- /dev/null +++ b/examples/stm32wba6/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | runner = "probe-rs run --chip STM32WBA65RI" | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv8m.main-none-eabihf" | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml new file mode 100644 index 000000000..f98317846 --- /dev/null +++ b/examples/stm32wba6/Cargo.toml | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32wba6-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } | ||
| 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | ||
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 13 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | ||
| 14 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 15 | |||
| 16 | defmt = "1.0.1" | ||
| 17 | defmt-rtt = "1.0.0" | ||
| 18 | |||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 20 | cortex-m-rt = "0.7.0" | ||
| 21 | embedded-hal = "1.0.0" | ||
| 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 23 | heapless = { version = "0.8", default-features = false } | ||
| 24 | static_cell = "2" | ||
| 25 | |||
| 26 | [profile.release] | ||
| 27 | debug = 2 | ||
| 28 | |||
| 29 | [package.metadata.embassy] | ||
| 30 | build = [ | ||
| 31 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba6" } | ||
| 32 | ] | ||
diff --git a/examples/stm32wba6/build.rs b/examples/stm32wba6/build.rs new file mode 100644 index 000000000..8fc6faab8 --- /dev/null +++ b/examples/stm32wba6/build.rs | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | use std::error::Error; | ||
| 2 | |||
| 3 | fn main() -> Result<(), Box<dyn Error>> { | ||
| 4 | println!("cargo:rerun-if-changed=link.x"); | ||
| 5 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 6 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 7 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 8 | |||
| 9 | Ok(()) | ||
| 10 | } | ||
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs new file mode 100644 index 000000000..a9651d57e --- /dev/null +++ b/examples/stm32wba6/src/bin/adc.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_stm32::adc::{adc4, AdcChannel}; | ||
| 6 | use {defmt_rtt as _, panic_probe as _}; | ||
| 7 | |||
| 8 | #[embassy_executor::main] | ||
| 9 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 10 | let config = embassy_stm32::Config::default(); | ||
| 11 | |||
| 12 | let mut p = embassy_stm32::init(config); | ||
| 13 | |||
| 14 | // **** ADC4 init **** | ||
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | ||
| 16 | let mut adc4_pin1 = p.PA0; // A4 | ||
| 17 | let mut adc4_pin2 = p.PA1; // A5 | ||
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | ||
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | ||
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | ||
| 22 | |||
| 23 | // **** ADC4 blocking read **** | ||
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | ||
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | ||
| 26 | info!("Read adc4 pin 1 {}", volt); | ||
| 27 | |||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | ||
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | ||
| 30 | info!("Read adc4 pin 2 {}", volt); | ||
| 31 | |||
| 32 | // **** ADC4 async read **** | ||
| 33 | let mut degraded41 = adc4_pin1.degrade_adc(); | ||
| 34 | let mut degraded42 = adc4_pin2.degrade_adc(); | ||
| 35 | let mut measurements = [0u16; 2]; | ||
| 36 | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | ||
| 38 | adc4.read( | ||
| 39 | p.GPDMA1_CH1.reborrow(), | ||
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | ||
| 41 | &mut measurements, | ||
| 42 | ) | ||
| 43 | .await | ||
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | ||
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | ||
| 47 | info!("Async read 4 pin 1 {}", volt1); | ||
| 48 | info!("Async read 4 pin 2 {}", volt2); | ||
| 49 | } | ||
diff --git a/examples/stm32wba6/src/bin/blinky.rs b/examples/stm32wba6/src/bin/blinky.rs new file mode 100644 index 000000000..0d803b257 --- /dev/null +++ b/examples/stm32wba6/src/bin/blinky.rs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_stm32::init(Default::default()); | ||
| 13 | info!("Hello World!"); | ||
| 14 | |||
| 15 | let mut led = Output::new(p.PB4, Level::High, Speed::Low); | ||
| 16 | |||
| 17 | loop { | ||
| 18 | info!("high"); | ||
| 19 | led.set_high(); | ||
| 20 | Timer::after_millis(500).await; | ||
| 21 | |||
| 22 | info!("low"); | ||
| 23 | led.set_low(); | ||
| 24 | Timer::after_millis(500).await; | ||
| 25 | } | ||
| 26 | } | ||
diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs new file mode 100644 index 000000000..34a08bbc6 --- /dev/null +++ b/examples/stm32wba6/src/bin/button_exti.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::exti::ExtiInput; | ||
| 7 | use embassy_stm32::gpio::Pull; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_stm32::init(Default::default()); | ||
| 13 | info!("Hello World!"); | ||
| 14 | |||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | ||
| 16 | |||
| 17 | info!("Press the USER button..."); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | button.wait_for_falling_edge().await; | ||
| 21 | info!("Pressed!"); | ||
| 22 | button.wait_for_rising_edge().await; | ||
| 23 | info!("Released!"); | ||
| 24 | } | ||
| 25 | } | ||
diff --git a/examples/stm32wba6/src/bin/pwm.rs b/examples/stm32wba6/src/bin/pwm.rs new file mode 100644 index 000000000..2c696834a --- /dev/null +++ b/examples/stm32wba6/src/bin/pwm.rs | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use defmt_rtt as _; // global logger | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::gpio::OutputType; | ||
| 8 | use embassy_stm32::rcc::{ | ||
| 9 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 10 | }; | ||
| 11 | use embassy_stm32::time::khz; | ||
| 12 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | ||
| 13 | use embassy_stm32::Config; | ||
| 14 | use embassy_time::Timer; | ||
| 15 | use panic_probe as _; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | info!("Hello World!"); | ||
| 20 | |||
| 21 | let mut config = Config::default(); | ||
| 22 | // Fine-tune PLL1 dividers/multipliers | ||
| 23 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 24 | source: PllSource::HSI, | ||
| 25 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 26 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 27 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 28 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 29 | divq: None, | ||
| 30 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 31 | frac: Some(0), // Fractional part (enabled) | ||
| 32 | }); | ||
| 33 | |||
| 34 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 35 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 36 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 37 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 38 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 39 | |||
| 40 | // voltage scale for max performance | ||
| 41 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 42 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 43 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 44 | |||
| 45 | let p = embassy_stm32::init(config); | ||
| 46 | |||
| 47 | let ch1_pin = PwmPin::new(p.PA2, OutputType::PushPull); | ||
| 48 | let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); | ||
| 49 | let mut ch1 = pwm.ch1(); | ||
| 50 | ch1.enable(); | ||
| 51 | |||
| 52 | info!("PWM initialized"); | ||
| 53 | info!("PWM max duty {}", ch1.max_duty_cycle()); | ||
| 54 | |||
| 55 | loop { | ||
| 56 | ch1.set_duty_cycle_fully_off(); | ||
| 57 | Timer::after_millis(300).await; | ||
| 58 | ch1.set_duty_cycle_fraction(1, 4); | ||
| 59 | Timer::after_millis(300).await; | ||
| 60 | ch1.set_duty_cycle_fraction(1, 2); | ||
| 61 | Timer::after_millis(300).await; | ||
| 62 | ch1.set_duty_cycle(ch1.max_duty_cycle() - 1); | ||
| 63 | Timer::after_millis(300).await; | ||
| 64 | } | ||
| 65 | } | ||
diff --git a/examples/stm32wba6/src/bin/usb_hs_serial.rs b/examples/stm32wba6/src/bin/usb_hs_serial.rs new file mode 100644 index 000000000..20bdeaac3 --- /dev/null +++ b/examples/stm32wba6/src/bin/usb_hs_serial.rs | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{panic, *}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_futures::join::join; | ||
| 7 | use embassy_stm32::usb::{Driver, Instance}; | ||
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 10 | use embassy_usb::driver::EndpointError; | ||
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; | ||
| 16 | }); | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | info!("Hello World!"); | ||
| 21 | |||
| 22 | let mut config = Config::default(); | ||
| 23 | |||
| 24 | { | ||
| 25 | use embassy_stm32::rcc::*; | ||
| 26 | config.rcc.pll1 = Some(Pll { | ||
| 27 | source: PllSource::HSI, | ||
| 28 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 29 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 30 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 31 | divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz | ||
| 32 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) | ||
| 33 | frac: Some(0), // Fractional part (disabled) | ||
| 34 | }); | ||
| 35 | |||
| 36 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 37 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 38 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 39 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 40 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 41 | |||
| 42 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 43 | config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; | ||
| 44 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 45 | } | ||
| 46 | |||
| 47 | let p = embassy_stm32::init(config); | ||
| 48 | |||
| 49 | // Create the driver, from the HAL. | ||
| 50 | let mut ep_out_buffer = [0u8; 256]; | ||
| 51 | let mut config = embassy_stm32::usb::Config::default(); | ||
| 52 | // Do not enable vbus_detection. This is a safe default that works in all boards. | ||
| 53 | // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need | ||
| 54 | // to enable vbus_detection to comply with the USB spec. If you enable it, the board | ||
| 55 | // has to support it or USB won't work at all. See docs on `vbus_detection` for details. | ||
| 56 | config.vbus_detection = false; | ||
| 57 | let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); | ||
| 58 | |||
| 59 | // Create embassy-usb Config | ||
| 60 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); | ||
| 61 | config.manufacturer = Some("Embassy"); | ||
| 62 | config.product = Some("USB-serial example"); | ||
| 63 | config.serial_number = Some("12345678"); | ||
| 64 | |||
| 65 | // Create embassy-usb DeviceBuilder using the driver and config. | ||
| 66 | // It needs some buffers for building the descriptors. | ||
| 67 | let mut config_descriptor = [0; 256]; | ||
| 68 | let mut bos_descriptor = [0; 256]; | ||
| 69 | let mut control_buf = [0; 64]; | ||
| 70 | |||
| 71 | let mut state = State::new(); | ||
| 72 | |||
| 73 | let mut builder = Builder::new( | ||
| 74 | driver, | ||
| 75 | config, | ||
| 76 | &mut config_descriptor, | ||
| 77 | &mut bos_descriptor, | ||
| 78 | &mut [], // no msos descriptors | ||
| 79 | &mut control_buf, | ||
| 80 | ); | ||
| 81 | |||
| 82 | // Create classes on the builder. | ||
| 83 | let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); | ||
| 84 | |||
| 85 | // Build the builder. | ||
| 86 | let mut usb = builder.build(); | ||
| 87 | |||
| 88 | // Run the USB device. | ||
| 89 | let usb_fut = usb.run(); | ||
| 90 | |||
| 91 | // Do stuff with the class! | ||
| 92 | let echo_fut = async { | ||
| 93 | loop { | ||
| 94 | class.wait_connection().await; | ||
| 95 | info!("Connected"); | ||
| 96 | let _ = echo(&mut class).await; | ||
| 97 | info!("Disconnected"); | ||
| 98 | } | ||
| 99 | }; | ||
| 100 | |||
| 101 | // Run everything concurrently. | ||
| 102 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. | ||
| 103 | join(usb_fut, echo_fut).await; | ||
| 104 | } | ||
| 105 | |||
| 106 | struct Disconnected {} | ||
| 107 | |||
| 108 | impl From<EndpointError> for Disconnected { | ||
| 109 | fn from(val: EndpointError) -> Self { | ||
| 110 | match val { | ||
| 111 | EndpointError::BufferOverflow => panic!("Buffer overflow"), | ||
| 112 | EndpointError::Disabled => Disconnected {}, | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { | ||
| 118 | let mut buf = [0; 64]; | ||
| 119 | loop { | ||
| 120 | let n = class.read_packet(&mut buf).await?; | ||
| 121 | let data = &buf[..n]; | ||
| 122 | info!("data: {:x}", data); | ||
| 123 | class.write_packet(data).await?; | ||
| 124 | } | ||
| 125 | } | ||
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 6b677914e..825d25c0d 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml | |||
| @@ -3,25 +3,31 @@ edition = "2021" | |||
| 3 | name = "embassy-stm32wl-examples" | 3 | name = "embassy-stm32wl-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [dependencies] | 8 | [dependencies] |
| 8 | # Change stm32wl55jc-cm4 to your chip name, if necessary. | 9 | # Change stm32wl55jc-cm4 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } |
| 14 | 15 | ||
| 15 | defmt = "0.3" | 16 | defmt = "1.0.1" |
| 16 | defmt-rtt = "0.4" | 17 | defmt-rtt = "1.0.0" |
| 17 | 18 | ||
| 18 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 20 | embedded-hal = "0.2.6" | 21 | embedded-hal = "0.2.6" |
| 21 | embedded-storage = "0.3.1" | 22 | embedded-storage = "0.3.1" |
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 23 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 24 | chrono = { version = "^0.4", default-features = false } | 25 | chrono = { version = "^0.4", default-features = false } |
| 25 | 26 | ||
| 26 | [profile.release] | 27 | [profile.release] |
| 27 | debug = 2 | 28 | debug = 2 |
| 29 | |||
| 30 | [package.metadata.embassy] | ||
| 31 | build = [ | ||
| 32 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" } | ||
| 33 | ] | ||
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs new file mode 100644 index 000000000..118f02ae1 --- /dev/null +++ b/examples/stm32wl/src/bin/adc.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime}; | ||
| 9 | use embassy_stm32::SharedData; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) { | ||
| 17 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); | ||
| 18 | info!("Hello World!"); | ||
| 19 | |||
| 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); | ||
| 21 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 22 | let mut pin = p.PB2; | ||
| 23 | |||
| 24 | let mut vrefint = adc.enable_vrefint(); | ||
| 25 | let vrefint_sample = adc.blocking_read(&mut vrefint); | ||
| 26 | let convert_to_millivolts = |sample| { | ||
| 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | ||
| 28 | // 6.3.3 Embedded internal reference voltage | ||
| 29 | const VREFINT_MV: u32 = 1212; // mV | ||
| 30 | |||
| 31 | (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16 | ||
| 32 | }; | ||
| 33 | |||
| 34 | loop { | ||
| 35 | let v = adc.blocking_read(&mut pin); | ||
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | ||
| 37 | Timer::after_millis(100).await; | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 3a27f913c..e8897506c 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml | |||
| @@ -3,14 +3,15 @@ edition = "2021" | |||
| 3 | name = "embassy-wasm-example" | 3 | name = "embassy-wasm-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | ||
| 6 | 7 | ||
| 7 | [lib] | 8 | [lib] |
| 8 | crate-type = ["cdylib"] | 9 | crate-type = ["cdylib"] |
| 9 | 10 | ||
| 10 | [dependencies] | 11 | [dependencies] |
| 11 | embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] } |
| 12 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } |
| 13 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } | 14 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "wasm", ] } |
| 14 | 15 | ||
| 15 | wasm-logger = "0.2.0" | 16 | wasm-logger = "0.2.0" |
| 16 | wasm-bindgen = "0.2" | 17 | wasm-bindgen = "0.2" |
| @@ -19,3 +20,8 @@ log = "0.4.11" | |||
| 19 | 20 | ||
| 20 | [profile.release] | 21 | [profile.release] |
| 21 | debug = 2 | 22 | debug = 2 |
| 23 | |||
| 24 | [package.metadata.embassy] | ||
| 25 | build = [ | ||
| 26 | { target = "wasm32-unknown-unknown", artifact-dir = "out/examples/wasm" } | ||
| 27 | ] | ||
diff --git a/examples/wasm/src/lib.rs b/examples/wasm/src/lib.rs index 71cf980dd..170c97fb7 100644 --- a/examples/wasm/src/lib.rs +++ b/examples/wasm/src/lib.rs | |||
| @@ -24,5 +24,5 @@ async fn ticker() { | |||
| 24 | #[embassy_executor::main] | 24 | #[embassy_executor::main] |
| 25 | async fn main(spawner: Spawner) { | 25 | async fn main(spawner: Spawner) { |
| 26 | wasm_logger::init(wasm_logger::Config::default()); | 26 | wasm_logger::init(wasm_logger::Config::default()); |
| 27 | spawner.spawn(ticker()).unwrap(); | 27 | spawner.spawn(ticker().unwrap()); |
| 28 | } | 28 | } |
