diff options
| author | klownfish <[email protected]> | 2024-09-11 11:55:50 +0200 |
|---|---|---|
| committer | klownfish <[email protected]> | 2024-09-11 11:55:50 +0200 |
| commit | f0a86d1a344eac1528ce8653c573d1fe840b4083 (patch) | |
| tree | 426b03be0f9306261c8d12e75d58a1fcafcbf2e7 /examples | |
| parent | 0ba91ca555efc75dca603adbb51355c92b2fdb80 (diff) | |
| parent | 7648d42b7f23a2caad29ed6e16123b088ccdc8b5 (diff) | |
Merge branch 'main' of github.com:embassy-rs/embassy
Diffstat (limited to 'examples')
179 files changed, 9034 insertions, 322 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index dbbe0fddc..93e49faef 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml | |||
| @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [] } |
| 11 | embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } | 11 | embassy-nrf = { version = "0.2.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } |
| 12 | embassy-boot = { version = "0.2.0", path = "../../../../embassy-boot", features = [] } | 12 | embassy-boot = { version = "0.3.0", path = "../../../../embassy-boot", features = [] } |
| 13 | embassy-boot-nrf = { version = "0.2.0", path = "../../../../embassy-boot-nrf", features = [] } | 13 | embassy-boot-nrf = { version = "0.3.0", path = "../../../../embassy-boot-nrf", features = [] } |
| 14 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 15 | 15 | ||
| 16 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "0.3", optional = true } |
| 17 | defmt-rtt = { version = "0.4", optional = true } | 17 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index d4341e8f6..8bb8afdfe 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [] } |
| 11 | embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", ] } | 11 | embassy-rp = { version = "0.2.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } |
| 12 | embassy-boot-rp = { version = "0.2.0", path = "../../../../embassy-boot-rp", features = [] } | 12 | embassy-boot-rp = { version = "0.3.0", path = "../../../../embassy-boot-rp", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
| 16 | defmt-rtt = "0.4" | 16 | defmt-rtt = "0.4" |
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index c203ffc9f..1c2934298 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index ed13eab65..09e34c7df 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index f25e9815d..5e7f4d5e7 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index c1a47dfe4..60fdcfafb 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } | 11 | embassy-stm32 = { version = "0.1.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 = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 1e83d3113..fe3ab2c04 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index bca292681..169856358 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 0484e6ceb..7cef8fe0d 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml | |||
| @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../../../embassy-usb" } | 14 | embassy-usb = { version = "0.3.0", path = "../../../../embassy-usb" } |
| 15 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } | 15 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } |
| 16 | 16 | ||
| 17 | defmt = { version = "0.3", optional = true } | 17 | defmt = { version = "0.3", optional = true } |
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index b785a1968..860a835a9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml | |||
| @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } | 12 | embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 16 | defmt-rtt = { version = "0.4", optional = true } | 16 | defmt-rtt = { version = "0.4", optional = true } |
diff --git a/examples/boot/application/stm32wl/memory.x b/examples/boot/application/stm32wl/memory.x index e1d4e7fa8..20109e37e 100644 --- a/examples/boot/application/stm32wl/memory.x +++ b/examples/boot/application/stm32wl/memory.x | |||
| @@ -5,7 +5,8 @@ MEMORY | |||
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K |
| 6 | FLASH : ORIGIN = 0x08008000, LENGTH = 64K | 6 | FLASH : ORIGIN = 0x08008000, LENGTH = 64K |
| 7 | DFU : ORIGIN = 0x08018000, LENGTH = 68K | 7 | DFU : ORIGIN = 0x08018000, LENGTH = 68K |
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K | 8 | SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128 |
| 9 | RAM (rwx) : ORIGIN = 0x20000080, LENGTH = 32K - 128 | ||
| 9 | } | 10 | } |
| 10 | 11 | ||
| 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); | 12 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); |
| @@ -13,3 +14,11 @@ __bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - O | |||
| 13 | 14 | ||
| 14 | __bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER); | 15 | __bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER); |
| 15 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER); | 16 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER); |
| 17 | |||
| 18 | SECTIONS | ||
| 19 | { | ||
| 20 | .shared_data : | ||
| 21 | { | ||
| 22 | *(.shared_data) | ||
| 23 | } > SHARED_RAM | ||
| 24 | } | ||
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index 9f4f0b238..127de0237 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | #[cfg(feature = "defmt")] | 6 | #[cfg(feature = "defmt")] |
| 5 | use defmt_rtt::*; | 7 | use defmt_rtt::*; |
| 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 8 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| @@ -9,6 +11,7 @@ use embassy_executor::Spawner; | |||
| 9 | use embassy_stm32::exti::ExtiInput; | 11 | use embassy_stm32::exti::ExtiInput; |
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 12 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 13 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 14 | use embassy_stm32::SharedData; | ||
| 12 | use embassy_sync::mutex::Mutex; | 15 | use embassy_sync::mutex::Mutex; |
| 13 | use panic_reset as _; | 16 | use panic_reset as _; |
| 14 | 17 | ||
| @@ -17,9 +20,12 @@ static APP_B: &[u8] = &[0, 1, 2, 3]; | |||
| 17 | #[cfg(not(feature = "skip-include"))] | 20 | #[cfg(not(feature = "skip-include"))] |
| 18 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 21 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 19 | 22 | ||
| 23 | #[link_section = ".shared_data"] | ||
| 24 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 25 | |||
| 20 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 27 | async fn main(_spawner: Spawner) { |
| 22 | let p = embassy_stm32::init(Default::default()); | 28 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 23 | let flash = Flash::new_blocking(p.FLASH); | 29 | let flash = Flash::new_blocking(p.FLASH); |
| 24 | let flash = Mutex::new(BlockingAsync::new(flash)); | 30 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 25 | 31 | ||
diff --git a/examples/boot/application/stm32wl/src/bin/b.rs b/examples/boot/application/stm32wl/src/bin/b.rs index e954d8b91..768dadf8b 100644 --- a/examples/boot/application/stm32wl/src/bin/b.rs +++ b/examples/boot/application/stm32wl/src/bin/b.rs | |||
| @@ -1,16 +1,22 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | #[cfg(feature = "defmt")] | 6 | #[cfg(feature = "defmt")] |
| 5 | use defmt_rtt::*; | 7 | use defmt_rtt::*; |
| 6 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 9 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 10 | use embassy_stm32::SharedData; | ||
| 8 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 9 | use panic_reset as _; | 12 | use panic_reset as _; |
| 10 | 13 | ||
| 14 | #[link_section = ".shared_data"] | ||
| 15 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 16 | |||
| 11 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 18 | async fn main(_spawner: Spawner) { |
| 13 | let p = embassy_stm32::init(Default::default()); | 19 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 14 | let mut led = Output::new(p.PB15, Level::High, Speed::Low); | 20 | let mut led = Output::new(p.PB15, Level::High, Speed::Low); |
| 15 | 21 | ||
| 16 | loop { | 22 | loop { |
diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index c15c980ca..9df396e5e 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml | |||
| @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" | |||
| 9 | defmt = { version = "0.3", optional = true } | 9 | defmt = { version = "0.3", optional = true } |
| 10 | defmt-rtt = { version = "0.4", optional = true } | 10 | defmt-rtt = { version = "0.4", optional = true } |
| 11 | 11 | ||
| 12 | embassy-rp = { path = "../../../../embassy-rp", features = [] } | 12 | embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } |
| 13 | embassy-boot-rp = { path = "../../../../embassy-boot-rp" } | 13 | embassy-boot-rp = { path = "../../../../embassy-boot-rp" } |
| 14 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } | 14 | embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } |
| 15 | embassy-time = { path = "../../../../embassy-time", features = [] } | 15 | embassy-time = { path = "../../../../embassy-time", features = [] } |
diff --git a/examples/boot/bootloader/rp/memory.x b/examples/boot/bootloader/rp/memory.x index c3b54976e..88b5bbb15 100644 --- a/examples/boot/bootloader/rp/memory.x +++ b/examples/boot/bootloader/rp/memory.x | |||
| @@ -2,7 +2,7 @@ MEMORY | |||
| 2 | { | 2 | { |
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ |
| 4 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 | 4 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 |
| 5 | FLASH : ORIGIN = 0x10000100, LENGTH = 24K | 5 | FLASH : ORIGIN = 0x10000100, LENGTH = 24K - 0x100 |
| 6 | BOOTLOADER_STATE : ORIGIN = 0x10006000, LENGTH = 4K | 6 | BOOTLOADER_STATE : ORIGIN = 0x10006000, LENGTH = 4K |
| 7 | ACTIVE : ORIGIN = 0x10007000, LENGTH = 512K | 7 | ACTIVE : ORIGIN = 0x10007000, LENGTH = 512K |
| 8 | DFU : ORIGIN = 0x10087000, LENGTH = 516K | 8 | DFU : ORIGIN = 0x10087000, LENGTH = 516K |
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 9950ed7b6..050b672ce 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml | |||
| @@ -18,7 +18,7 @@ embedded-storage = "0.3.1" | |||
| 18 | embedded-storage-async = "0.4.0" | 18 | embedded-storage-async = "0.4.0" |
| 19 | cfg-if = "1.0.0" | 19 | cfg-if = "1.0.0" |
| 20 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } | 20 | embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } |
| 21 | embassy-usb = { version = "0.2.0", path = "../../../../embassy-usb", default-features = false } | 21 | embassy-usb = { version = "0.3.0", path = "../../../../embassy-usb", default-features = false } |
| 22 | embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } | 22 | embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } |
| 23 | 23 | ||
| 24 | [features] | 24 | [features] |
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 70a89bb30..98a678815 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml | |||
| @@ -16,9 +16,9 @@ log = [ | |||
| 16 | 16 | ||
| 17 | [dependencies] | 17 | [dependencies] |
| 18 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync" } | 18 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync" } |
| 19 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "integrated-timers"] } | 19 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "integrated-timers"] } |
| 20 | embassy-time = { version = "0.3.1", path = "../../embassy-time" } | 20 | embassy-time = { version = "0.3.2", path = "../../embassy-time" } |
| 21 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 21 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 22 | 22 | ||
| 23 | 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"] } |
| 24 | cortex-m-rt = "0.7.0" | 24 | cortex-m-rt = "0.7.0" |
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index c52256d8e..93a19bea7 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml | |||
| @@ -5,9 +5,9 @@ version = "0.1.0" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 8 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 9 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 9 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } | 10 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } |
| 11 | 11 | ||
| 12 | defmt = "0.3" | 12 | defmt = "0.3" |
| 13 | defmt-rtt = "0.4" | 13 | defmt-rtt = "0.4" |
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 2031b253f..0e3e81c3f 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml | |||
| @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 12 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
| 15 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 731cee843..7fae7aefc 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml | |||
| @@ -9,8 +9,8 @@ rtic = { version = "2", features = ["thumbv7-backend"] } | |||
| 9 | 9 | ||
| 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "generic-queue"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "generic-queue"] } |
| 13 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 13 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
| 16 | defmt-rtt = "0.4" | 16 | defmt-rtt = "0.4" |
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 000857821..17fa6234d 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml | |||
| @@ -7,11 +7,11 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 12 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | 15 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } |
| 16 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | 16 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } |
| 17 | embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } | 17 | embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } |
| @@ -27,7 +27,7 @@ cortex-m-rt = "0.7.0" | |||
| 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 28 | rand = { version = "0.8.4", default-features = false } | 28 | rand = { version = "0.8.4", default-features = false } |
| 29 | embedded-storage = "0.3.1" | 29 | embedded-storage = "0.3.1" |
| 30 | usbd-hid = "0.7.0" | 30 | usbd-hid = "0.8.1" |
| 31 | serde = { version = "1.0.136", default-features = false } | 31 | serde = { version = "1.0.136", default-features = false } |
| 32 | embedded-hal = { version = "1.0" } | 32 | embedded-hal = { version = "1.0" } |
| 33 | embedded-hal-async = { version = "1.0" } | 33 | embedded-hal-async = { version = "1.0" } |
diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs index 7fcea9dbd..e06ba1c73 100644 --- a/examples/nrf52840/src/bin/channel.rs +++ b/examples/nrf52840/src/bin/channel.rs | |||
| @@ -35,8 +35,8 @@ async fn main(spawner: Spawner) { | |||
| 35 | 35 | ||
| 36 | loop { | 36 | loop { |
| 37 | match CHANNEL.receive().await { | 37 | match CHANNEL.receive().await { |
| 38 | LedState::On => led.set_high(), | 38 | LedState::On => led.set_low(), |
| 39 | LedState::Off => led.set_low(), | 39 | LedState::Off => led.set_high(), |
| 40 | } | 40 | } |
| 41 | } | 41 | } |
| 42 | } | 42 | } |
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs index 3095a04ec..29f70f91c 100644 --- a/examples/nrf52840/src/bin/channel_sender_receiver.rs +++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs | |||
| @@ -33,8 +33,8 @@ async fn recv_task(led: AnyPin, receiver: Receiver<'static, NoopRawMutex, LedSta | |||
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | match receiver.receive().await { | 35 | match receiver.receive().await { |
| 36 | LedState::On => led.set_high(), | 36 | LedState::On => led.set_low(), |
| 37 | LedState::Off => led.set_low(), | 37 | LedState::Off => led.set_high(), |
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | } | 40 | } |
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs index 279f32edc..94cf09c88 100644 --- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs +++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs | |||
| @@ -66,16 +66,11 @@ async fn main(spawner: Spawner) { | |||
| 66 | let seed = u64::from_le_bytes(seed); | 66 | let seed = u64::from_le_bytes(seed); |
| 67 | 67 | ||
| 68 | // Init network stack | 68 | // Init network stack |
| 69 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 69 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 70 | static STACK: StaticCell< | 70 | static STACK: StaticCell< |
| 71 | Stack<Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>>, | 71 | Stack<Enc28j60<ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static>, Delay>, Output<'static>>>, |
| 72 | > = StaticCell::new(); | 72 | > = StaticCell::new(); |
| 73 | let stack = STACK.init(Stack::new( | 73 | let stack = STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 74 | device, | ||
| 75 | config, | ||
| 76 | RESOURCES.init(StackResources::<2>::new()), | ||
| 77 | seed, | ||
| 78 | )); | ||
| 79 | 74 | ||
| 80 | unwrap!(spawner.spawn(net_task(stack))); | 75 | unwrap!(spawner.spawn(net_task(stack))); |
| 81 | 76 | ||
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index a7e5c2668..e56b215e3 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs | |||
| @@ -115,7 +115,7 @@ async fn main(spawner: Spawner) { | |||
| 115 | let seed = u64::from_le_bytes(seed); | 115 | let seed = u64::from_le_bytes(seed); |
| 116 | 116 | ||
| 117 | // Init network stack | 117 | // Init network stack |
| 118 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 118 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 119 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | 119 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); |
| 120 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); | 120 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 121 | 121 | ||
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 00bd50081..a3b69a99b 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs | |||
| @@ -89,14 +89,9 @@ async fn main(spawner: Spawner) { | |||
| 89 | let seed = u64::from_le_bytes(seed); | 89 | let seed = u64::from_le_bytes(seed); |
| 90 | 90 | ||
| 91 | // Init network stack | 91 | // Init network stack |
| 92 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | static STACK: StaticCell<Stack<hosted::NetDriver<'static>>> = StaticCell::new(); | 93 | static STACK: StaticCell<Stack<hosted::NetDriver<'static>>> = StaticCell::new(); |
| 94 | let stack = &*STACK.init(Stack::new( | 94 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 95 | device, | ||
| 96 | config, | ||
| 97 | RESOURCES.init(StackResources::<2>::new()), | ||
| 98 | seed, | ||
| 99 | )); | ||
| 100 | 95 | ||
| 101 | unwrap!(spawner.spawn(net_task(stack))); | 96 | unwrap!(spawner.spawn(net_task(stack))); |
| 102 | 97 | ||
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 02f6190f0..0da85be07 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml | |||
| @@ -7,11 +7,11 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 8 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 12 | embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embedded-io-async = { version = "0.6.1" } | 15 | embedded-io-async = { version = "0.6.1" } |
| 16 | 16 | ||
| 17 | defmt = "0.3" | 17 | defmt = "0.3" |
| @@ -23,7 +23,7 @@ cortex-m-rt = "0.7.0" | |||
| 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 24 | rand = { version = "0.8.4", default-features = false } | 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.7.0" | 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] |
diff --git a/examples/nrf9151/ns/.cargo/config.toml b/examples/nrf9151/ns/.cargo/config.toml new file mode 100644 index 000000000..1444b0cd1 --- /dev/null +++ b/examples/nrf9151/ns/.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 nRF9160_xxAA" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv8m.main-none-eabihf" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "trace" | ||
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml new file mode 100644 index 000000000..17fe27b67 --- /dev/null +++ b/examples/nrf9151/ns/Cargo.toml | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-nrf9151-non-secure-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||
| 9 | embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||
| 10 | embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | ||
| 11 | |||
| 12 | defmt = "0.3" | ||
| 13 | defmt-rtt = "0.4" | ||
| 14 | |||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 16 | cortex-m-rt = "0.7.0" | ||
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 18 | |||
| 19 | [profile.release] | ||
| 20 | debug = 2 | ||
diff --git a/examples/nrf9151/ns/README.md b/examples/nrf9151/ns/README.md new file mode 100644 index 000000000..a3f81d24e --- /dev/null +++ b/examples/nrf9151/ns/README.md | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | You must flash the TFM before running any non-secure examples. The TFM | ||
| 2 | configures the secure and non-secure execution environments and then loads the | ||
| 3 | non-secure application. A reference TFM is included, and you can use the | ||
| 4 | provided helper script to flash it. | ||
diff --git a/examples/nrf9151/ns/build.rs b/examples/nrf9151/ns/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf9151/ns/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/nrf9151/ns/flash_tfm.sh b/examples/nrf9151/ns/flash_tfm.sh new file mode 100644 index 000000000..29e4e0ed5 --- /dev/null +++ b/examples/nrf9151/ns/flash_tfm.sh | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | nrfjprog --family NRF91 --recover | ||
| 2 | nrfjprog --family NRF91 --chiperase --verify --program tfm.hex | ||
diff --git a/examples/nrf9151/ns/memory.x b/examples/nrf9151/ns/memory.x new file mode 100644 index 000000000..8d7b66fcc --- /dev/null +++ b/examples/nrf9151/ns/memory.x | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* Trusted Firmware-M (TF-M) is flashed at the start */ | ||
| 4 | FLASH : ORIGIN = 0x00008000, LENGTH = 0xf8000 | ||
| 5 | RAM (rwx) : ORIGIN = 0x2000C568, LENGTH = 0x33a98 | ||
| 6 | } | ||
| 7 | |||
diff --git a/examples/nrf9151/ns/src/bin/blinky.rs b/examples/nrf9151/ns/src/bin/blinky.rs new file mode 100644 index 000000000..7457a95a3 --- /dev/null +++ b/examples/nrf9151/ns/src/bin/blinky.rs | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_nrf::init(Default::default()); | ||
| 12 | let mut led = Output::new(p.P0_00, Level::Low, OutputDrive::Standard); | ||
| 13 | |||
| 14 | loop { | ||
| 15 | led.set_high(); | ||
| 16 | defmt::info!("high"); | ||
| 17 | Timer::after_millis(500).await; | ||
| 18 | led.set_low(); | ||
| 19 | defmt::info!("low"); | ||
| 20 | Timer::after_millis(1000).await; | ||
| 21 | } | ||
| 22 | } | ||
diff --git a/examples/nrf9151/ns/src/bin/uart.rs b/examples/nrf9151/ns/src/bin/uart.rs new file mode 100644 index 000000000..2220dccfb --- /dev/null +++ b/examples/nrf9151/ns/src/bin/uart.rs | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | bind_interrupts!(struct Irqs { | ||
| 10 | SPIM0_SPIS0_TWIM0_TWIS0_UARTE0 => uarte::InterruptHandler<peripherals::SERIAL0>; | ||
| 11 | }); | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_nrf::init(Default::default()); | ||
| 16 | let mut config = uarte::Config::default(); | ||
| 17 | config.parity = uarte::Parity::EXCLUDED; | ||
| 18 | config.baudrate = uarte::Baudrate::BAUD115200; | ||
| 19 | |||
| 20 | let mut uart = uarte::Uarte::new(p.SERIAL0, Irqs, p.P0_26, p.P0_27, config); | ||
| 21 | |||
| 22 | info!("uarte initialized!"); | ||
| 23 | |||
| 24 | // Message must be in SRAM | ||
| 25 | let mut buf = [0; 8]; | ||
| 26 | buf.copy_from_slice(b"Hello!\r\n"); | ||
| 27 | |||
| 28 | unwrap!(uart.write(&buf).await); | ||
| 29 | info!("wrote hello in uart!"); | ||
| 30 | |||
| 31 | loop { | ||
| 32 | info!("reading..."); | ||
| 33 | unwrap!(uart.read(&mut buf).await); | ||
| 34 | info!("writing..."); | ||
| 35 | unwrap!(uart.write(&buf).await); | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/examples/nrf9151/ns/tfm.hex b/examples/nrf9151/ns/tfm.hex new file mode 100644 index 000000000..9864a1849 --- /dev/null +++ b/examples/nrf9151/ns/tfm.hex | |||
| @@ -0,0 +1,1543 @@ | |||
| 1 | :10000000F80B0020690600000D070000255A0000CB | ||
| 2 | :10001000455A0000655A0000A55A0000855A0000A4 | ||
| 3 | :100020000000000000000000000000001D2700008C | ||
| 4 | :100030000D070000000000000D0700000D07000084 | ||
| 5 | :10004000000000000000000000000000F13200008D | ||
| 6 | :10005000000000000D07000000000000000000008C | ||
| 7 | :100060000D0700000D0700000D0700000D07000040 | ||
| 8 | :10007000000000000D0700000D0700000D07000044 | ||
| 9 | :100080000D0700000D070000000000000000000048 | ||
| 10 | :100090000D0700000D070000000000000000000038 | ||
| 11 | :1000A0000D07000000000000000000000D07000028 | ||
| 12 | :1000B0000D0700000D0700000D0700000D070000F0 | ||
| 13 | :1000C0000D0700000D0700000D0700000D070000E0 | ||
| 14 | :1000D0000D070000000000000D07000000000000F8 | ||
| 15 | :1000E0000D070000000000000D07000000000000E8 | ||
| 16 | :1000F0000D070000000000000000000000000000EC | ||
| 17 | :10010000000000000D0700000000000000000000DB | ||
| 18 | :1001100000000000000000000000000000000000DF | ||
| 19 | :10012000000000000D0700000000000000000000BB | ||
| 20 | :1001300000000000000000000000000000000000BF | ||
| 21 | :100140000D07000000015F5F00000000FE0B0000D3 | ||
| 22 | :10015000F9270000800600000000000000000000F9 | ||
| 23 | :10016000000000000000000000000000401200201D | ||
| 24 | :100170000000000001015F5F030100001F0100009B | ||
| 25 | :1001800085040000000000000000000001000000E5 | ||
| 26 | :10019000010000000000000000000000000000005E | ||
| 27 | :1001A0000000000070000000CC5E00008000000035 | ||
| 28 | :1001B000000F000001000000D102000001015F5F9C | ||
| 29 | :1001C000040100001F010000F30500000000000012 | ||
| 30 | :1001D000000000000000000001000000000000001E | ||
| 31 | :1001E000000000000000000000000000D75E0000DA | ||
| 32 | :1001F000400000000507000001000000DF040000CF | ||
| 33 | :1002000038B50025054C29462046D4F80024C4F80A | ||
| 34 | :10021000045405F0B0FCC4F8005438BD200C002094 | ||
| 35 | :1002200013B511460022CDE9002242680346382A60 | ||
| 36 | :10023000046844D194F82820022A19D01AB900F091 | ||
| 37 | :1002400047F902B010BD21482468D0F80404013AEF | ||
| 38 | :10025000CDE90040082A35D8DFE802F0050A0E1380 | ||
| 39 | :10026000181D22272C006A46184600F02EF9E8E7F0 | ||
| 40 | :10027000184600F018F9E4E76A46184600F016F947 | ||
| 41 | :10028000DFE76A46184600F00BF9DAE76A461846D7 | ||
| 42 | :1002900000F00FF9D5E76A46184600F00DF9D0E7EF | ||
| 43 | :1002A0006A46184600F00BF9CBE76A46184600F09C | ||
| 44 | :1002B00009F9C6E76A46184600F00EF9C1E76FF083 | ||
| 45 | :1002C0008000BEE76FF08500BBE700BF200C002078 | ||
| 46 | :1002D0002DE9F04F05680446A1B0002D40F0AA803A | ||
| 47 | :1002E0002022294602A805F046FC12AF202229460A | ||
| 48 | :1002F0000AA805F040FC38222946384605F03BFCA8 | ||
| 49 | :10030000E26904F11C039846B2B10426E26A04F1E2 | ||
| 50 | :100310002C03EAB10425EEB96FF08306304621B014 | ||
| 51 | :10032000BDE8F08F002EF1D053F8041D3246013E97 | ||
| 52 | :100330000029F7D01646E9E70326F5E7002DEAD0B5 | ||
| 53 | :1003400053F8041D2A46013D0029F7D01546E2E77F | ||
| 54 | :100350000325F5E738233A460021606805F048FC9C | ||
| 55 | :100360003828D9D14FF00109CDE90270334F0DF192 | ||
| 56 | :10037000080A04F1100B4E45D7F800141CD10DF1FA | ||
| 57 | :1003800028094B46002008EB850EC64533D108B13D | ||
| 58 | :10039000C7F80014A3683146C7F804340AAA2B46EC | ||
| 59 | :1003A00002A8FFF73DFF00270646BD4209F10809F4 | ||
| 60 | :1003B00038D1FFF725FFB1E75BF8043FC1F5806254 | ||
| 61 | :1003C000D81C20F00300904204D9FFF719FF6FF00A | ||
| 62 | :1003D0008C06A3E70844CA19C7F8000449466068B8 | ||
| 63 | :1003E000019205F005FC019ACAF80C0009F1010917 | ||
| 64 | :1003F0004AF8082FBFE758F804CFC1F5806A0CF11E | ||
| 65 | :10040000030222F00302524503F1080305D87818CD | ||
| 66 | :1004100043E9020C11440120B7E70028D5D0C7F802 | ||
| 67 | :100420000014D2E7394659E90223606805F0F5FB6C | ||
| 68 | :100430000137BAE76FF0850670E700BF200C002097 | ||
| 69 | :1004400008B528220021024805F095FB002008BDD0 | ||
| 70 | :100450002810002010B5044C0F222046034905F057 | ||
| 71 | :1004600065FB204610BD00BF51100020F6050000BE | ||
| 72 | :1004700008B50121024803F011FB002008BD00BFB0 | ||
| 73 | :100480005010002008B5FFF7DBFF40B9FFF7E2FF8F | ||
| 74 | :10049000FFF7EEFF18B9BDE8084003F06DBB08BDDB | ||
| 75 | :1004A0006FF0850070476FF0850070476FF0850032 | ||
| 76 | :1004B00070476FF0850070476FF0850070476FF0F0 | ||
| 77 | :1004C000850070476FF0850070476FF085007047BA | ||
| 78 | :1004D000D1E9000103F030BB6FF085007047F0B543 | ||
| 79 | :1004E00003680546B3F57D7FA7B007D040F2F5322B | ||
| 80 | :1004F000934207D06FF0850027B0F0BD01F08EFC6D | ||
| 81 | :100500000020F9E700243C22214607A8CDE9024457 | ||
| 82 | :10051000CDE90444069405F02EFB3C22214617A8A1 | ||
| 83 | :10052000169405F028FBEA69019405F11C0302B357 | ||
| 84 | :100530000426EA6A05F12C033AB30424731E012B46 | ||
| 85 | :1005400052D8012C50D80423002168680DEB030217 | ||
| 86 | :1005500005F04EFB04281AD06FF08000CCE7002E87 | ||
| 87 | :10056000E7D053F8041D3246013E0029F7D0164665 | ||
| 88 | :10057000DFE70326F5E7002CE0D053F8041D224600 | ||
| 89 | :10058000013C0029F7D01446D8E70324F5E7022EF2 | ||
| 90 | :1005900016D16E69402E29D806AF33463A4601215E | ||
| 91 | :1005A000686805F025FB8642D6D1CDE9027602A91E | ||
| 92 | :1005B00044B92246019801F01AFE044620469BE702 | ||
| 93 | :1005C0000021F5E72B6A402BC6D816AACDE90423F3 | ||
| 94 | :1005D000019804AA01F00BFEDDE904230446002182 | ||
| 95 | :1005E000686805F01AFBE9E7012085E76FF08900EC | ||
| 96 | :1005F00082E7002070474D62656420544C532033DD | ||
| 97 | :100600002E352E3000000000000000000000000029 | ||
| 98 | :1006100000000000000000000000000000000000DA | ||
| 99 | :100620005431000001000000407C000080100020D8 | ||
| 100 | :100630004A000000407C0000200C00200000000068 | ||
| 101 | :10064000407C0000000C002000000000A8110020E9 | ||
| 102 | :10065000C4050000200C002018010000000C002040 | ||
| 103 | :100660000800000002F07ABC08B572B61E4A1F4BA3 | ||
| 104 | :100670009A601F4B83F309881E4B83F30A8883F328 | ||
| 105 | :100680000B881D4B16A1D1E90001C3E9000100F060 | ||
| 106 | :1006900089F81A4B1A498B4212D30020194B1A4978 | ||
| 107 | :1006A0008B4218D303F06AF8186850F82240586853 | ||
| 108 | :1006B00040F82240013298688242F5D30C33EAE7D1 | ||
| 109 | :1006C0000022F8E71C6844F8220001325C68A2426C | ||
| 110 | :1006D000F8D30833E4E70022F8E700BFAFF3008067 | ||
| 111 | :1006E000A5EDF5FEA5EDF5FE0000000000ED00E033 | ||
| 112 | :1006F000F80B002000040020F80B00202806000062 | ||
| 113 | :100700004C0600004C06000064060000EFF3088071 | ||
| 114 | :10071000EFF309812DE9F00F6B46724600F038F9CE | ||
| 115 | :1007200008B0FFF79FFFFEE708B5EFF31083012B3A | ||
| 116 | :100730000C4A07D1126ABFF34F8F511C4A424A41FB | ||
| 117 | :10074000104608BD01F0BEFB00B172B6126ABFF3DD | ||
| 118 | :100750004F8F531C5A425A4101F0B4FB0028EFD08E | ||
| 119 | :1007600062B6EDE70080FF0008B5EFF31083012BC0 | ||
| 120 | :100770000B4A06D1D269BFF34F8F02F00102104637 | ||
| 121 | :1007800008BD01F09FFB00B172B6D269BFF34F8F75 | ||
| 122 | :1007900002F0010201F096FB0028F0D062B6EEE70D | ||
| 123 | :1007A0000080FF006F4A10B5D2F8D03043F002034A | ||
| 124 | :1007B000C2F8D03001F086FB30B14FF05023002258 | ||
| 125 | :1007C000C3F81421C3F8182101F08BFB28B10122D2 | ||
| 126 | :1007D000654BC3F8382AC3F878254FF47F02D2F866 | ||
| 127 | :1007E0003031D2F83421BFF34F8FC3F30B03092B01 | ||
| 128 | :1007F00005D1012A1EBF01225B4BC3F8782501F009 | ||
| 129 | :1008000070FB18B10E22594BC3F8E42E01F05AFBCD | ||
| 130 | :1008100030B10022544BC3F80C270122C3F8102733 | ||
| 131 | :100820000022D30003F57F03D3F80013BFF34F8FEB | ||
| 132 | :10083000013108D0D3F800130132D3F80433B2F5F4 | ||
| 133 | :10084000807F0B60EDD1EFF31084FFF78DFF002860 | ||
| 134 | :100850004DD0BFF34F8F464BD3F80024012AFBD174 | ||
| 135 | :10086000C3F80425D3F80024012AFBD1012C03D0BE | ||
| 136 | :1008700001F028FB00B172B6FFF776FF58B13D4A90 | ||
| 137 | :10088000D36923F00103D361BFF34F8F384AD2F805 | ||
| 138 | :100890000034012BFBD1FFF747FF68B1354A136ADB | ||
| 139 | :1008A00023F0FF0343F020031362BFF34F8F304A5E | ||
| 140 | :1008B000D2F80034012BFBD1012C03D001F002FB54 | ||
| 141 | :1008C00000B162B600222A4BC3F80425D3F80024F5 | ||
| 142 | :1008D000012AFBD1BFF34F8F2249274BCA6802F48C | ||
| 143 | :1008E000E0621343CB60BFF34F8F00BFFDE7FFF71C | ||
| 144 | :1008F0001BFF0028ADD11B4AD2F88C3043F4406373 | ||
| 145 | :10090000C2F88C304FF47F03D3F83021D3F8343160 | ||
| 146 | :10091000BFF34F8FC2F30B02092A16D1013B022B02 | ||
| 147 | :1009200002D8164AD35C83B1124815490368104AAD | ||
| 148 | :100930008B420CBF5A230023C2F8103EC36A8B427D | ||
| 149 | :100940000CBF5A230023C2F8003E064AD2F8883072 | ||
| 150 | :1009500043F47003C2F88830BFF34F8FBFF36F8F3B | ||
| 151 | :1009600010BD00BF00ED00E00040005000A00350AB | ||
| 152 | :10097000009003500080FF000400FA05C43300001B | ||
| 153 | :10098000FA50FA507C22014905F0D0B8DC1800205A | ||
| 154 | :1009900038B51D46374B384C5B68C3F308032360FA | ||
| 155 | :1009A000EFF30383C4E901206365C2F3801302F00F | ||
| 156 | :1009B0000C020C2AE16038D10BB9EFF389812022B7 | ||
| 157 | :1009C0002E48216105F0B2F825B1202229462C4895 | ||
| 158 | :1009D00005F0ACF8274B9A6AA265D96AE165986B75 | ||
| 159 | :1009E000206602F400406066586BA06602F080004A | ||
| 160 | :1009F000E0669A62D962D3F8E4202267D3F8E8105F | ||
| 161 | :100A0000616702F04001A167C3F8E42000F06AF8D2 | ||
| 162 | :100A10000E211C4801F077FA2268D31E042B1CD843 | ||
| 163 | :100A2000DFE803F0090F1215180013B9EFF38881FE | ||
| 164 | :100A3000C5E70146C3E70C211348BDE8384001F083 | ||
| 165 | :100A400062BA12211148F8E70B211148F5E70D2190 | ||
| 166 | :100A50001048F2E70E211048EFE70F2A98BF142143 | ||
| 167 | :100A6000BDE8384089BF25210C480D48103A01F0F7 | ||
| 168 | :100A7000F5BB00BF00ED00E0DC180020F0180020FE | ||
| 169 | :100A800010190020C7330000D5330000E133000007 | ||
| 170 | :100A9000F3330000FE3300000B3400001934000073 | ||
| 171 | :100AA0002D3400002DE9F34106460F460C4DD5F8D4 | ||
| 172 | :100AB0002C80C04710F00104FBD1394630466B69E9 | ||
| 173 | :100AC000984740B9C047C307FCD42B6A019302B0D2 | ||
| 174 | :100AD000BDE8F0411847204602B0BDE8F08100BFF4 | ||
| 175 | :100AE0005434000010B5094C0020A36898472369CE | ||
| 176 | :100AF00002209847A46A4FF4E1310120A047234621 | ||
| 177 | :100B0000BDE8104001211520184700BF54340000F3 | ||
| 178 | :100B100010B5044C002023699847E368BDE81040F5 | ||
| 179 | :100B2000184700BF54340000064B82B018680023F9 | ||
| 180 | :100B300082B262F30F03000C60F31F43184602B049 | ||
| 181 | :100B4000704700BF9C340000014B1869704700BF1C | ||
| 182 | :100B500084100020014B5869704700BF84100020AA | ||
| 183 | :100B600038B50C4D0C4695F8203013B94FF0FF30D6 | ||
| 184 | :100B700038BD0A460146284600F06CFF064B9842F5 | ||
| 185 | :100B800005D00B3B9842F1D100206C61F0E76FF08B | ||
| 186 | :100B90000100EDE7841000200B00AD0BF0B51B4EFB | ||
| 187 | :100BA000054696F820300C4691B01BB94FF0FF3047 | ||
| 188 | :100BB00011B0F0BD00F06043B3F1005F21D100231C | ||
| 189 | :100BC0000A460146304600F031FC114B98421AD0DB | ||
| 190 | :100BD0000B3B9842EAD1346111E0A71B402F28BF9C | ||
| 191 | :100BE0004027A9193A46684604F0A0FF39466846EE | ||
| 192 | :100BF000FFF7D4FF0028DBD14036B442EDD8002007 | ||
| 193 | :100C0000D6E70026F9E76FF00100D1E78410002055 | ||
| 194 | :100C10000B00AD0BC3B2012B10B540F096804DF622 | ||
| 195 | :100C2000C023994270D028D8B1F5615F6FD011D838 | ||
| 196 | :100C3000B1F5965F6DD008D8B1F5966F6BD0B1F570 | ||
| 197 | :100C4000166F6BD06FF007005DE0B1F5165FF9D15C | ||
| 198 | :100C5000454B33E047F61223994262D007D8B1F5ED | ||
| 199 | :100C6000964F61D0B1F5E14FECD1404B26E0B1F5A4 | ||
| 200 | :100C7000164FE7D14FF41D0320E03D4B994255D06C | ||
| 201 | :100C800011D8B1F5E13F54D007D8B1F5614F53D039 | ||
| 202 | :100C9000B1F5963FD6D1374B10E0B1F5613FD1D1D8 | ||
| 203 | :100CA0004FF06C730AE0B1F5612F48D0324B994296 | ||
| 204 | :100CB00048D0B1F5E12FC5D14FF0E86310F4E06FF3 | ||
| 205 | :100CC00046D110F4404103D0B1F5804F43D11021FB | ||
| 206 | :100CD00010F4405203D0B2F5805F3FD10E2210F4E1 | ||
| 207 | :100CE000403003D0B0F5403F3BD10120234C20766B | ||
| 208 | :100CF0006276E361A1760A4324681043C4F8243580 | ||
| 209 | :100D0000C4F86C05002010BD4FF46503D6E71C4BFA | ||
| 210 | :100D1000D4E71C4BD2E74FF49E23CFE74FF41D23BB | ||
| 211 | :100D2000CCE74FF40003C9E7174BC7E74FF08063E8 | ||
| 212 | :100D3000C4E74FF0EB73C1E74FF46B03BEE74FF02E | ||
| 213 | :100D40007063BBE74FF08053B8E76FF00300DAE75A | ||
| 214 | :100D50006FF00800D7E76FF00A00D4E76FF00900E2 | ||
| 215 | :100D6000D1E76FF00B00CEE70050270000C0750000 | ||
| 216 | :100D700090D0030000903A0140420F008410002000 | ||
| 217 | :100D800000F03A0000B0130000A04E0010B5114C66 | ||
| 218 | :100D9000204600F0D5FD0021206884F8201000F0E6 | ||
| 219 | :100DA00047FF226842F30732002A11DB0121530971 | ||
| 220 | :100DB0009B0003F1604303F56143D3F8800202F026 | ||
| 221 | :100DC0001F0201FA02F20243C3F88022D3F88032F4 | ||
| 222 | :100DD000002010BD8410002010B5264C0021206892 | ||
| 223 | :100DE0008EB000F017FF226842F30732002A12DBB0 | ||
| 224 | :100DF000012053099B0003F1604303F56143D3F8DD | ||
| 225 | :100E0000801202F01F0200FA02F221EA0202C3F885 | ||
| 226 | :100E10008022D3F880322422002105A804F0ABFE02 | ||
| 227 | :100E2000D4E902124FF0FF33CDE90133CDE90333AA | ||
| 228 | :100E30004FF0EB730B93072301A88DF8363001F0C8 | ||
| 229 | :100E400080F8014600220B4800F03AFA0A4B98421B | ||
| 230 | :100E50000DD10C9B002023831B0CA3760B9BC4E9B4 | ||
| 231 | :100E60000400E361012384F820300EB010BD6FF060 | ||
| 232 | :100E70000100FAE7841000200000AD0B7FB50025CB | ||
| 233 | :100E80000C46C0F808511646D0F80821D0F80022C8 | ||
| 234 | :100E900022F02002C0F80022104AC0F8082301F016 | ||
| 235 | :100EA000A0F8A560256104F14C03D3E8EF1F21F4FD | ||
| 236 | :100EB0007F0121F47041C3E8E21F002AF5D110221E | ||
| 237 | :100EC0002946684604F057FE042368468DF8003032 | ||
| 238 | :100ED0000196D4E90013984704B070BD10020A00CF | ||
| 239 | :100EE00000F01F03400909D1074A02EB8303D3F83E | ||
| 240 | :100EF0000012064A0A40C3F80022704700228033DD | ||
| 241 | :100F000052F82330FFDE00BF00258450F0F8FCFFCC | ||
| 242 | :100F10002DE9F04F804690F804A05020664F0E4611 | ||
| 243 | :100F200000FB0A70416885B049B113F0020304D098 | ||
| 244 | :100F3000836B002B00F0B2800123009300E000914E | ||
| 245 | :100F40004FF0500909FB0A73DB6CD90600F1A6804B | ||
| 246 | :100F50004FF0010BB3180293029BB34200F0A7803D | ||
| 247 | :100F600006F06043039398F80450D8F8004009FB5A | ||
| 248 | :100F700005739A6B9AB9039BB3F1005F40F09980B7 | ||
| 249 | :100F8000019200F0A1FD09FB0572D16C204601F031 | ||
| 250 | :100F9000010100F0F4FF28B900F09EFDE3E7012312 | ||
| 251 | :100FA0000193EEE7516C33460029BCBFD4F84C15D1 | ||
| 252 | :100FB0005164019A42B109FB05713078D1E90E23E1 | ||
| 253 | :100FC000D054D1E90E3213441BB1C4F84435C4F8EF | ||
| 254 | :100FD00048B50022C4F82021D4F82011C4F85821C3 | ||
| 255 | :100FE000D4F85811C4F85021D4F850210822C4F87C | ||
| 256 | :100FF0000025009AE2B14FF48003C4F80433C4F82A | ||
| 257 | :1010000008B000F069FD502303FB0A725168002903 | ||
| 258 | :101010004BD1D26C120748D503FB0A734C33D3E88B | ||
| 259 | :10102000EF1F21F00801C3E8E21F002A36D0F6E7DF | ||
| 260 | :10103000C4F808B0019300F04FFD09FB0572D16CB4 | ||
| 261 | :10104000019B01F001012046019300F098FF8446C6 | ||
| 262 | :10105000019BD4F84C05D4F84425BCF1000F0DD108 | ||
| 263 | :101060009342F0D005EB850507EB0515D1B100F0F3 | ||
| 264 | :101070002BFD2946204600F0F9FFC2E705EB850568 | ||
| 265 | :10108000934207EB0515F1D10028EFD100F01CFDCC | ||
| 266 | :101090002946204600F0EAFF00F01EFD074805B093 | ||
| 267 | :1010A000BDE8F08FC4F80CB0E1E7013654E704481E | ||
| 268 | :1010B000F5E70448F3E700BF581900200800AD0B1E | ||
| 269 | :1010C0000000AD0B0400AD0B430904D10123034A1A | ||
| 270 | :1010D00083409360704700239B60FFDE00258450AF | ||
| 271 | :1010E00000F01F0340090BD1084A02EB8302D2F83B | ||
| 272 | :1010F0000012074B0B4043F00303C2F80032704765 | ||
| 273 | :101100000022803352F82330FFDE00BF00258450D8 | ||
| 274 | :10111000F0F8FCFF2DE9F84391F8303005460C4615 | ||
| 275 | :1011200090F804800F6853BB5023DFF85091781C6F | ||
| 276 | :1011300003FB0893DE6C46F00072DA6404D0384694 | ||
| 277 | :10114000FFF7C2FFFFF7CCFF6068411C01D0FFF73B | ||
| 278 | :10115000C7FE94F82C30012B11D1502303FB0893C8 | ||
| 279 | :10116000E06846F02066421CDE6401D0FFF7B8FE5E | ||
| 280 | :10117000A068431C03D0FFF7A7FFFFF7B1FF94F867 | ||
| 281 | :101180002F0038B950223D4B02FB0833DA6C42F095 | ||
| 282 | :101190008072DA6494F82CC094F82D1094F82EE044 | ||
| 283 | :1011A000A26A2B6841EA0C01E668D4E90198C3F809 | ||
| 284 | :1011B00024254EEA0102C3F86C2550B9BCF1010F99 | ||
| 285 | :1011C000C3F80C75C3F8149504BFC3F80885C3F8B9 | ||
| 286 | :1011D0001065D3F8682503F26458012A08BFDA6065 | ||
| 287 | :1011E000D3F86425012A13D1082149F64046244F3B | ||
| 288 | :1011F000C3F8001547F001075A60D8F800309BBBD0 | ||
| 289 | :101200002B68D3F88024C3F880240022C3F800257B | ||
| 290 | :1012100000212B6894F83220C3F81011D3F8100184 | ||
| 291 | :10122000C3F82011D3F82001C3F82411D3F8240106 | ||
| 292 | :10123000C3F84411D3F84401C3F85811D3F8581136 | ||
| 293 | :1012400043F307335201002BD2B212DB0D49C81809 | ||
| 294 | :1012500080F800230122580903F01F0302FA03F368 | ||
| 295 | :1012600041F82030BDE8F8834020B847013EC4D1A2 | ||
| 296 | :10127000C6E7054903F00F03CA54F3E758190020E5 | ||
| 297 | :10128000A034000000E100E014ED00E000F01F03D6 | ||
| 298 | :1012900040090BD1084A02EB8302D2F80012074B37 | ||
| 299 | :1012A0000B4043F00203C2F8003270470022803343 | ||
| 300 | :1012B00052F82330FFDE00BF00258450F0F8FCFF19 | ||
| 301 | :1012C0002DE9F3479046502290F80490514C02FBD0 | ||
| 302 | :1012D00009FA04EB0A070D4697F84810064600295C | ||
| 303 | :1012E00040F0858009EB890004EB001004F043FC1A | ||
| 304 | :1012F0002B69AA6944F80A306B69BB6302B1013AF1 | ||
| 305 | :10130000502303FB0943DA632A6A042A81BFEA698E | ||
| 306 | :101310009A610022DA6195F83130B8F1000F37D0C8 | ||
| 307 | :1013200083F001073F0233B1502303FB0943DA6C1A | ||
| 308 | :1013300042F00102DA64502303FB09440123C4F89C | ||
| 309 | :10134000048084F848303468D4F84C2112BB294614 | ||
| 310 | :101350003046FFF7DFFE0822002334688DF807309F | ||
| 311 | :10136000C4F800250DF10702C4F84425C4F8483537 | ||
| 312 | :1013700001230A25A360E360D4F85831002B38D14B | ||
| 313 | :10138000254B402043F001039847013DF4D128E06C | ||
| 314 | :101390004746C8E708224FF06409C4F80025636097 | ||
| 315 | :1013A0001D4B43F0010AD4F84431F3B9D4F8243189 | ||
| 316 | :1013B000DBB94FF42070D047B9F10109F3D14B46A6 | ||
| 317 | :1013C0000022C4F84C21D4F84C11C4F81021D4F8F0 | ||
| 318 | :1013D0001011C4F84421D4F84411C4F80025002B9E | ||
| 319 | :1013E000B5D10E4802B0BDE8F0870123E8E70C480C | ||
| 320 | :1013F000F8E70023C4F820319845D4F82021C4F838 | ||
| 321 | :101400000035084B08BF00231F4333680648C3F864 | ||
| 322 | :101410000473E7E758190020A03400000100AD0B69 | ||
| 323 | :101420000C00AD0B10020A000000AD0B2DE9F047D7 | ||
| 324 | :1014300084460F469E4616460579002A51D04FF045 | ||
| 325 | :10144000500ADFF8BC80D0F800900AFB058ADAF871 | ||
| 326 | :10145000044074B96BB9DAF82C50002D43D1CAF8A6 | ||
| 327 | :101460002C20FFF755FD0446CAF82C502046BDE855 | ||
| 328 | :10147000F0871EF0030F07D0734632463946BDE8A9 | ||
| 329 | :10148000F0476046FFF744BD07F06043B3F1005FEB | ||
| 330 | :101490004FF0500414D104FB058400F015FBE26A00 | ||
| 331 | :1014A0001AB1134C00F018FBE0E7C4E90A7605EB2B | ||
| 332 | :1014B0008505484608EB051100F0E3FD0D4CF1E70A | ||
| 333 | :1014C00004FB0584A36B83B100F0FEFAE36A002BF2 | ||
| 334 | :1014D000E7D1E36C012243F00203C4E90A76E36436 | ||
| 335 | :1014E000E5E7054CC2E7024CC0E7044CBEE700BF8D | ||
| 336 | :1014F0000B00AD0B0000AD0B0600AD0B0A00AD0BF1 | ||
| 337 | :10150000581900202DE9F84350230679284D046826 | ||
| 338 | :1015100003FB0653D4F80473DA6AC4F8087322B9DB | ||
| 339 | :101520002448C4F80473BDE8F88306EB860005F18F | ||
| 340 | :101530004C024FEA001802EB0012D2E8EFCF4CF059 | ||
| 341 | :10154000080CC2E8E0CF0028F7D10122E26031B3F5 | ||
| 342 | :10155000D96C01EA02094946204600F010FD002836 | ||
| 343 | :10156000FAD000F0B1FAB9F1000F1CD1D4F8203153 | ||
| 344 | :1015700053B10123E360D4F85831002BFBD020464F | ||
| 345 | :1015800005EB080100F072FD00F0A6FA0023C4F894 | ||
| 346 | :101590002031D4F82021502202FB0655EB62064888 | ||
| 347 | :1015A000C4F80473BFE7D4F85831002BE7D1EBE758 | ||
| 348 | :1015B000581900200500AD0B0000AD0B2DE9F843D4 | ||
| 349 | :1015C00090F80480484F08EB8806360106F14C0578 | ||
| 350 | :1015D00004683D44D5E8EF3F43F48052C5E8E02F6E | ||
| 351 | :1015E0000028F7D1DB047BD4480705D5502303FB43 | ||
| 352 | :1015F00008739B69002B75D03C4B3E44C4F80833FC | ||
| 353 | :101600000823C4F800350023C4F81031D4F81021A1 | ||
| 354 | :10161000C4F84C31D4F84C21C4F844310A03D4F84E | ||
| 355 | :1016200044318B0303F4804302F400524903134313 | ||
| 356 | :1016300001F400410B43D5E8EF2F1A43C5E8E12F31 | ||
| 357 | :101640000029F8D14FF0500909FB0879D9F8083082 | ||
| 358 | :10165000BBB9D9F8043063B9D5E8EF3F23F47F0371 | ||
| 359 | :1016600023F47043C5E8E23F002AF5D12048BDE8E5 | ||
| 360 | :10167000F8830321304600F08FFCD9F80830002BA6 | ||
| 361 | :10168000EAD0D4F80433590713D5502303FB087369 | ||
| 362 | :101690005A6872B1DB6C1A030BD5D5E8EF3F23F41F | ||
| 363 | :1016A0000023C5E8E23F002AF7D10621304600F0CA | ||
| 364 | :1016B00073FC502303FB0873DB6CDB0401D40D487F | ||
| 365 | :1016C000D5E7D4F84C310BB901232360502303FB39 | ||
| 366 | :1016D00008735B68002BF2D0044BC4F80433EEE7C8 | ||
| 367 | :1016E0000548C4E70548C2E75819002010020A005F | ||
| 368 | :1016F0000200AD0B0000AD0B0B00AD0B0800AD0BF5 | ||
| 369 | :101700002DE9F84F056801F06043D5F804A3B3F163 | ||
| 370 | :10171000005F90F804B089461746C5F808A37CD14D | ||
| 371 | :101720005023404E03FB0B639A6852B15B68002B59 | ||
| 372 | :101730005ED1D5F81021002A5AD0C5F81031D5F85D | ||
| 373 | :101740001031502404FB0B64E269C4E90297002ABB | ||
| 374 | :101750003CD00BEB8B0897424FEA081824D24FF08D | ||
| 375 | :10176000000B3A46A1694846C4E902BB04F0DEF921 | ||
| 376 | :10177000E269A069D21BC119E26104F0A1F96368B2 | ||
| 377 | :101780006BB1B04449463A46404600F016FCE36C63 | ||
| 378 | :10179000990404D55A4641462846FFF76FFB224874 | ||
| 379 | :1017A000C5F804A3BDE8F88F4846A16904F0BEF966 | ||
| 380 | :1017B000E36963620023E3611C4B9844D8E8EF3F80 | ||
| 381 | :1017C00043F40023C8E8E23F002AF7D1502303FB8B | ||
| 382 | :1017D0000B63586ADA689968DB6C121A0144C5F821 | ||
| 383 | :1017E0003415C5F83825DA04D9D501232B60D6E79E | ||
| 384 | :1017F000502303FB0B6633698BB9F36CC5F8349542 | ||
| 385 | :101800005B04C6E90497C5F83875C8D5D5F8003229 | ||
| 386 | :1018100043F02003C5F80032C1E70548C0E705489A | ||
| 387 | :10182000BEE700BF581900200000AD0BA41900202E | ||
| 388 | :101830000A00AD0B0B00AD0B50232DE9F0413C4DE0 | ||
| 389 | :1018400090F80480046803FB0853DB6CD4F80002B2 | ||
| 390 | :1018500003F48223B3F5805F68D1D4F80463C4F83D | ||
| 391 | :10186000086309B9830656D4D4F8003223F0200364 | ||
| 392 | :10187000C4F800324FF4842308EB8801090101F118 | ||
| 393 | :101880004C072F44D7E8EF0F1843C7E8EC0FBCF123 | ||
| 394 | :10189000000FF7D12AB9502303FB08535B68002BD4 | ||
| 395 | :1018A00041D1244BC4F8083301236360D4F8443198 | ||
| 396 | :1018B000002BFBD00023C4F84C31D4F84C21C4F8E1 | ||
| 397 | :1018C0001031D4F81021C4F84431D4F844315023F5 | ||
| 398 | :1018D00003FB0853DA6C12F400421FD1DA61204690 | ||
| 399 | :1018E00000F07FFB502303FB08550023AB602B6106 | ||
| 400 | :1018F000D7E8EF3F23F47F0323F47043C7E8E23FC8 | ||
| 401 | :10190000002AF5D126F4202626F404760A48C4F8E5 | ||
| 402 | :101910000463BDE8F0814FF48033ADE720462944ED | ||
| 403 | :1019200000F071FBDBE701236360EFE70348F0E7BA | ||
| 404 | :101930005819002010020A000000AD0B0500AD0B85 | ||
| 405 | :101940002DE9F8432F4A03680679C3F8082343F3C7 | ||
| 406 | :101950000733002B04460DDB01215A0903F01F0356 | ||
| 407 | :10196000994002F12003284A42F82310BFF34F8F19 | ||
| 408 | :10197000BFF36F8F012220461146FFF75DFF012163 | ||
| 409 | :101980002046FFF7BFFD50212279204D236801FB3F | ||
| 410 | :101990000252D46CD3F80C05E201D3F81495D3F8B5 | ||
| 411 | :1019A0000875D3F8108509D54FF0FF32C3F80C2520 | ||
| 412 | :1019B000C3F81425C3F80825C3F81025A30116D5CC | ||
| 413 | :1019C000411C01D0FFF762FCB9F1FF3F02D048464D | ||
| 414 | :1019D000FFF75CFC22010AD5B8F1FF3F02D0404678 | ||
| 415 | :1019E000FFF754FC7B1C02D03846FFF74FFC502316 | ||
| 416 | :1019F000002203FB0653DA6483F848205A60BDE8EE | ||
| 417 | :101A0000F88300BF10034A0000E100E058190020ED | ||
| 418 | :101A100010B5502402790B4B04FB02335B686BB9A1 | ||
| 419 | :101A20000368D3F810211AB9D3F80025082A07D083 | ||
| 420 | :101A300011B1D3F83C350B60034810BD0348FCE7F7 | ||
| 421 | :101A40000348FAE7581900200000AD0B0800AD0B61 | ||
| 422 | :101A50000B00AD0BF7B505461646FFF751FE164BCA | ||
| 423 | :101A60000446984222D1032128462F79FFF7A6FD8C | ||
| 424 | :101A7000124B984201D0A0421BD15022104B02FBC6 | ||
| 425 | :101A800007335B6893B90C4C284601A9FFF7C0FFE8 | ||
| 426 | :101A9000A042F9D1019BB34207D301222846114647 | ||
| 427 | :101AA00003B0BDE8F040FFF7C7BE064C204603B0C8 | ||
| 428 | :101AB000F0BD0446FAE700BF0000AD0B0B00AD0B14 | ||
| 429 | :101AC000581900200800AD0B72B6024A13680133A2 | ||
| 430 | :101AD00013607047A8190020034A1368013B136084 | ||
| 431 | :101AE00003B962B6704700BFA81900200722024B55 | ||
| 432 | :101AF000C3F80423704700BF00300050084BD3F8F0 | ||
| 433 | :101B00000801D3F80021003818BF012080000AB175 | ||
| 434 | :101B100040F00100D3F804310BB140F002007047EF | ||
| 435 | :101B2000003000500022074BC3F80021D3F8001109 | ||
| 436 | :101B3000C3F80421D3F80411C3F80821D3F80831FD | ||
| 437 | :101B4000704700BF0030005000231720094A03F5FA | ||
| 438 | :101B5000C0710133202B42F82100F8D10023172057 | ||
| 439 | :101B6000044A03F5E0710133202B42F82100F8D13B | ||
| 440 | :101B7000704700BF0030005010B59DF80840C00B02 | ||
| 441 | :101B800043EA0423064CC90B43EA0213884200D9F6 | ||
| 442 | :101B900010BDC2B202F5C07244F822300130F5E740 | ||
| 443 | :101BA0000030005010B59DF8084000F1604043EA55 | ||
| 444 | :101BB000042301F16041074C400B490B43EA021337 | ||
| 445 | :101BC000884200D910BDC2B202F5E07244F822305A | ||
| 446 | :101BD0000130F5E700300050C0F30E03C3F50043B9 | ||
| 447 | :101BE000B3FA83F3C3F11B03064AC0F3C730DBB279 | ||
| 448 | :101BF00040F4807043F48073C2F80005C2F80435E5 | ||
| 449 | :101C0000704700BF0030005043030148184470473C | ||
| 450 | :101C1000FF1FF81F054BC0F30730090241F03001E8 | ||
| 451 | :101C200000F5007043F82010704700BF00300050EE | ||
| 452 | :101C3000044BC0F30730090200F5007043F8201090 | ||
| 453 | :101C4000704700BF00300050003A18BF0122003931 | ||
| 454 | :101C500018BF012103688900074841EA420118635F | ||
| 455 | :101C600059605A6842F001025A60BFF34F8FBFF3C8 | ||
| 456 | :101C70006F8F0020704700BF04AAFF0008B5FFF770 | ||
| 457 | :101C80003DFF044B162118600348BDE8084000F0F2 | ||
| 458 | :101C90003AB900BFEC1F0020A63400000C22014915 | ||
| 459 | :101CA00003F044BFEC1F002010B501F006FB044612 | ||
| 460 | :101CB00090B901F097FF044680B90A4A2E21D368F3 | ||
| 461 | :101CC000094823F008031B041B0C43F0BF6343F4D3 | ||
| 462 | :101CD0000033D36000F017F9204610BD45F22354BD | ||
| 463 | :101CE000FAE700BF00ED00E0BC340000024B1860D2 | ||
| 464 | :101CF000024B002019607047FC1F0020F81F0020D5 | ||
| 465 | :101D00001FB5374C426923685A6282699A62C26978 | ||
| 466 | :101D1000DA62026A1A63426A5A63826A9A63C26A20 | ||
| 467 | :101D2000DA63026B1A64426B5A60826B9A60C26B10 | ||
| 468 | :101D3000DA60026C1A61426C5A61826C9A61C26C00 | ||
| 469 | :101D4000DA61026D1A62826D5A65C26D9A65026F20 | ||
| 470 | :101D5000DA65026E1A66826E5A66426F9A66EFF311 | ||
| 471 | :101D600088825A64EFF389829A644268DA64EFF3F6 | ||
| 472 | :101D700094821A65026801A81A67FFF78FFF23682B | ||
| 473 | :101D8000019ADA6601221A70164B1C686408640016 | ||
| 474 | :101D90002046214622462346B7EE000AF7EE000A07 | ||
| 475 | :101DA000B7EE001AF7EE001AB7EE002AF7EE002A97 | ||
| 476 | :101DB000B7EE003AF7EE003AB7EE004AF7EE004A07 | ||
| 477 | :101DC000B7EE005AF7EE005AB7EE006AF7EE006A77 | ||
| 478 | :101DD000B7EE007AF7EE007A03F081FF04B010BD91 | ||
| 479 | :101DE000FC1F0020F81F002000B5A1B001A8FEF7DD | ||
| 480 | :101DF000C9FD029B63B15B060AD4019B23F0020379 | ||
| 481 | :101E0000052B05D1044B1B6813B101A8FFF778FF20 | ||
| 482 | :101E100021B05DF804FB00BFF81F0020BFF34F8F17 | ||
| 483 | :101E20000549064BCA6802F4E0621343CB60BFF376 | ||
| 484 | :101E30004F8F00BFFDE700BF00ED00E00400FA0592 | ||
| 485 | :101E400038B543680C2B30D14B68042B2DD14FF0A3 | ||
| 486 | :101E5000FF3304680D6821682B6031B3A26822B398 | ||
| 487 | :101E60000623012001F081F9F8B96168104B99420D | ||
| 488 | :101E70000DD9A2680F485318834202D9F43883421F | ||
| 489 | :101E800010D8206803F052FE0020286038BD0A4BAD | ||
| 490 | :101E900099420AD9A26809488B188342F1D90730C0 | ||
| 491 | :101EA000814202D906488342EBD90220EEE700BF07 | ||
| 492 | :101EB000FF01FF002C02FF002F01FF003801FF008F | ||
| 493 | :101EC0004C01FF004FF47F03D3F83001D3F83431D5 | ||
| 494 | :101ED000BFF34F8FC0F30B00A0F1090358425841E4 | ||
| 495 | :101EE00070474FF47F02D2F83031D2F83401BFF39B | ||
| 496 | :101EF0004F8FC3F30B03092B03D1431E58425841A4 | ||
| 497 | :101F0000704700207047FEF7CDBD012070476FF08D | ||
| 498 | :101F100003007047002382B00193019802B070471C | ||
| 499 | :101F20006FF003007047002382B00193019802B064 | ||
| 500 | :101F30007047022814BF6FF0030000207047FEF7BF | ||
| 501 | :101F40002DBE30B501EB8202914200D130BD51F877 | ||
| 502 | :101F5000044B04F07F037F2B4FEA144408BF4FF07B | ||
| 503 | :101F6000FF33032CF0D8DFE804F002040608036016 | ||
| 504 | :101F7000EAE74360E8E78360E6E7C360E4E7034637 | ||
| 505 | :101F8000D0F8580130B931B9D3F82001003818BF62 | ||
| 506 | :101F9000012070470120704730B504460D4685B0DA | ||
| 507 | :101FA00010220021684603F0E6FDD4E900136846DC | ||
| 508 | :101FB0008DF80050984705B030BD7FB504460E46F9 | ||
| 509 | :101FC000154600211022684603F0D5FD012368461E | ||
| 510 | :101FD0008DF80030CDE90165D4E90013984704B0CD | ||
| 511 | :101FE00070BD10B50446FFF76FFDD4F8583133B11A | ||
| 512 | :101FF000D4F8043313F4800308BFC4F80035BDE8F7 | ||
| 513 | :102000001040FFF769BD70B50D4604460522AA21B0 | ||
| 514 | :10201000D0F83C65A86903F0AEFD0522AB69C4F8B1 | ||
| 515 | :102020003435C4F838250022C4F81021D4F8101132 | ||
| 516 | :102030000121E162D4F810110029FBD0C4F84C2131 | ||
| 517 | :10204000D4F84C11C4F81021D4F81021D4F83C2550 | ||
| 518 | :102050009642EA6109D15A1E043312F8011FAA29D7 | ||
| 519 | :1020600003D19A42F9D10023EB6170BDD0F8583109 | ||
| 520 | :1020700033B1CB6CC3F30032DB0458BFC0F800258A | ||
| 521 | :10208000704770B5CE6C0D4606F001010446FFF7AF | ||
| 522 | :1020900076FF38B94FF4800346F00406EE64C4F8C6 | ||
| 523 | :1020A000043370BDD5E90A365AB1296CEA6B761A49 | ||
| 524 | :1020B000964228BF164619443246A86B03F036FDF7 | ||
| 525 | :1020C000AB6B4FF0FF326A641BB1C4F84435C4F8FF | ||
| 526 | :1020D00048650023C4F82031D4F82021C4F85831D1 | ||
| 527 | :1020E000D4F85821C4F85031D4F850310823C4F83A | ||
| 528 | :1020F00000354FF48003C4F804330123A360D0E714 | ||
| 529 | :10210000C0037047C00300F5FF407F3070470020D8 | ||
| 530 | :1021100070471F2070474FF40040704700F57F4024 | ||
| 531 | :10212000C03040037047402070475F2070474FF435 | ||
| 532 | :10213000005070474B6830B513F01F052DD1026871 | ||
| 533 | :102140000C681068C0F30720844226D2506855609E | ||
| 534 | :1021500094600C7C23F01F0304F001041C438B7C6F | ||
| 535 | :10216000DB0003F018031C434B7C5B0003F0060309 | ||
| 536 | :102170002343D3608B68013B23F01F04CB685B00D3 | ||
| 537 | :1021800003F00E03234343F0010313615060BFF3D8 | ||
| 538 | :102190004F8FBFF36F8F284630BD0120FCE70368E7 | ||
| 539 | :1021A00000205A68C9B258609960D86018615A60B6 | ||
| 540 | :1021B000704770B50546002403681E68C6F30726FD | ||
| 541 | :1021C000B44201D1002070BD21462846FFF7E7FF49 | ||
| 542 | :1021D0000134F5E70020704708B5FFF705FE72B639 | ||
| 543 | :1021E00020BFFDE7002070470020704770470B4676 | ||
| 544 | :1021F00070B5114618B1032806D0032070BD1846EB | ||
| 545 | :10220000BDE87040FFF71CBE5A68082A01D00220C2 | ||
| 546 | :10221000F4E74C68042CFAD11D684FF0FF330E68C8 | ||
| 547 | :10222000296833600029F2D06B68002BEFD0262399 | ||
| 548 | :102230007422012000F099FF0028E8D122462323D0 | ||
| 549 | :102240000120696800F091FF04460028DFD1D5E93C | ||
| 550 | :102250000001FFF74BFD30602046CFE730B50C465C | ||
| 551 | :10226000154685B038B139B1FFF74DFE041E03DACB | ||
| 552 | :10227000204605B030BD044640F60D23ADF80E30C3 | ||
| 553 | :1022800009230B4901A805F00F028A5C2D091A5495 | ||
| 554 | :10229000013B012BF7D147F630030C21ADF8043098 | ||
| 555 | :1022A000FFF731FE0028B4BF04462418E0E700BF62 | ||
| 556 | :1022B000EA34000008B5194B83F30A88184800F087 | ||
| 557 | :1022C000E7FF40BBFFF7F0FC28BBFFF783FF10BB25 | ||
| 558 | :1022D000FFF788FFD8B9FFF789FF00F067FA3521CB | ||
| 559 | :1022E0001048FFF710FE17210F48FFF70CFE1821CA | ||
| 560 | :1022F0000E48FFF708FE00F03FFC21210C48FFF7D5 | ||
| 561 | :1023000002FE00F03FFA00F0CDFE002008BDFFF70E | ||
| 562 | :102310006BFF0028DFD000F021FEEEE70004002074 | ||
| 563 | :10232000AC190020FA3400002F35000046350000BB | ||
| 564 | :102330005E3500002DE9F04F93B00093574B814676 | ||
| 565 | :10234000D3F800B00BB2002B0D461646C1F302685D | ||
| 566 | :10235000C1F3024A04DA6FF0800013B0BDE8F08FD9 | ||
| 567 | :102360008B42C36001D10020F7E708EB0A03042B7E | ||
| 568 | :10237000F1D8CC0F64014FEAC80731463A46DBF882 | ||
| 569 | :10238000080044F0020300F0F0FE01460028E2D10C | ||
| 570 | :10239000202202A803F0EFFB3A46314602A84FEA9A | ||
| 571 | :1023A000CA0603F0C3FB32460099DBF8080044F08C | ||
| 572 | :1023B000060300F0DAFE07460028CCD101462022B1 | ||
| 573 | :1023C0000AA803F0D8FB324600990AA802AE03F02F | ||
| 574 | :1023D000ADFB33460137B84514D91A46BC460DE06B | ||
| 575 | :1023E000D2F808E0D16818687144884203D259686D | ||
| 576 | :1023F00008448645AFD30CF1010C0832C445EFD137 | ||
| 577 | :102400000833E7E715F0006F18BF202409F118071B | ||
| 578 | :1024100007EB880844F00203474513D1202C26D14E | ||
| 579 | :10242000002D02DBC5F3C0456C0109F128050AAE99 | ||
| 580 | :1024300005EB8A0A44F0060455451AD1009BC9F8F9 | ||
| 581 | :102440007C3090E77268DBF8080056F8081B0193AF | ||
| 582 | :1024500000F08BFE00287FF47EAF56F8042C019B21 | ||
| 583 | :1024600047F8042F56F8082C38633A62D4E7002462 | ||
| 584 | :10247000DBE77268234656F8081BDBF8080000F01B | ||
| 585 | :1024800074FE00287FF467AF56F8043C45F8043F1B | ||
| 586 | :1024900056F8083C28642B63CEE700BFB019002033 | ||
| 587 | :1024A0002DE9F0411F461A4B0D461646D3F8008021 | ||
| 588 | :1024B00000F051FF044608B900F050FDE368002B1E | ||
| 589 | :1024C00001DA00F04BFD032D01D900F047FD04EBCC | ||
| 590 | :1024D0008504E569E36CED1A16D006233A463146C9 | ||
| 591 | :1024E000D8F8080000F041FE08B100F037FDBD4209 | ||
| 592 | :1024F00028BF3D46E36CE16B2A461944304603F0A1 | ||
| 593 | :1025000015FBE36C2B44E3642846BDE8F08100BF73 | ||
| 594 | :10251000B01900202DE9F0411D461A4B0F46164612 | ||
| 595 | :10252000D3F8008000F017FF044608B900F016FD4C | ||
| 596 | :10253000E368002B01DA00F011FD032F01D900F050 | ||
| 597 | :102540000DFD04EB8704E36AE26E9B1AAB4201D2F5 | ||
| 598 | :1025500000F004FD02232A463146D8F8080000F0B6 | ||
| 599 | :1025600004FE08B100F0FAFCE36EE06D2A46314645 | ||
| 600 | :10257000184403F0DBFAE36E00202B44E366BDE869 | ||
| 601 | :10258000F08100BFB01900202DE9F04105464FF061 | ||
| 602 | :1025900001080E4E0E4B37685C681CB92846376040 | ||
| 603 | :1025A000BDE8F0812268936813F400700CD1A36930 | ||
| 604 | :1025B000012B09D0D368346023B19847002801DA91 | ||
| 605 | :1025C00000F0CCFCC4F81880246AE6E7B0190020BB | ||
| 606 | :1025D000B419002038B5044610B96FF0800038BD3A | ||
| 607 | :1025E0008368002BF9D01A68002AF6D05D68002DA8 | ||
| 608 | :1025F000F3D00B4BE861A8691D6020B92B68DB683C | ||
| 609 | :1026000053B90123AB61A36804F10C001B681B697B | ||
| 610 | :10261000984701232360E2E798470028F1DADCE7D6 | ||
| 611 | :10262000B01900204268024B08461A60704700BF8C | ||
| 612 | :10263000B0190020002330B505680446AA68C0E937 | ||
| 613 | :10264000063312F4406F85B01CD012F4006202D041 | ||
| 614 | :1026500000F0C2F90246A96A2B6968460B440731AB | ||
| 615 | :1026600023F0070321F00701CDE9021300930023B3 | ||
| 616 | :1026700005490193EB6800F09FFA684600F04EFEB2 | ||
| 617 | :10268000024B1C6005B030BD89250000B019002048 | ||
| 618 | :1026900001F00C0370B50C2B0CBF154605464A061D | ||
| 619 | :1026A0000C461ED58B0658BF2835AB6913F8026C53 | ||
| 620 | :1026B00084F00803C3F3C003C6F38012934201D031 | ||
| 621 | :1026C00000F04CFC16F0A00F1ED176B1032E17D0EF | ||
| 622 | :1026D00032461C210E48FFF7C1FD6FF083032B60CB | ||
| 623 | :1026E0000CE000F03BFC2026E2E700F03BFB044658 | ||
| 624 | :1026F000FEF70EFA2146074800F00AFE204670BD9C | ||
| 625 | :10270000284600F03FFAF9E732461F210248E2E787 | ||
| 626 | :102710007F350000F80B00209B350000EFF30880A8 | ||
| 627 | :102720007146EFF30982EFF30B830CB406B4FFF7A5 | ||
| 628 | :10273000AFFF8646009900F0080001F00801401A3A | ||
| 629 | :1027400002DC12DB04B070471EF020031CBF2DE931 | ||
| 630 | :10275000F00FBDF1080D0A4C254626462746A04637 | ||
| 631 | :10276000A146A246A34630B4704704B030BC1EF068 | ||
| 632 | :1027700020031CBF1DF1080DBDE8F00F04B0704729 | ||
| 633 | :10278000A5EDF5FE084BDA6882F07F4282F47F0205 | ||
| 634 | :1027900042F48042DA6000221A765A76DA76DA77E4 | ||
| 635 | :1027A000602283F82220704700ED00E0114BD3F83F | ||
| 636 | :1027B000882042F47002C3F88820BFF34F8FBFF324 | ||
| 637 | :1027C0006F8FD3F88C2042F44062C3F88C20D3F88A | ||
| 638 | :1027D000342242F08042C3F83422D3F8342242F04B | ||
| 639 | :1027E0003C42C3F834224FF0E022D36843F4200384 | ||
| 640 | :1027F000D360704700ED00E0009A164B9A4227D153 | ||
| 641 | :1028000001229043014641EC100B41EC110B41ECCD | ||
| 642 | :10281000120B41EC130B41EC140B41EC150B41EC8A | ||
| 643 | :10282000160B41EC170BEFF3148222F0040282F333 | ||
| 644 | :102830001488BFF36F8F02460346044605460646DA | ||
| 645 | :10284000074680468146824683468446864604473C | ||
| 646 | :10285000FEE70000A5EDF5FE2DE9F041044618B9AC | ||
| 647 | :1028600043F6DA30BDE8F0810029F9D0836800250D | ||
| 648 | :1028700013F4406F14BF01230023134F43F00203EE | ||
| 649 | :10288000DFF848800B6000F13006236AAB4201D8C4 | ||
| 650 | :102890000020E7E71421A369E26906EB830301FB4B | ||
| 651 | :1028A00002330C226A4399188968090709D59B5895 | ||
| 652 | :1028B000BB4201D04345D3D1186810B10121FFF7C5 | ||
| 653 | :1028C000A9F90135E1E700BFB4100020AC100020E9 | ||
| 654 | :1028D00070B5324C86B03248FFF76BFC2368012597 | ||
| 655 | :1028E0005A1C01932F4B2260DA681B694FF4407623 | ||
| 656 | :1028F000039300232A4801A902920495ADF81460BD | ||
| 657 | :102900008DF81630FFF716FC18B143F6DA3006B032 | ||
| 658 | :1029100070BD23688DF816005A1C0193224B204885 | ||
| 659 | :102920000293224B01A9CDE903352260ADF8146072 | ||
| 660 | :10293000FFF700FC0028E8D123688DF816005A1C28 | ||
| 661 | :1029400001931B4B164802931A4B01A9CDE903359D | ||
| 662 | :102950002260ADF81460FFF7EDFB0028D5D12368A5 | ||
| 663 | :102960008DF816005A1C0193134B0D480293134B1C | ||
| 664 | :1029700001A903930223049340F201132260ADF8EE | ||
| 665 | :102980001430FFF7D7FB04460028BED12A4629465B | ||
| 666 | :102990000348FFF759F92046B9E700BFBC190020EA | ||
| 667 | :1029A000A81000202C36000060360000005F0000F8 | ||
| 668 | :1029B0002006000020060000000C0020200C002053 | ||
| 669 | :1029C000014B1868704700BF2C360000014B1B6894 | ||
| 670 | :1029D000186870472C360000014B1B685868704718 | ||
| 671 | :1029E0002C36000008B5FFF749F9FFF79BF80A4BB2 | ||
| 672 | :1029F0005A68103AD3B2120609D401215A0903F0D9 | ||
| 673 | :102A00001F03994002F16003044A42F82310BDE815 | ||
| 674 | :102A1000084000F0A3BA00BF00ED00E000E100E0D4 | ||
| 675 | :102A20000020034BD8765A6A42F470225A627047EB | ||
| 676 | :102A300000ED00E00349044BCA68002092B2134342 | ||
| 677 | :102A4000CB60704700ED00E00800FA0500224FF06F | ||
| 678 | :102A5000FF300D4B02F1A0010132102A43F8210092 | ||
| 679 | :102A6000F8D1D3F88022002022F00802C3F8802297 | ||
| 680 | :102A7000D3F88022D3F8802222F40072C3F8802297 | ||
| 681 | :102A8000D3F88032704700BF00E100E008B5FFF7DF | ||
| 682 | :102A90002DF80822024BC3F880211A60002008BDDF | ||
| 683 | :102AA00000E100E0064BD3F8D02022F00102C3F889 | ||
| 684 | :102AB000D020D3F8D02042F00202C3F8D0207047D3 | ||
| 685 | :102AC00000ED00E037B50124FFF73EF8134D224634 | ||
| 686 | :102AD000052347F6FF7100200094FFF74DF82246CA | ||
| 687 | :102AE00007234FF000500E490094FFF75BF8D5E93B | ||
| 688 | :102AF0000101072300220094FFF73EF8072300227C | ||
| 689 | :102B0000084909480094FFF74DF82969E868013938 | ||
| 690 | :102B1000FFF762F8002003B030BD00BF2C36000084 | ||
| 691 | :102B2000FF7F0020FFFF03200080002038B5002435 | ||
| 692 | :102B30000E4D002155F8040B0134FFF779F81C2CD9 | ||
| 693 | :102B4000F7D10020012240F20111094BC3F88004A3 | ||
| 694 | :102B5000C3F88424C3F8C004C3F8C424054AC2F8E7 | ||
| 695 | :102B600040154FF48072C3F8402438BDBC350000D6 | ||
| 696 | :102B700000300050009003500122014B1A60704752 | ||
| 697 | :102B8000C019002010B50446094B228918686168F5 | ||
| 698 | :102B90000623806800F0E9FA28B9064B1B68012B70 | ||
| 699 | :102BA00001D100F087F86FF08603236010BD00BFED | ||
| 700 | :102BB000B0190020C01900202DE9F84305461E4633 | ||
| 701 | :102BC0000068134B9046AA68A0F1080440E902335C | ||
| 702 | :102BD000503890420F4601D200F0C0F9A4F14809E4 | ||
| 703 | :102BE00048220021484602F0C6FF002344E907338B | ||
| 704 | :102BF00044F8143C4FF0807344F8043C6FF0020337 | ||
| 705 | :102C000044E9036744F8208CC5E90093BDE8F883E4 | ||
| 706 | :102C1000A5EDF5FE30B5094C024661680023084673 | ||
| 707 | :102C200040B105686D68954205D11BB1826860604E | ||
| 708 | :102C30009A60816030BD03468068F1E7441A002045 | ||
| 709 | :102C400038B504462AB10B689B68DB0512D5002015 | ||
| 710 | :102C500038BD0B4B1D680DB900F080F900222B68C0 | ||
| 711 | :102C600099692C338A4203D053F8040FA04204D14F | ||
| 712 | :102C70009142ECD16FF0FC00EAE70132F2E700BFCD | ||
| 713 | :102C8000B019002070B504460E46154600213022CA | ||
| 714 | :102C90000C3002F070FF064B20461B68A660636094 | ||
| 715 | :102CA000656100F001FA00232061236070BD00BF60 | ||
| 716 | :102CB000B0190020044B1B681BB11B680BB158688E | ||
| 717 | :102CC00070474FF0FF307047B0190020064B10B529 | ||
| 718 | :102CD0001C680CB900F042F923689B6813F4406F3C | ||
| 719 | :102CE00014BF0120002010BDB01900202DE9F843C9 | ||
| 720 | :102CF000904607460C46FFF7E9FF024624B96FF0FD | ||
| 721 | :102D000080042046BDE8F8836300F8D5144B04F036 | ||
| 722 | :102D10001F0153F82150002DF1D02B682946586827 | ||
| 723 | :102D2000FFF78EFFB0B9C4F30721284600F001FB7E | ||
| 724 | :102D300004460028E3D1EFF3108972B600F0C1F920 | ||
| 725 | :102D4000064689F3108840B142462946FFF79AFFAC | ||
| 726 | :102D50003E60D6E76FF08104D3E76FF08204D0E7DE | ||
| 727 | :102D6000C41900202DE9F04100F0AAF90023134E08 | ||
| 728 | :102D7000134F73607B6000F0E5F8DFF84880304661 | ||
| 729 | :102D800000F022F80446A8B139468023424600F0FC | ||
| 730 | :102D90007FF80546204600F011FB206804F1080189 | ||
| 731 | :102DA000FFF75AFD08B100F0D9F829462046FFF791 | ||
| 732 | :102DB00041FCE4E7BDE8F04100F071B9B41900202E | ||
| 733 | :102DC000441A0020C4190020F8B5054608B900F0DF | ||
| 734 | :102DD000C5F82A4E346814F1290F4CD8284B1968CD | ||
| 735 | :102DE00004F128038B4246D2236AA26903EB430312 | ||
| 736 | :102DF0000C321344606AE269024402EB820213441B | ||
| 737 | :102E00009B00E31801D2994201D200F0A7F8236891 | ||
| 738 | :102E10001C4A1B0C1B04934201D000F09FF823882E | ||
| 739 | :102E2000B3F5817F01D300F099F86368002B01DAD4 | ||
| 740 | :102E300000F094F8144A176807F124031360134A4A | ||
| 741 | :102E40001268934201D900F089F8236AA26903EB62 | ||
| 742 | :102E500043030C32616A1344E2693C600A4402EBAA | ||
| 743 | :102E600082021344326802EB83026B6832603B6279 | ||
| 744 | :102E70006F603846F8BD0027FBE700BFC410002094 | ||
| 745 | :102E80004836000000005F5FC0100020443600009C | ||
| 746 | :102E90002DE9F74F0F4690460646009300B109B959 | ||
| 747 | :102EA00000F05CF8D6F800A0DAF818200AF1300338 | ||
| 748 | :102EB00003EB820BDAF81C40204B1D6854B10C2246 | ||
| 749 | :102EC00002FB04541C601E4B1B689C4201D900F09D | ||
| 750 | :102ED00045F82C4625464FF00009DAF81C204A45F3 | ||
| 751 | :102EE00000D91CB9002003B0BDE8F08F142303FB08 | ||
| 752 | :102EF00009B20023C5E900269268AB60930516D598 | ||
| 753 | :102F0000B8F1000F02D0009B802B03D0019200F09B | ||
| 754 | :102F100025F8019A12F0E00FD0B202D158F8202023 | ||
| 755 | :102F20001AB1019000F01AF8019848F820507A6818 | ||
| 756 | :102F300009F10109AA607D600C35CEE7BC100020C4 | ||
| 757 | :102F40004036000008B5FFF73BFD034B9860FFF7E4 | ||
| 758 | :102F50003DFD80F3888808BD00ED02E0FFF73CB935 | ||
| 759 | :102F60008230012808B506D8FFF7B0FE18B9BDE8D1 | ||
| 760 | :102F70000840FFF7F3BF08BDF8B506460D4600F060 | ||
| 761 | :102F8000EAF9044608B9FFF7E9FFA7680FB9FFF7A8 | ||
| 762 | :102F9000E5FFE368991C20D05A1C21D1A5B315F197 | ||
| 763 | :102FA000820F13D102232360EFF3108672B62946F5 | ||
| 764 | :102FB0002046FFF737FB054686F310882368022B6F | ||
| 765 | :102FC00024D1204600F086F82846F8BD15F1830F7D | ||
| 766 | :102FD000EAD0FFF7C3FF0025E6E702232360FAE704 | ||
| 767 | :102FE000002BF6DB204600F0DAF93B689B689B0576 | ||
| 768 | :102FF00001D50223236015F1810FD5D16369002B20 | ||
| 769 | :10300000D2DBFFF7ABFFCFE73546F4E700232360C1 | ||
| 770 | :10301000DAE708B5FFF7E0F86FF0830008BD2DE9A7 | ||
| 771 | :10302000F3410E46174698460546FFF74FFE00F05F | ||
| 772 | :10303000A6F92946024601A8FFF758FE044660B9E2 | ||
| 773 | :1030400043463A4631460198FFF774F9044640B1C9 | ||
| 774 | :103050006B0002D5019800F03DF8204602B0BDE8B3 | ||
| 775 | :10306000F0810198FFF7B6FA0446F6E740F2011046 | ||
| 776 | :10307000704770B50546FFF729FE06462846FFF75C | ||
| 777 | :10308000C9FD044608B9002070BD014632462846F5 | ||
| 778 | :10309000FFF7D6FD0028F6D12368D868F4E76FF073 | ||
| 779 | :1030A0000200704700DF70474FF480507047B0F562 | ||
| 780 | :1030B000805F03D1EFF30B808038704700207047AA | ||
| 781 | :1030C0007047EFF30B8000F1800383F30B887047A8 | ||
| 782 | :1030D00000207047EFF30B83803B83F30B8870472E | ||
| 783 | :1030E00080EA0000E1EE100A00EE100A00EE900AFD | ||
| 784 | :1030F00001EE100A01EE900A02EE100A02EE900AAA | ||
| 785 | :1031000003EE100A03EE900A04EE100A04EE900A91 | ||
| 786 | :1031100005EE100A05EE900A06EE100A06EE900A79 | ||
| 787 | :1031200007EE100A07EE900A08EE100A08EE900A61 | ||
| 788 | :1031300009EE100A09EE900A0AEE100A0AEE900A49 | ||
| 789 | :103140000BEE100A0BEE900A0CEE100A0CEE900A31 | ||
| 790 | :103150000DEE100A0DEE900A0EEE100A0EEE900A19 | ||
| 791 | :103160000FEE100A0FEE900A70472DE9F0410E465F | ||
| 792 | :103170001546002A4AD0C4074BD480F00204C4F399 | ||
| 793 | :103180004004A40003F00602062A4AD144F00104D8 | ||
| 794 | :1031900022462946304602F077FBB8BB46E800F2EB | ||
| 795 | :1031A00005EB0608100E120208F1FF3747E800F39E | ||
| 796 | :1031B0004FEA136166D51B0264D5884262D046E8A7 | ||
| 797 | :1031C00000F547E800F7FEF7A2FF2D0E85424FEA13 | ||
| 798 | :1031D000176734D3FEF79DFF874230D82846FEF7A5 | ||
| 799 | :1031E00091FF2246C6F101010144304602F04CFB3A | ||
| 800 | :1031F000002847D00135AF4218D83846FEF780FF87 | ||
| 801 | :103200002246A8EB000102F03FFBD8B30020BDE846 | ||
| 802 | :10321000F081EFF39484A40004F0040444F0120459 | ||
| 803 | :10322000B0E7990731D544F00804B1E72846FEF726 | ||
| 804 | :1032300067FF0646FEF76FFF22460146D5E7FEF719 | ||
| 805 | :1032400072FF85421ED3FEF770FF87421AD82846C8 | ||
| 806 | :10325000FEF7DAFC2246C6F101010144304602F0D5 | ||
| 807 | :1032600013FB78B10135AF4203D83846FEF756FF5D | ||
| 808 | :10327000C6E72846FEF752FF0646FEF758FF2246ED | ||
| 809 | :103280000146EBE76FF07F00C1E74CF2DA20BEE7C2 | ||
| 810 | :1032900010B50446FFF706FCFFF714FC10B143F627 | ||
| 811 | :1032A000DA3010BDFFF742FC0028F8D1FFF710FB21 | ||
| 812 | :1032B0000028F4D102232360F3E708B5FFF7B0FB41 | ||
| 813 | :1032C00010B143F6DA3008BDFFF7B4FB0028F8D19F | ||
| 814 | :1032D00000F01CF80028F4D162B6FDF703FCFFF7FC | ||
| 815 | :1032E000B5FB0028EDD1FFF7D1FB0028EBD0E8E7D4 | ||
| 816 | :1032F000EFF30880EFF309812DE9F00F6B4672467A | ||
| 817 | :10330000FDF746FB08B0FFF76DFBFEE700207047B6 | ||
| 818 | :1033100004460D46FFF7E4FEA54628470368283318 | ||
| 819 | :1033200083F30988836883F30B88BFF36F8F40684A | ||
| 820 | :10333000704703689A68DB6812F4806F05D18B428E | ||
| 821 | :103340002CBF00206FF0FA0070478B420CBF0020AA | ||
| 822 | :103350006FF0FA00704710B5FFF7A9FE0446FFF7BB | ||
| 823 | :10336000B7FE50B9FFF7A6FCA3685B681B685B68F3 | ||
| 824 | :10337000834218BF0024204610BD0024FBE738B567 | ||
| 825 | :10338000054648B100F01BF8B5EBD07F044601D0EC | ||
| 826 | :10339000FFF7E4FD204638BDFFF78CFCF4E700237F | ||
| 827 | :1033A00010B500F1280252F8041F19B1C16F146C56 | ||
| 828 | :1033B00019444C600833202BF5D110BD70474FF0F5 | ||
| 829 | :1033C000FF307047000001464154414C20455252A5 | ||
| 830 | :1033D0004F523A2000486172644661756C740D0A60 | ||
| 831 | :1033E000004D656D4D616E616765206661756C7439 | ||
| 832 | :1033F0000D0A004275734661756C740D0A005573B1 | ||
| 833 | :103400006167654661756C740D0A0053656375727A | ||
| 834 | :10341000654661756C740D0A005265736572766558 | ||
| 835 | :103420006420457863657074696F6E2000506C612C | ||
| 836 | :1034300074666F726D2065787465726E616C206958 | ||
| 837 | :103440006E7465727275707420284952516E293AF3 | ||
| 838 | :1034500020000000290B00000B1F0000D90D000008 | ||
| 839 | :103460008D0D0000331F00003F1F0000610B0000A6 | ||
| 840 | :103470000F1F0000490B0000550B0000150C000049 | ||
| 841 | :10348000151F0000211F0000271F00001D00000065 | ||
| 842 | :10349000100004001C0002001100060003020202DA | ||
| 843 | :1034A0000338FDD87047506C6174666F726D2045AB | ||
| 844 | :1034B0007863657074696F6E3A0D0A00416C6C2018 | ||
| 845 | :1034C00070696E732068617665206265656E206341 | ||
| 846 | :1034D0006F6E66696775726564206173206E6F6ECA | ||
| 847 | :1034E0002D7365637572650D0A00303132333435E2 | ||
| 848 | :1034F000363738394142434445461B5B313B333410 | ||
| 849 | :103500006D5B536563205468726561645D2053652B | ||
| 850 | :103510006375726520696D61676520696E6974699C | ||
| 851 | :10352000616C697A696E67211B5B306D0D0A00540E | ||
| 852 | :10353000462D4D20466C6F6174204142493A204827 | ||
| 853 | :103540006172640D0A004C617A7920737461636B57 | ||
| 854 | :10355000696E6720656E61626C65640D0A001B5BB5 | ||
| 855 | :10356000313B33346D426F6F74696E672054462D62 | ||
| 856 | :103570004D2076322E302E301B5B306D0D0A0055FB | ||
| 857 | :103580006E6B6E6F776E2053504D205356432072F2 | ||
| 858 | :1035900065717565737465643A2000556E6B6E6F66 | ||
| 859 | :1035A000776E20535643206E756D6265722072658A | ||
| 860 | :1035B000717565737465643A200000000040005026 | ||
| 861 | :1035C000005000500080005000A0005000B000509B | ||
| 862 | :1035D00000E0005000F000500000015000100150C9 | ||
| 863 | :1035E0000040015000500150007001500080015017 | ||
| 864 | :1035F00000B0015000C0015000D0015000E0015067 | ||
| 865 | :1036000000F0015000000250001002500020025053 | ||
| 866 | :103610000030025000400250006002500080025012 | ||
| 867 | :1036200000A002500090035000258450008000004C | ||
| 868 | :1036300000800000FFFF0F00007C00000080000001 | ||
| 869 | :0C3640002C1200201412002000020000D8 | ||
| 870 | :10366000009A204B9A4208D110B502F0A7FA02F056 | ||
| 871 | :10367000A9F906BC96460C46744702F0E3FA009A94 | ||
| 872 | :10368000184B9A4208D110B502F0A4FA02F09AF948 | ||
| 873 | :1036900006BC96460C46744702F0D4FA0CB4029A63 | ||
| 874 | :1036A000104B9A420CD14FF0004319430CBC10B59B | ||
| 875 | :1036B00000F09EF802F086F906BC96460C46744768 | ||
| 876 | :1036C00002F0C0FA009A074B9A4202D106490868F4 | ||
| 877 | :1036D000744702F0B7FA009A024B9A4200D174473D | ||
| 878 | :1036E00002F0B0FAA5EDF5FE801000200348044B6F | ||
| 879 | :1036F000834202D0034B03B118477047A811002042 | ||
| 880 | :10370000A8110020000000000548064B1B1AD90F25 | ||
| 881 | :1037100001EBA301491002D0034B03B118477047D6 | ||
| 882 | :10372000A8110020A81100200000000010B5064CD0 | ||
| 883 | :10373000237843B9FFF7DAFF044B13B10448AFF322 | ||
| 884 | :1037400000800123237010BDC0180020000000007D | ||
| 885 | :10375000EC5E000008B5044B1BB104490448AFF30C | ||
| 886 | :103760000080BDE80840CFE700000000C41800203A | ||
| 887 | :10377000EC5E0000A3F5803A704700BF174B002BAA | ||
| 888 | :1037800008BF134B9D46FFF7F5FF00218B460F4600 | ||
| 889 | :103790001348144A121A02F0EEF90E4B002B00D017 | ||
| 890 | :1037A00098470D4B002B00D09847002000210400C3 | ||
| 891 | :1037B0000D000D48002802D00C48AFF3008002F045 | ||
| 892 | :1037C000DBF820002900FEF775FD02F0C1F800BF0C | ||
| 893 | :1037D000000008000000000000000000F80B0020BE | ||
| 894 | :1037E000A8110020B8280020000000000000000000 | ||
| 895 | :1037F0002DE9F84304460D4616461F46EFF30583B0 | ||
| 896 | :10380000C3F308030BB1FFF7A9FBDFF834903B4685 | ||
| 897 | :10381000204632462946D9F80080FFF700FCD9F847 | ||
| 898 | :1038200000300446984506D0DB6901461869BDE8BA | ||
| 899 | :10383000F843FFF7A1BBFFF793FB2046BDE8F883F1 | ||
| 900 | :10384000B019002001680E4A0346914215D1C169A2 | ||
| 901 | :10385000A2F11022A2F1EF1291420ED18268012A48 | ||
| 902 | :103860000BD8C26812B101698A4206D0586928B1E2 | ||
| 903 | :103870009B691B1A5842584170470120704700BF8E | ||
| 904 | :1038800055AA00FF0D4B70B59E68A6B13046FFF7F4 | ||
| 905 | :10389000D9FF044678B9F3686BB935690DB920468C | ||
| 906 | :1038A00070BD2846FFF7CEFF28B9EB68B34202D1BE | ||
| 907 | :1038B0002E462D69F2E70124F1E700BF4C1A0020E3 | ||
| 908 | :1038C0002DE9F041394E3468F368D4B1B468C4B11D | ||
| 909 | :1038D000002861D000295FD001FB00F5B5FBF0F0B6 | ||
| 910 | :1038E000884259D1291D57D8AA070DD025F00302C7 | ||
| 911 | :1038F00004321C4603E0616891424FD2A469002C57 | ||
| 912 | :10390000F9D12046BDE8F0812A46F2E7891A232939 | ||
| 913 | :1039100004F12007D4E9050C1AD80123A360A0B153 | ||
| 914 | :10392000C0F818C0A36903B158610023C4E9053386 | ||
| 915 | :103930003369DB0702D5FFF7A5FFA0BB2A460021AC | ||
| 916 | :1039400038463C4602F017F9DBE7C6F80CC0E9E759 | ||
| 917 | :1039500002F1200804EB08032039C3E9011E2169A4 | ||
| 918 | :10396000DFF84CE0DC60196144F808E0AEF1102E9D | ||
| 919 | :10397000AEF1EF1EC3F81CE001B1CB60C3E9050C4A | ||
| 920 | :1039800040B18361996901B14B6101212361C4E9AF | ||
| 921 | :103990000121CAE7F360F5E70024B2E7D4F808E0B4 | ||
| 922 | :1039A000BEF1000FB2D0012001F0D2FF4C1A00206E | ||
| 923 | :1039B00055AA00FFF8B5054600283AD0364E3368C0 | ||
| 924 | :1039C000002B36D0B268002A33D0834203D8726805 | ||
| 925 | :1039D0001344984202D3012001F0BAFFA0F1200461 | ||
| 926 | :1039E0002046FFF72FFF0028F5D155F8183C012B92 | ||
| 927 | :1039F000F1D145F8180C55E90570DFB1BB68CBB9BA | ||
| 928 | :103A000055F81C2C7B68203213447B60386100B170 | ||
| 929 | :103A1000C76020220021204602F0ADF8386908B1C5 | ||
| 930 | :103A200083682BB333699B0703D5FFF72BFF00286F | ||
| 931 | :103A3000D1D1F8BD40B3836833BB42686368134497 | ||
| 932 | :103A4000203363600369D4E90521236192B9B9B9D0 | ||
| 933 | :103A5000426981696261A161A2B19461A26902B106 | ||
| 934 | :103A6000546103B1DC602022002102F084F8D9E720 | ||
| 935 | :103A70003C46E2E79161A1690029E9D04A61E7E7A4 | ||
| 936 | :103A8000F160F8E7F460E9E7F36845F8083C03B152 | ||
| 937 | :103A90005C61F460C6E700BF4C1A002038B50D46E3 | ||
| 938 | :103AA000142200210446124802F065F81149124818 | ||
| 939 | :103AB00000F02CF8232D1AD914F003031FBF043D86 | ||
| 940 | :103AC000ED18C3F10403E4182A460021204602F051 | ||
| 941 | :103AD00052F8074B094AC3E900459C602260A2F1F5 | ||
| 942 | :103AE0001022203DA2F1EF126560E261DC6038BD7A | ||
| 943 | :103AF0004C1A0020B5390000C138000055AA00FF5B | ||
| 944 | :103B0000014B1B68184700BFC8100020024B18600B | ||
| 945 | :103B1000024B002019607047CC100020C810002014 | ||
| 946 | :103B200010B50A46044619B1024B00211B6898479C | ||
| 947 | :103B300010BD00BFD0100020054B0A46197819B1FE | ||
| 948 | :103B40000146181D02F0B8B86FF08800704700BF3A | ||
| 949 | :103B5000601A002010B5074C00F032F8204602F041 | ||
| 950 | :103B6000BCF8201F0821FFF7DBFFBDE8104002F082 | ||
| 951 | :103B7000A0B800BF641A002070B50C4D2B787BB93B | ||
| 952 | :103B800002F095F8044670B90126281D6E7002F007 | ||
| 953 | :103B900091F8044638B900F00BF8044618B92E70B5 | ||
| 954 | :103BA0000024204670BDFFF7D5FFFAE7601A002019 | ||
| 955 | :103BB0000122024B002083F880257047681A0020FC | ||
| 956 | :103BC000F8B5074C2025264601272046276202F03B | ||
| 957 | :103BD0005DF8013D04F12C04F7D186F88055F8BD5D | ||
| 958 | :103BE000681A002010B50C4C236813B10B4B1B68EE | ||
| 959 | :103BF0002BB900F089FC30B90122084B1A6001236F | ||
| 960 | :103C00002360002010BD0138062801D9044810BDEA | ||
| 961 | :103C1000044B53F8200010BD042000200020002099 | ||
| 962 | :103C2000FE8FFFFF545D0000144B2DE9F043002888 | ||
| 963 | :103C300014BF04461C46124F236883B0BB4219D000 | ||
| 964 | :103C400016460D4620464FF4147104F1040900F0A5 | ||
| 965 | :103C500047F804F58E78484600F0CEF8404600F06C | ||
| 966 | :103C600019FA2B464A4640460649009600F034FBB6 | ||
| 967 | :103C700008B92760002003B0BDE8F08308200020C9 | ||
| 968 | :103C8000A5BCC95A7D3E000070B50D4C1D460028EC | ||
| 969 | :103C900014BF064626460B4B306882B098420DD1C1 | ||
| 970 | :103CA00006F58E70002633460096144600F03EFB63 | ||
| 971 | :103CB000002818BF34462C6002B070BD0248FBE7F4 | ||
| 972 | :103CC00008200020A5BCC95AE88FFFFF38B131B1E8 | ||
| 973 | :103CD000002201440346013081421A70FAD1704734 | ||
| 974 | :103CE00038B131B1002201440346013088421A70D4 | ||
| 975 | :103CF000FAD170472DE9F043202B1D460646884631 | ||
| 976 | :103D000091468BB026D8DBB202AF8DF80480B04666 | ||
| 977 | :103D100058F8041B8DF8053021B9404601F038F9F8 | ||
| 978 | :103D2000044640B9012302224046336001A901F054 | ||
| 979 | :103D300043F9044638B138462021FFF7D1FF204629 | ||
| 980 | :103D40000BB0BDE8F0832A464946404601F034F9FD | ||
| 981 | :103D50000446F0E702AF1946104600233A4601F048 | ||
| 982 | :103D6000B1FA04460028E6D12023B9461D46CCE727 | ||
| 983 | :103D70002DE9F041D0F8F830A6B0002BD8BF02AE44 | ||
| 984 | :103D800031DD05460027D0F80C4102AEA4F1010850 | ||
| 985 | :103D90009022D5F8FC403146D0F8000101AB0197E4 | ||
| 986 | :103DA000B8FA88F8A0474FEA5818044620B9019B92 | ||
| 987 | :103DB00053B9B8F1000F16D030469021FFF790FFAD | ||
| 988 | :103DC000204626B0BDE8F081014632462846FFF77E | ||
| 989 | :103DD00091FF58B9D5F80431019A1344C5F804315C | ||
| 990 | :103DE000B8F1000FE8D16FF03C04E5E70446204647 | ||
| 991 | :103DF00026B0BDE8F08100BF70B50025044614224E | ||
| 992 | :103E000004F588762946C0F8F850FC3001F0B3FE7E | ||
| 993 | :103E100008222946304601F0AEFE144B30461B689E | ||
| 994 | :103E20009847204640F8045B01F098F8104B304664 | ||
| 995 | :103E30001B689847C8B9D4F8F830AB420FDC03EBE5 | ||
| 996 | :103E4000830204EB82022021C2F800010120C2E9B2 | ||
| 997 | :103E5000421008490133C2F8FC10C4F8F830064B90 | ||
| 998 | :103E60003046BDE870401B68184770BDF010002058 | ||
| 999 | :103E7000EC100020614E0000E81000202DE9F04712 | ||
| 1000 | :103E8000202A88B07AD83F4B00F5887904461B6811 | ||
| 1001 | :103E900048461746884698470546F8B940F2011645 | ||
| 1002 | :103EA000D4F8F830002B65D02046FFF761FF0546B7 | ||
| 1003 | :103EB00038B9D4F8F830002B14DC013EF2D16FF0A1 | ||
| 1004 | :103EC0003B056E4620213046FFF70AFF2E4B484641 | ||
| 1005 | :103ED0001B689847002818BF6FF01D05284608B0DA | ||
| 1006 | :103EE000BDE8F087D4E94132934203D3D4F80C21E2 | ||
| 1007 | :103EF000012A02D0013ED7D1E1E71F2BFAD96E4645 | ||
| 1008 | :103F000001462022304604F1040A01F034FE314615 | ||
| 1009 | :103F1000504601F07BF805460028D3D1504601F009 | ||
| 1010 | :103F200031F8504601F01AF82946504601F030F8B1 | ||
| 1011 | :103F300005460028C6D150462022314601F03CF803 | ||
| 1012 | :103F400005460028BED1034632462021304601F006 | ||
| 1013 | :103F5000B9F905460028B5D1D4F8F8303A46002B17 | ||
| 1014 | :103F6000C8BF002340463146C8BFC4F8043101F041 | ||
| 1015 | :103F7000DDFDA7E76FF03F056E46A3E76FF03B0559 | ||
| 1016 | :103F8000ACE700BFEC100020E810002070B590B046 | ||
| 1017 | :103F900000287AD03E4C0D46402236210646204667 | ||
| 1018 | :103FA00001F0E9FD40225C21A01801F0E4FD2B1D89 | ||
| 1019 | :103FB000A34203D904F144039D4252D32B682268E3 | ||
| 1020 | :103FC000534023602B68226C534023646B68626803 | ||
| 1021 | :103FD000534063606B68626C53406364AB68A26873 | ||
| 1022 | :103FE0005340A360AB68A26C5340A364EB68E268E3 | ||
| 1023 | :103FF0005340E360EB68E26C5340E3642B69226951 | ||
| 1024 | :1040000053402361226D2B695340236562696B69BC | ||
| 1025 | :10401000534063616B69626D53406365AB69A2692C | ||
| 1026 | :104020005340A361AB69A26D5340A365EB69E2699C | ||
| 1027 | :104030005340E361EB69E26D5340E3650021304694 | ||
| 1028 | :1040400000F0A6FF044628B940223046104900F08F | ||
| 1029 | :10405000B3FF044640216846FFF742FE204610B0F9 | ||
| 1030 | :1040600070BD631E04F13F01013D1F3415F8010FBF | ||
| 1031 | :1040700013F8012F42401A7011F8012F2878A3423B | ||
| 1032 | :1040800082EA00020A70F1D1D8E76FF07304E5E725 | ||
| 1033 | :104090005822002010B54FF49A720021044601F016 | ||
| 1034 | :1040A0006AFD42F21072044BC4F8202104F59670A8 | ||
| 1035 | :1040B0001B68BDE810401847F01000202DE9F04FB4 | ||
| 1036 | :1040C00004468846914695B0002900F0A780002A52 | ||
| 1037 | :1040D0000CBF0126022600238DF80C30002C00F0C6 | ||
| 1038 | :1040E0009F80DFF844A104AF0AF1400B0021204675 | ||
| 1039 | :1040F00000F04EFF034648B1384620210193FFF7F8 | ||
| 1040 | :10410000EFFD019B184615B0BDE8F08F40225146E7 | ||
| 1041 | :10411000204600F051FF03460028EDD104F1F405DC | ||
| 1042 | :1041200020222946204600F047FF03460028E3D11D | ||
| 1043 | :104130000122204603A900F03FFF03460028DBD1FF | ||
| 1044 | :10414000022E62D020460CA900F060FF0346002832 | ||
| 1045 | :10415000D2D10146204600F01BFF03460028CBD1F8 | ||
| 1046 | :1041600040225946204600F027FF03460028C3D1CD | ||
| 1047 | :10417000202220460CA900F01FFF03460028BBD1D7 | ||
| 1048 | :104180003946204600F042FF03460028B4D13946A4 | ||
| 1049 | :104190002046FFF7FBFE03460028ADD1202229462A | ||
| 1050 | :1041A000204600F009FF03460028A5D120460CA9AF | ||
| 1051 | :1041B00000F02CFF034600289ED10146204600F067 | ||
| 1052 | :1041C000E7FE0346002897D140225946204600F0DA | ||
| 1053 | :1041D000F3FE034600288FD1202220460CA900F0D0 | ||
| 1054 | :1041E000EBFE0346002887D12946204600F00EFF4B | ||
| 1055 | :1041F0000346002880D19DF80C200132D2B2B24291 | ||
| 1056 | :104200008DF80C20FFF472AF76E74A46414620460F | ||
| 1057 | :1042100000F0D2FE0346002894D06DE701265AE74D | ||
| 1058 | :104220006FF0730304AF67E7582200202DE9F041D7 | ||
| 1059 | :104230000446884615461F46D0F81801E0B013B171 | ||
| 1060 | :1042400000EB40004008B5F5807F3ED82844B0F52B | ||
| 1061 | :10425000C07F3AD84FF4C0720021684601F08BFC51 | ||
| 1062 | :104260006946D4F82431D4F81821D4F828019847A5 | ||
| 1063 | :1042700070BBD4F8186157B1D4E9493072080DEB1E | ||
| 1064 | :104280000601984720BBD4F8183106EB5306B8F165 | ||
| 1065 | :10429000000F00D08DB9324669462046FFF70EFF69 | ||
| 1066 | :1042A000054610B90123C4F8143131466846FFF7BA | ||
| 1067 | :1042B00017FD284660B0BDE8F0810DEB06004146D1 | ||
| 1068 | :1042C0002A462E4401F032FCE5E76FF00405F0E7E2 | ||
| 1069 | :1042D0006FF00805EDE700BF2DE9F047044604F153 | ||
| 1070 | :1042E000F4050F4691461E46DDF8208000F036FEAC | ||
| 1071 | :1042F00029462046FFF74AFE08B1BDE8F087284668 | ||
| 1072 | :104300002022012101F037FCD4F81831C4F82471BF | ||
| 1073 | :10431000C4F8289113B92023C4F818314246314615 | ||
| 1074 | :104320002046BDE8F0470123FFF780BFB2F5806F5C | ||
| 1075 | :1043300000F295802DE9F04F89B09A46129BB3F5B3 | ||
| 1076 | :10434000807F00F29080D0F82431164604460F4654 | ||
| 1077 | :104350004BB3D0F81C31012B05D0D0F81421D0F884 | ||
| 1078 | :1043600020319A421FDD514600232046129AFFF762 | ||
| 1079 | :104370005DFF014698B900231293002E5ED0DFF84E | ||
| 1080 | :10438000EC9009F1400B0021204600F001FE202EA8 | ||
| 1081 | :104390003546014628BF202504F1F40890B10846AF | ||
| 1082 | :1043A00009B0BDE8F08FBAF1000FE6D0129B002BE8 | ||
| 1083 | :1043B000E1D051461A462046FFF780FE014600280C | ||
| 1084 | :1043C000DBD0ECE749464022204600F0F5FD0146EF | ||
| 1085 | :1043D0000028E4D141462022204600F0EDFD0146B0 | ||
| 1086 | :1043E0000028DCD16946204600F010FE0146002876 | ||
| 1087 | :1043F000D5D1204600F0CCFD01460028CFD159464A | ||
| 1088 | :104400004022204600F0D8FD01460028C7D1694669 | ||
| 1089 | :104410002022204600F0D0FD01460028BFD14146B1 | ||
| 1090 | :10442000204600F0F3FD01460028B8D138462A4660 | ||
| 1091 | :10443000414601F07BFB761B2F44A4D15146204618 | ||
| 1092 | :10444000129AFFF73BFE01460028A8D10846D4F88F | ||
| 1093 | :1044500014310133C4F8143109B0BDE8F08F6FF0A6 | ||
| 1094 | :104460000201084670476FF0040198E758220020C7 | ||
| 1095 | :10447000002130B58DB0282202A8019101F07BFB0C | ||
| 1096 | :1044800002A800F047FF044610B120460DB030BD31 | ||
| 1097 | :10449000174D4FF0FF31286800F042F9044620B173 | ||
| 1098 | :1044A000144800F0D3F9012C18D0002000F068F96E | ||
| 1099 | :1044B000D0B9114A02A901A800F0C4FC04460120A9 | ||
| 1100 | :1044C00000F05EF960B9286800F032F90028DCD00D | ||
| 1101 | :1044D0000A4800F0BBF920460DB030BD0524F2E7D4 | ||
| 1102 | :1044E000074800F0B3F9EEE7064800F0AFF9E0E75F | ||
| 1103 | :1044F000D4100020705D0000D8220020C85D0000AC | ||
| 1104 | :10450000A85D0000885D000030B583B000F05CF865 | ||
| 1105 | :1045100028B100F0ABF80324204603B030BD00F012 | ||
| 1106 | :1045200077F8D8B900F02CF9E0B9224CD4F8283942 | ||
| 1107 | :104530001B0EF02B0AD1D4F8242A1F4B9A4231D0FB | ||
| 1108 | :1045400000F044F8072400F091F8E5E7062400F0B5 | ||
| 1109 | :104550003DF800F08BF8204603B030BD042420461F | ||
| 1110 | :1045600003B030BD00F032F800F080F8FFF780FFB4 | ||
| 1111 | :10457000044698B9114D2B68002BCDD10246014657 | ||
| 1112 | :10458000FFF752FB50B968220D4901ABFFF77CFBE6 | ||
| 1113 | :1045900020B920460B4B2B6003B030BD05242046CC | ||
| 1114 | :1045A00003B030BD012000F0EBF80028DAD1C4F8E8 | ||
| 1115 | :1045B0000C0ADBE7001084500000E020F824002003 | ||
| 1116 | :1045C000FC2400205AEA5A5A002070470020704705 | ||
| 1117 | :1045D000430504D54FF0FF32034BC3F80821024BCB | ||
| 1118 | :1045E000C3F8080A704700BF00108450014BC3F89D | ||
| 1119 | :1045F000040A70470010845008B100F06BB84FF403 | ||
| 1120 | :104600007500704708B100F04FB84FF4750070475F | ||
| 1121 | :1046100010B5114800F070F800B110BD0F4800F05F | ||
| 1122 | :104620006BF80028F9D10E4C204600F065F8002800 | ||
| 1123 | :10463000F3D10C4B0C481C6000F05EF801460028DA | ||
| 1124 | :10464000EBD100F02DF8044608B1204610BD00F073 | ||
| 1125 | :1046500079F82046FAE700BFE4100020E0100020BF | ||
| 1126 | :10466000DC100020D4100020D810002008B5084825 | ||
| 1127 | :1046700000F04CF8074800F049F8074800F046F809 | ||
| 1128 | :10468000064800F043F8BDE8084000F00BB800BF52 | ||
| 1129 | :10469000E4100020E0100020DC100020D8100020E2 | ||
| 1130 | :1046A00000207047704700BF024610B4084CD4F891 | ||
| 1131 | :1046B000003A1342FBD021B1D4F804310B60C4F8A6 | ||
| 1132 | :1046C0000831034B0020C3F8082A5DF8044B7047FB | ||
| 1133 | :1046D00000108450044AD2F8003A1842FBD0C2F8C5 | ||
| 1134 | :1046E000080A0020704700BF0010845001F0E8B9AC | ||
| 1135 | :1046F0000A46002101F03FBA08B5034B02681B6867 | ||
| 1136 | :1047000010689847002008BD1011002008B5034B21 | ||
| 1137 | :1047100002685B6810689847002008BD10110020EF | ||
| 1138 | :10472000024B02689B681068184700BF10110020F8 | ||
| 1139 | :1047300008B5034B0268DB6810689847002008BD85 | ||
| 1140 | :104740001011002070B5094C094D2069AB689847DD | ||
| 1141 | :1047500018B1084B08485B6898470021074AEB6886 | ||
| 1142 | :1047600011602069BDE87040184700BFFC100020B0 | ||
| 1143 | :1047700010110020F4100020E05D000064250020EE | ||
| 1144 | :10478000F8B51A4D1A4E0446B26828699047E8B940 | ||
| 1145 | :10479000184F3B684CB1A3B1012B19D0013B3B60D2 | ||
| 1146 | :1047A0002869F36898470020F8BD43B90121124AEF | ||
| 1147 | :1047B000C2F800151149D1F81029002AFBD10133A4 | ||
| 1148 | :1047C0003B60F368286998470020F8BD0C48F8BDA5 | ||
| 1149 | :1047D0000A4AD2F81039002BFBD1074A6FF07E400D | ||
| 1150 | :1047E000C2F80035FFF702FF3B68D7E7FC10002056 | ||
| 1151 | :1047F0001011002064250020000084500010845017 | ||
| 1152 | :10480000E98FFFFF014B1B68184700BF1011002004 | ||
| 1153 | :10481000014B9B68184700BF10110020014BDB685B | ||
| 1154 | :10482000184700BF10110020BFF34F8F0549064BFA | ||
| 1155 | :10483000CA6802F4E0621343CB60BFF34F8F00BF3E | ||
| 1156 | :10484000FDE700BF00ED00E00400FA0530B44FF0D2 | ||
| 1157 | :10485000FE320025074B084C08494968C3F800247C | ||
| 1158 | :10486000C3F80424C3F80824C3F80C24C4F8005582 | ||
| 1159 | :1048700030BC08470010845000008450F410002021 | ||
| 1160 | :1048800010B5044650B1636813F0685F05D0064A5E | ||
| 1161 | :10489000934202D000236260236010BD034B0448A2 | ||
| 1162 | :1048A0005B689847EFE700BF2C5F5CA9F41000201D | ||
| 1163 | :1048B000005E0000C8B143680D4A934213D013F064 | ||
| 1164 | :1048C000685F0ED0012350E8002F194640E8001C15 | ||
| 1165 | :1048D0009CF0000FF7D1012AF5D0BFF35F8F0020C5 | ||
| 1166 | :1048E000704704487047044870476FF4E0407047D1 | ||
| 1167 | :1048F0002C5F5CA9E98FFFFFEA8FFFFF034680B1C1 | ||
| 1168 | :10490000426809498A420AD012F0685F05D0BFF3B5 | ||
| 1169 | :104910005F8F002210461A607047044870470448B1 | ||
| 1170 | :1049200070476FF4E04070472C5F5CA9E98FFFFF90 | ||
| 1171 | :10493000EA8FFFFF10B5044620B10023034A23602D | ||
| 1172 | :10494000626010BD0248FFF781FFF6E73A00003AC7 | ||
| 1173 | :10495000285E00002DE9F047002878D00C46002999 | ||
| 1174 | :1049600075D01D46002B72D007461AB101220023D4 | ||
| 1175 | :104970002A6003602B68002B64D02946204600F093 | ||
| 1176 | :10498000B7FD804600285FD12146286800F096FDDB | ||
| 1177 | :104990008046002858D12B68082B6CD0042B6DD092 | ||
| 1178 | :1049A000A3F10209B9FA89F94FEA59190121354EE3 | ||
| 1179 | :1049B000C6F8C411C6F84011C6F8C411636AC6F837 | ||
| 1180 | :1049C0003031D6F830219342F6D14FF0000A4FF043 | ||
| 1181 | :1049D000FF30C6F82CA1FFF7FBFD6FF01B0350461C | ||
| 1182 | :1049E000C6F80031FFF702FEC6F80C91D6F8040AAB | ||
| 1183 | :1049F00040F48060FFF7FAFD0A23C6F83831089BBF | ||
| 1184 | :104A0000012B29D02369204AA2FB03231B09626AD8 | ||
| 1185 | :104A1000404602FB03F303EB43031A4ADB039B0903 | ||
| 1186 | :104A2000C2F8D8310123C2F82C313B682A6823F040 | ||
| 1187 | :104A30007F4343EA02633B602A6843EA02233B6008 | ||
| 1188 | :104A4000BDE8F087DFF844804046BDE8F087DFF836 | ||
| 1189 | :104A500040804046BDE8F0874FF47F03D3F80C2C2C | ||
| 1190 | :104A6000013206D0D3F80C3C074AA2FB03231B09F2 | ||
| 1191 | :104A7000CDE71623CBE74FF0030997E74FF0020984 | ||
| 1192 | :104A800094E700BF00108450ABAAAAAA310CF10031 | ||
| 1193 | :104A9000350CF10058B34B1EB3F5047F27D230B567 | ||
| 1194 | :104AA0004FF0000ECD00744671464B0901F01F0C0B | ||
| 1195 | :104AB00050F82330BCF11F0F23FA0CF306D003F09B | ||
| 1196 | :104AC000010319B901211C468E46EEE79C4201F113 | ||
| 1197 | :104AD000010106D01C464FF0010EA942E5D100208D | ||
| 1198 | :104AE00030BD0EF1010E9645F7D1024830BD0148A8 | ||
| 1199 | :104AF000704700BF360CF100C0B32DE9F0434C1EE7 | ||
| 1200 | :104B0000B4F5047F1DD2E3B1DAB100252E46A846E4 | ||
| 1201 | :104B10002C46CF0003F1FF394FEA541C04F01F0E5E | ||
| 1202 | :104B200050F82C10BEF11F0F21FA0EFC0CD00CF027 | ||
| 1203 | :104B3000010C4CB90126E04634463546ECE7964276 | ||
| 1204 | :104B400016D90C48BDE8F083AB420BD0C44508BF72 | ||
| 1205 | :104B50000136A945F3D001350134BC42DCD1002037 | ||
| 1206 | :104B6000BDE8F0830125E0462E46F5E70148704791 | ||
| 1207 | :104B70001D46F1E7370CF1002DE9F04F91B0834667 | ||
| 1208 | :104B8000DDE91B460D46002E6ED10F691C60002327 | ||
| 1209 | :104B90001A990B60002A00F02F819D4B6A6AD3F8A6 | ||
| 1210 | :104BA0003811D3F830319A4269D10A2967D19BF87C | ||
| 1211 | :104BB0000330089304F10803079304230593954BEE | ||
| 1212 | :104BC000934CA3FB07239B0803EB4303A7EB43038F | ||
| 1213 | :104BD000039306971A9B069E1E60002E00F0EA8043 | ||
| 1214 | :104BE00000F096FC00230993BBF1000F00F0D58084 | ||
| 1215 | :104BF00098464FF0010ADDF81C90002D00F0CD80A2 | ||
| 1216 | :104C0000089B002B3DD0284608A900F071FC002825 | ||
| 1217 | :104C100039D0814B984220D0089B082B00F0E480CB | ||
| 1218 | :104C200000225B000893294608AB58460092FFF724 | ||
| 1219 | :104C300091FE7A4B984200F0D38070B9DBF80020E7 | ||
| 1220 | :104C4000130A03F47F03134323F07F43CBF80030B0 | ||
| 1221 | :104C5000059B013B0593BDD10020039000F058FC5B | ||
| 1222 | :104C6000039811B0BDE8F08F4FF47F01D1F80C0C20 | ||
| 1223 | :104C700001300CBF4FF40477D1F80C7C86E768480C | ||
| 1224 | :104C8000EBE76648C5E72946089800F017FC0028BE | ||
| 1225 | :104C9000BFD1089B082B00F0A980042B00F0A9804D | ||
| 1226 | :104CA000A3F10203B3FA83F35B090493C4F8C4A12C | ||
| 1227 | :104CB000C4F840A1C4F8C4A16B6AC4F83031D4F878 | ||
| 1228 | :104CC00030219342F6D100234FF0FF30C4F82C314D | ||
| 1229 | :104CD000FFF77EFC002318466FF01B03C4F8003179 | ||
| 1230 | :104CE000FFF784FC049B4B4FC4F80C31D4F8040A42 | ||
| 1231 | :104CF00040F48060FFF77AFC0A23C4F838312B694E | ||
| 1232 | :104D000009A8A7FB03236A6A1B0902FB03F303EB51 | ||
| 1233 | :104D10004303DB039B09C4F8D831C4F82CA1DBF8AA | ||
| 1234 | :104D20000030089923F07F420B0243EA01631343EA | ||
| 1235 | :104D3000CBF8003000F0B2FB099B03F01A030343E9 | ||
| 1236 | :104D40007FF46AAFA7FB0637D4F81431B8EB970F9E | ||
| 1237 | :104D50000A93D4F818310B93D4F81C310C93D4F87F | ||
| 1238 | :104D600020310D93D4F824310E93D4F828310F93C9 | ||
| 1239 | :104D700001D1039B9BB9484618220AA9183EFFF7A8 | ||
| 1240 | :104D8000B5FC09F1180908F101089EB100F0C0FB5B | ||
| 1241 | :104D900000230993002D7FF433AF224839E74846BA | ||
| 1242 | :104DA0001A46F61A0AA9994408F10108FFF79EFC71 | ||
| 1243 | :104DB000002EEBD1069F079E6A6939463046FFF701 | ||
| 1244 | :104DC00069FEAA6940B94FF4806339463046FFF75F | ||
| 1245 | :104DD00093FE00283FF440AF00231A9A136018E7AF | ||
| 1246 | :104DE0002B6A002B3FF439AF0F4836E703230493B7 | ||
| 1247 | :104DF0005CE70223049359E70122294658460096AE | ||
| 1248 | :104E000008ABFFF7A7FD00283FF4D4AE25E700BFAD | ||
| 1249 | :104E100000108450ABAAAAAA020CF100310CF100D8 | ||
| 1250 | :104E2000300CF100350CF100320CF10030B4DDE94A | ||
| 1251 | :104E3000023402940024049DCDE9035430BCFFF7F2 | ||
| 1252 | :104E40009BBE00BF30B51546012487B005AB00936B | ||
| 1253 | :104E50000022CDE9015404ABFFF78EFE07B030BD50 | ||
| 1254 | :104E6000F0B587B0002966D01E46002B63D01446EB | ||
| 1255 | :104E7000002A60D0314F0D4638684FF0FF31FFF700 | ||
| 1256 | :104E80004FFC00284DD10020FFF77AFC002844D1C8 | ||
| 1257 | :104E90002B4800F03FFAD8B101204FF0FF35FFF763 | ||
| 1258 | :104EA0006FFC002835D14FF408712648FEF70EFF3D | ||
| 1259 | :104EB00004212548FEF70AFF21482821FEF706FFB6 | ||
| 1260 | :104EC0003868FFF735FC00282FD1284607B0F0BD21 | ||
| 1261 | :104ED0001C4A0346029205AA019204AA039000927A | ||
| 1262 | :104EE000174902461848FFF7A1FF03460028D3D10F | ||
| 1263 | :104EF00028461D46059B22469C4228BF1A46049917 | ||
| 1264 | :104F000032600831FFF7F2FB0120FFF739FC00287F | ||
| 1265 | :104F1000C9D00E48FFF79AFCC5E70D48FFF796FC8D | ||
| 1266 | :104F2000B6E70C48FFF792FCADE70B48FFF78EFCA5 | ||
| 1267 | :104F3000284607B0F0BD4FF0FF35C6E7D41000207B | ||
| 1268 | :104F40007C250020A425002078250020A85D0000F5 | ||
| 1269 | :104F5000885D0000705D00004C5E000010B50446E6 | ||
| 1270 | :104F600028B12046BDE81040F421FFF7C1BB04483A | ||
| 1271 | :104F7000FFF76CFC2046BDE81040F421FFF7B8BBFA | ||
| 1272 | :104F8000645E000010B1F421FEF7A0BE704700BFC0 | ||
| 1273 | :104F900008B521B1012908D06FF0360008BD012104 | ||
| 1274 | :104FA00000F058F80028F7D108BD022100F052F8AF | ||
| 1275 | :104FB0000028F9D0F0E700BF30B505468818B0F5F5 | ||
| 1276 | :104FC000801F0B461446A1B001D8802A0CD9B3F536 | ||
| 1277 | :104FD000801F17D922461946284600F07DF804465E | ||
| 1278 | :104FE00084B9204621B030BD6846FFF77FFB2246DA | ||
| 1279 | :104FF0006946284600F070F8802104466846FFF7AD | ||
| 1280 | :1050000077FBEDE76FF03604EBE700BF70B5E8B172 | ||
| 1281 | :105010000E46D9B1044600F031F80546B0B9236810 | ||
| 1282 | :10502000012B0BD0022B01D0284670BD1C2230462C | ||
| 1283 | :1050300004F10801FFF75AFB284670BD20223046D4 | ||
| 1284 | :1050400004F10801FFF752FB284670BD6FF03605EA | ||
| 1285 | :10505000EAE700BF78B138B50D46F0210446FFF706 | ||
| 1286 | :1050600047FB402320462560E36500F091FA0038B5 | ||
| 1287 | :1050700018BF012038BD0120704700BFF0B5056E94 | ||
| 1288 | :10508000A5B0044604AEE5B90023012701933046DC | ||
| 1289 | :105090006760294602AA009300F046FA10B1012089 | ||
| 1290 | :1050A00025B0F0BD2A46204602A900F099FA002852 | ||
| 1291 | :1050B000F5D1204600F0AAFB0028F0D1206625B0EB | ||
| 1292 | :1050C000F0BD802D2A46304628BF802204F16401BD | ||
| 1293 | :1050D000FFF70CFB256ED7E7002800F0AE802DE926 | ||
| 1294 | :1050E000F04F1446A5B0002A3DD00F46002949D004 | ||
| 1295 | :1050F000B2F5803F0546006E20D34FF6FF7805F1EC | ||
| 1296 | :10510000640AEB6D1A1AB2FBF3F103FB1122002AB9 | ||
| 1297 | :1051100065D18342B9464FF6FF7672D0B6FBF3FBFA | ||
| 1298 | :1051200003FB0BFBBBF1000F30D1002E45D1A4F5E2 | ||
| 1299 | :105130007F44FF3CB4F5803F4744E2D2EA6D161A43 | ||
| 1300 | :10514000B6FBF2F302FB1366A64228BF2646002EEA | ||
| 1301 | :1051500075D1824200F08D80B4FBF2F602FB06F6B8 | ||
| 1302 | :105160002EB9002C79D1002025B0BDE8F08F0023A6 | ||
| 1303 | :1051700031463846CDE9003302AA00F0D5F90028BF | ||
| 1304 | :1051800000F09580012025B0BDE8F08F002359463E | ||
| 1305 | :105190004846CDE9003302AA00F0C6F90028F1D153 | ||
| 1306 | :1051A0005A46284602A900F01BFA0028EAD1A6EBCD | ||
| 1307 | :1051B0000B06286ED944002EB9D019304946324624 | ||
| 1308 | :1051C00005EB8000FFF792FAA4F57F44286EFF3CC0 | ||
| 1309 | :1051D0003044B4F5803F4744286692D2AEE742455A | ||
| 1310 | :1051E00028BF4246164639465044FFF77FFA286EDC | ||
| 1311 | :1051F000EB6D3044834207EB06092866A8EB0606F0 | ||
| 1312 | :105200008CD1802B28BF802351461A4604A8FFF773 | ||
| 1313 | :105210006DFA0023E96D02AACDE9003304A800F07D | ||
| 1314 | :1052200083F90028AED12846EA6D02A900F0D8F92A | ||
| 1315 | :105230000028A7D1EB6D286670E70120704705F1C3 | ||
| 1316 | :105240006403394632461844FFF750FA286EEA6D77 | ||
| 1317 | :105250003044A41B374428667BE72B6E2246193363 | ||
| 1318 | :1052600005EB83003946FFF741FA2B6E23442B668A | ||
| 1319 | :1052700079E7802A28BF802205F1640104A8FFF79E | ||
| 1320 | :1052800035FA0023E96D04A8CDE9003302AA00F045 | ||
| 1321 | :105290004BF900287FF476AF2846EA6D02A900F0AA | ||
| 1322 | :1052A0009FF900287FF46EAFEA6D286654E7324616 | ||
| 1323 | :1052B000284602A900F094F900287FF463AF374430 | ||
| 1324 | :1052C000A41B4EE7F8B51C460546114816460F4686 | ||
| 1325 | :1052D000FFF744FE21460E48FFF75AFE044620B170 | ||
| 1326 | :1052E0000B48FFF74FFE2046F8BD3A4629460848CE | ||
| 1327 | :1052F000FFF762FE04460028F2D131460448FFF76A | ||
| 1328 | :1053000085FE04460248FFF73DFE2046F8BD00BF7B | ||
| 1329 | :10531000C42700201C2370B582B001A90546019363 | ||
| 1330 | :1053200000F032F8044638B9019B1C2B07D0144C0E | ||
| 1331 | :105330001C212846FFF7DCF9204602B070BDD5E9F4 | ||
| 1332 | :105340000112131E18BF0123003918BF01210126C5 | ||
| 1333 | :1053500028689B00EA6843EA4103002818BF43F02D | ||
| 1334 | :105360000103EE612AB9C5E90834002BE4D1054CEC | ||
| 1335 | :10537000DEE7204643F00803C5E9083402B070BDFB | ||
| 1336 | :10538000370CF0000E0CF0000346002866D0002910 | ||
| 1337 | :1053900064D00A681C2A61D14FF47F023B49D2F8DD | ||
| 1338 | :1053A000100C88425CD0D2F8101C013158D0D2F8D1 | ||
| 1339 | :1053B000101C4FF47F021960D2F8140C3449884253 | ||
| 1340 | :1053C00060D0D2F8141C01315CD0D2F8141C4FF418 | ||
| 1341 | :1053D0007F025960D2F8181C11F5947F4FD0D2F893 | ||
| 1342 | :1053E000181C01314BD0D2F8181C4FF47F02996081 | ||
| 1343 | :1053F000D2F81C0C274988423ED0D2F81C1C01313F | ||
| 1344 | :105400003AD0D2F81C1C4FF47F02D960D2F8001CAD | ||
| 1345 | :1054100070312FD0D2F8001C01312BD0D2F8001CF3 | ||
| 1346 | :105420004FF47F021961D2F8041CAF3120D0D2F8BA | ||
| 1347 | :10543000041C01311CD0D2F8041C4FF47F025961C6 | ||
| 1348 | :10544000D2F8080C144988420DD0D2F8081C01315A | ||
| 1349 | :1054500009D0D2F8082C00209A61704701207047CB | ||
| 1350 | :1054600040F6FC01A5E740F2373200209A61704710 | ||
| 1351 | :105470005121E2E79021D3E742F60411C3E740F659 | ||
| 1352 | :10548000D861B2E742F2D001A1E700BFFCF8FFFF0C | ||
| 1353 | :10549000D020FFFF0429FFFF37F3FFFF014608B5C7 | ||
| 1354 | :1054A0004FF48060FFF7AEF80022034BC3F8C82129 | ||
| 1355 | :1054B000C3F82C2108BD00BF001084500138072814 | ||
| 1356 | :1054C00005D8DFE800F0100E040A040404060748BB | ||
| 1357 | :1054D0007047CB6800204B6270478B6800204B629E | ||
| 1358 | :1054E00070474B68F6E70B68F4E700BF310CF1003A | ||
| 1359 | :1054F0000B6802E0082B0B6006D8026A13424FEAE1 | ||
| 1360 | :105500004303F7D00020704700487047310CF1008A | ||
| 1361 | :105510000022044B4FF48060C3F82C21C3F8C4214F | ||
| 1362 | :10552000FFF756B800108450F0B5002483B0B0F1F6 | ||
| 1363 | :10553000005F8DF8074025D38C468444BCF1804F32 | ||
| 1364 | :1055400004461FD817461D4601220DF1070300F03F | ||
| 1365 | :1055500097F90646B0B99DF80730099A3C603B714F | ||
| 1366 | :1055600092B14DB10246089928460DF1070300F0AB | ||
| 1367 | :1055700087F938B99DF807303046099A15601371DC | ||
| 1368 | :1055800003B0F0BD4FF47506304603B0F0BD00BF68 | ||
| 1369 | :10559000D8B108B50368012B04D0022B0FD043B15A | ||
| 1370 | :1055A0000B4808BD20220B490830FFF79FF8002068 | ||
| 1371 | :1055B00008BD142208490830FFF798F8F7E72022C1 | ||
| 1372 | :1055C00006490830FFF792F8F1E74FF4730070478F | ||
| 1373 | :1055D0000100F300745E0000B45E0000945E000001 | ||
| 1374 | :1055E0002DE9F843002900F0F9800446002800F076 | ||
| 1375 | :1055F000F98003680F469046002B00F0C380013B02 | ||
| 1376 | :10560000012B00F2D7804FF0FF3178484FF00209AC | ||
| 1377 | :10561000FFF786F8002840F0BF800020FFF7B0F8C1 | ||
| 1378 | :105620000646002840F0C280714AD2F81C39002B8F | ||
| 1379 | :10563000FBD16F4DD5F8203C002BFBD14FF0FF3054 | ||
| 1380 | :10564000FEF7C6FFD5F8040A20F04000FEF7CEFFB3 | ||
| 1381 | :1056500001230722C5F81838C5F80029C5F8C43752 | ||
| 1382 | :10566000A36CC5F8CC37E36CC5F8D037C5F8C09744 | ||
| 1383 | :1056700023685BB1013B012B18D8636AC5F85C361F | ||
| 1384 | :10568000236AC5F85836E369C5F85436A269584B01 | ||
| 1385 | :10569000C3F850266269C3F84C262269C3F848262D | ||
| 1386 | :1056A000E268C3F84426A268C3F84026504AD2F8FC | ||
| 1387 | :1056B0001039002BFBD1B8F1000F5FD06368402098 | ||
| 1388 | :1056C000012B08BFC2F884363A68494BC3F8282C2E | ||
| 1389 | :1056D000C3F82C8CFEF790FF0646454AD2F81039E5 | ||
| 1390 | :1056E000002BFBD1424AD2F8203C002BFBD123688F | ||
| 1391 | :1056F0005BB1013B012B18D8D2F85C366362D2F85B | ||
| 1392 | :1057000058362362D2F85436E361394BD3F8502629 | ||
| 1393 | :10571000A261D3F84C266261D3F848262261D3F8FF | ||
| 1394 | :105720004426E260D3F84036A36000230121304ACA | ||
| 1395 | :10573000D2F8CC07A064D2F8D007E064C2F8C4174E | ||
| 1396 | :10574000C2F88436C2F8C837D2F81039002BFBD122 | ||
| 1397 | :10575000C2F81838002E3BD1254BD3F8040A40F08C | ||
| 1398 | :105760004000FEF743FF0120FFF70AF860BB1F4827 | ||
| 1399 | :10577000FEF7DEFF10BB3046BDE8F8830423C2F815 | ||
| 1400 | :10578000C837AAE74FF0FF3118484FF00109FEF77C | ||
| 1401 | :10579000C7FF00283FF441AF1648FFF757F8002035 | ||
| 1402 | :1057A000FEF7EEFF064600283FF43EAF1248FFF733 | ||
| 1403 | :1057B0004DF839E7114E3046BDE8F8831048FFF741 | ||
| 1404 | :1057C00045F83046BDE8F8830E48FFF73FF8CEE7CE | ||
| 1405 | :1057D000102104F10800FEF78BFFBDE70A4E3046AA | ||
| 1406 | :1057E000BDE8F8834FF47306C5E700BFE41000205E | ||
| 1407 | :1057F00000108450705D0000885D00000100F3001F | ||
| 1408 | :10580000C85D0000A85D00000300F300A0B30346DC | ||
| 1409 | :1058100070B4D0E90240D3E9041226BA05BA0CBA32 | ||
| 1410 | :1058200010BAC3E90440D3E90612986A09BAC3E979 | ||
| 1411 | :10583000026512BA996100BAD3E9084125BA0CBAD7 | ||
| 1412 | :10584000C3E90725D3E90B12C3E9094009BAD86BAC | ||
| 1413 | :1058500012BAD962D3E90D4125BAC3E90C250CBAB5 | ||
| 1414 | :1058600000BAD3E9101209BA12BAC3E90E4019649A | ||
| 1415 | :1058700000205A6470BC70474FF47300704700BF3B | ||
| 1416 | :1058800000201870704700BF431810B501D21F2ABE | ||
| 1417 | :1058900001D9002010BD013902F014030144102B7E | ||
| 1418 | :1058A00080EA01043CD009DC8BB1042BF1D11F2C20 | ||
| 1419 | :1058B00040E840F315D941E840F10EE0142BE8D15F | ||
| 1420 | :1058C0001F2C40E8C0F30CD941E8C0F105E01F2CC3 | ||
| 1421 | :1058D00040E800F305D941E800F11C460B468C4234 | ||
| 1422 | :1058E000D7D122F01402013A0A2AD2D801A151F8E4 | ||
| 1423 | :1058F00022F000BF435900003D5900002F5900001D | ||
| 1424 | :1059000093580000935800009358000093580000EB | ||
| 1425 | :105910004959000043590000375900002F59000031 | ||
| 1426 | :105920001F2C40E880F3DCD941E880F1D5E713F47F | ||
| 1427 | :10593000001FAFD1ADE713F4801FFAE75B02A9D5D2 | ||
| 1428 | :10594000A7E713F4002FF4E713F4802FF1E700BF6B | ||
| 1429 | :1059500008B5074B044613B10021AFF30080054B97 | ||
| 1430 | :105960001868836A03B19847204600F029F800BF01 | ||
| 1431 | :1059700000000000C85E000070B50D4D00260D4C03 | ||
| 1432 | :10598000641BA410A64209D10B4D00260B4C00F05D | ||
| 1433 | :10599000D5F9641BA410A64205D170BD55F8043B8F | ||
| 1434 | :1059A00001369847EEE755F8043B01369847F2E791 | ||
| 1435 | :1059B000A0110020A0110020A0110020A41100209F | ||
| 1436 | :1059C000FEE700BFB7EE000AF7EE000AB7EE001AD6 | ||
| 1437 | :1059D000F7EE001AB7EE002AF7EE002AB7EE003A0B | ||
| 1438 | :1059E000F7EE003AB7EE004AF7EE004AB7EE005A7B | ||
| 1439 | :1059F000F7EE005AB7EE006AF7EE006AB7EE007AEB | ||
| 1440 | :105A0000F7EE007AF1EE10CA40F29F01CFF20001EA | ||
| 1441 | :105A10003CEA010CE1EE10CA002383F300887047D2 | ||
| 1442 | :105A2000FDF79CBAEFF30880EFF309812DE9F00F41 | ||
| 1443 | :105A30006B467246FAF7ACFF08B0FFF7F1FFFEE7DE | ||
| 1444 | :105A4000FDF78CBAEFF30880EFF309812DE9F00F31 | ||
| 1445 | :105A50006B467246FAF79CFF08B0FFF7F1FFFEE7CE | ||
| 1446 | :105A6000FDF77CBAEFF30880EFF309812DE9F00F21 | ||
| 1447 | :105A70006B467246FAF78CFF08B0FFF7F1FFFEE7BE | ||
| 1448 | :105A8000FDF76CBAEFF30880EFF309812DE9F00F11 | ||
| 1449 | :105A90006B467246FAF77CFF08B0FFF7F1FFFEE7AE | ||
| 1450 | :105AA000FDF75CBAEFF30880EFF309812DE9F00F01 | ||
| 1451 | :105AB0006B467246FAF76CFF08B0FFF7F1FFFEE79E | ||
| 1452 | :105AC000814270B40546144602D370BC00F02EB873 | ||
| 1453 | :105AD000821821443CB141EA020313F003030FD1C1 | ||
| 1454 | :105AE000E018032812D86FF00300A30843430020F6 | ||
| 1455 | :105AF00019441A442344984210D1284670BC704778 | ||
| 1456 | :105B000011F8013D013C02F8013DE3E7581850F857 | ||
| 1457 | :105B1000046C981840F8046C043BE1E70C1A14F884 | ||
| 1458 | :105B2000016C141A04F8016C0130E4E770B5044606 | ||
| 1459 | :105B30003AB141EA040313F003030CD1D518032D45 | ||
| 1460 | :105B40000FD822F003031C441944002302F003027F | ||
| 1461 | :105B500093420CD170BD11F8013B013A04F8013BAE | ||
| 1462 | :105B6000E6E7CD1A2E68E51A2E60043BE6E75D5C99 | ||
| 1463 | :105B7000E5540133ECE7F0B5044662B922F00303C3 | ||
| 1464 | :105B8000234402F003021A44934214D1F0BD04F8F6 | ||
| 1465 | :105B9000011B013AF1E7A307F9D115460B0443EACB | ||
| 1466 | :105BA00001630B4343EA01231619032DE6D9771B42 | ||
| 1467 | :105BB0003B60043DF9E703F8011BE5E708B5EFF3A7 | ||
| 1468 | :105BC0000583C3F308030BB1FDF7C8F9BDE808402E | ||
| 1469 | :105BD000FDF74CBA10B50446EFF30583C3F3080391 | ||
| 1470 | :105BE0000BB1FDF7BBF92046BDE81040FDF741BA07 | ||
| 1471 | :105BF0002DE9F04104460D4616461F46EFF3058396 | ||
| 1472 | :105C0000C3F308030BB1FDF7A9F93B463246294619 | ||
| 1473 | :105C10002046BDE8F041FCF743BC2DE9F0410446C5 | ||
| 1474 | :105C20000D4616461F46EFF30583C3F308030BB179 | ||
| 1475 | :105C3000FDF794F93B46324629462046BDE8F0413F | ||
| 1476 | :105C4000FCF768BC08B5EFF30583C3F308030BB199 | ||
| 1477 | :105C5000FDF784F9BDE80840FDF7DBB90020704787 | ||
| 1478 | :105C6000704710B5044608B1FDF75AFF2046BDE85D | ||
| 1479 | :105C70001040FDF745BF10B50446406A10B1A16A57 | ||
| 1480 | :105C8000FFF7EFFF0020C4E9090010BD38B5044656 | ||
| 1481 | :105C9000FFF7F1FF236A2C22012B0CBF05466FF0A2 | ||
| 1482 | :105CA000960500212046FFF766FF284638BD0020F4 | ||
| 1483 | :105CB000704770470020704713B5002001AB1446B1 | ||
| 1484 | :105CC000FDF7E2FF30B9019BA34218BF6FF09300CC | ||
| 1485 | :105CD00002B010BD6FF09200FAE7002070472DE986 | ||
| 1486 | :105CE000E04F2746A046A146A246A346A4462DED76 | ||
| 1487 | :105CF000108B4FF0000545EC185B45EC195A45EC4C | ||
| 1488 | :105D00001A5A45EC1B5A45EC1C5A45EC1D5A45ECF9 | ||
| 1489 | :105D10001E5A45EC1F5AF1EE105A4FF66076C0F647 | ||
| 1490 | :105D2000FF763540E1EE105A84F30088254626467A | ||
| 1491 | :105D3000A447BDEC108BBDE8E08F0000F8B500BFB4 | ||
| 1492 | :105D4000F8BC08BC9E467047F8B500BFF8BC08BC5C | ||
| 1493 | :105D50009E467047FF8FFFFFFF8FFFFFFE8FFFFF05 | ||
| 1494 | :105D6000FE8FFFFFFD8FFFFFFC8FFFFFFC8FFFFF0C | ||
| 1495 | :105D70004661696C20746F2061637175697265207A | ||
| 1496 | :105D80006D757465780A00004661696C20746F2037 | ||
| 1497 | :105D9000696E63726561736520504D20636F756E27 | ||
| 1498 | :105DA0007465720A000000004661696C20746F20FF | ||
| 1499 | :105DB000646563726561736520504D20636F756E15 | ||
| 1500 | :105DC0007465720A000000004661696C20746F20DF | ||
| 1501 | :105DD00072656C65617365206D757465780A000085 | ||
| 1502 | :105DE000436F756C64206E6F74206C6F636B2070F2 | ||
| 1503 | :105DF0006F7765722073617665206D7574657800C4 | ||
| 1504 | :105E00006D757465785F667265652063616C6C653D | ||
| 1505 | :105E1000642077697468204E554C4C207061726123 | ||
| 1506 | :105E20006D6574657200000043616E277420696EB1 | ||
| 1507 | :105E3000697469616C697A65206D757465782C2068 | ||
| 1508 | :105E4000776173204E554C4C0D0A00004661696C19 | ||
| 1509 | :105E500020746F20756E6C6F636B206D7574657840 | ||
| 1510 | :105E60000A0000000A637478206973204E554C4C78 | ||
| 1511 | :105E70000A00000067E6096A85AE67BB72F36E3CF4 | ||
| 1512 | :105E80003AF54FA57F520E518C68059BABD9831F05 | ||
| 1513 | :105E900019CDE05BD89E05C107D57C3617DD703083 | ||
| 1514 | :105EA00039590EF7310BC0FF11155868A78FF964E7 | ||
| 1515 | :105EB000A44FFABE0123456789ABCDEFFEDCBA984B | ||
| 1516 | :105EC00076543210F0E1D2C34011002054464D5FA9 | ||
| 1517 | :105ED00043525950544F0054464D5F504C41544624 | ||
| 1518 | :105EE0004F524D5F53455256494345000000000054 | ||
| 1519 | :105EF00000000000000000000000000000000000A2 | ||
| 1520 | :107C00007FE97FE9FBF72CBD7FE97FE9FBF737BD13 | ||
| 1521 | :107C10007FE97FE9FBF75FBD7FE97FE9FBF752BDB5 | ||
| 1522 | :107C20007FE97FE9FBF73ABD00000000000000009B | ||
| 1523 | :107C30000000000000000000000000000000000044 | ||
| 1524 | :107C40007AFFFFFF00900050000000008C3400001D | ||
| 1525 | :107C50000400000000000000000000000000000020 | ||
| 1526 | :107C6000000000000000000090ED00E000A00350C4 | ||
| 1527 | :107C70007FA60350009000506F9500501412002012 | ||
| 1528 | :107C8000A811002044010000615C00005D5C000060 | ||
| 1529 | :107C9000775B0000DC1000200C1100200411002094 | ||
| 1530 | :107CA00000110020FC1000201D48000011480000B9 | ||
| 1531 | :107CB000054800000000000029480000381100209D | ||
| 1532 | :107CC00030110020281100200000000020110020A9 | ||
| 1533 | :107CD0003549000081480000B5480000FD4800001B | ||
| 1534 | :107CE000682500203A00003A6C2500203A00003A4E | ||
| 1535 | :107CF000702500203A00003A742500203A00003A2E | ||
| 1536 | :107D00000000000000000000000000000000000073 | ||
| 1537 | :107D10000000000000000000000000000000000063 | ||
| 1538 | :107D20000000000000000000000000000000000053 | ||
| 1539 | :107D30000000000000000000000000000000000043 | ||
| 1540 | :107D40000000000000000000000000000000000033 | ||
| 1541 | :107D50000000000000000000000000000000000023 | ||
| 1542 | :087D6000553700002D3700002B | ||
| 1543 | :00000001FF | ||
diff --git a/examples/nrf9151/s/.cargo/config.toml b/examples/nrf9151/s/.cargo/config.toml new file mode 100644 index 000000000..f64c63966 --- /dev/null +++ b/examples/nrf9151/s/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | runner = "probe-rs run --chip nRF9160_xxAA" | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv8m.main-none-eabihf" | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml new file mode 100644 index 000000000..7253fc4be --- /dev/null +++ b/examples/nrf9151/s/Cargo.toml | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-nrf9151-secure-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||
| 9 | embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||
| 10 | embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | ||
| 11 | |||
| 12 | defmt = "0.3" | ||
| 13 | defmt-rtt = "0.4" | ||
| 14 | |||
| 15 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 16 | cortex-m-rt = "0.7.0" | ||
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 18 | |||
| 19 | [profile.release] | ||
| 20 | debug = 2 | ||
diff --git a/examples/nrf9151/s/build.rs b/examples/nrf9151/s/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf9151/s/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/nrf9151/s/memory.x b/examples/nrf9151/s/memory.x new file mode 100644 index 000000000..4c7d4ebf0 --- /dev/null +++ b/examples/nrf9151/s/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K | ||
| 4 | RAM : ORIGIN = 0x20018000, LENGTH = 160K | ||
| 5 | } | ||
diff --git a/examples/nrf9151/s/src/bin/blinky.rs b/examples/nrf9151/s/src/bin/blinky.rs new file mode 100644 index 000000000..7457a95a3 --- /dev/null +++ b/examples/nrf9151/s/src/bin/blinky.rs | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_nrf::init(Default::default()); | ||
| 12 | let mut led = Output::new(p.P0_00, Level::Low, OutputDrive::Standard); | ||
| 13 | |||
| 14 | loop { | ||
| 15 | led.set_high(); | ||
| 16 | defmt::info!("high"); | ||
| 17 | Timer::after_millis(500).await; | ||
| 18 | led.set_low(); | ||
| 19 | defmt::info!("low"); | ||
| 20 | Timer::after_millis(1000).await; | ||
| 21 | } | ||
| 22 | } | ||
diff --git a/examples/nrf9160/.cargo/config.toml b/examples/nrf9160/.cargo/config.toml index 1444b0cd1..6072b8595 100644 --- a/examples/nrf9160/.cargo/config.toml +++ b/examples/nrf9160/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` | 2 | # runner = "probe-rs run --chip nRF9160_xxAA" |
| 3 | runner = "probe-rs run --chip nRF9160_xxAA" | 3 | runner = [ "probe-rs", "run", "--chip=nRF9160_xxAA", "--always-print-stacktrace", "--log-format={t} {[{L}]%bold} {s} {{c} {ff}:{l:1}%dimmed}" ] |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv8m.main-none-eabihf" | 6 | target = "thumbv8m.main-none-eabihf" |
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 2ff692b24..9aeb99317 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml | |||
| @@ -5,16 +5,22 @@ version = "0.1.0" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 8 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 9 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 9 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 10 | embassy-nrf = { version = "0.2.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 = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } | ||
| 11 | 13 | ||
| 12 | defmt = "0.3" | 14 | defmt = "0.3" |
| 13 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
| 14 | 16 | ||
| 17 | heapless = "0.8" | ||
| 15 | 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"] } |
| 16 | cortex-m-rt = "0.7.0" | 19 | cortex-m-rt = "0.7.0" |
| 17 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 21 | static_cell = { version = "2" } | ||
| 22 | embedded-io = "0.6.1" | ||
| 23 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | ||
| 18 | 24 | ||
| 19 | [profile.release] | 25 | [profile.release] |
| 20 | debug = 2 | 26 | debug = 2 |
diff --git a/examples/nrf9160/memory.x b/examples/nrf9160/memory.x index 4c7d4ebf0..e33498773 100644 --- a/examples/nrf9160/memory.x +++ b/examples/nrf9160/memory.x | |||
| @@ -1,5 +1,9 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K | 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K |
| 4 | RAM : ORIGIN = 0x20018000, LENGTH = 160K | 4 | RAM : ORIGIN = 0x20010000, LENGTH = 192K |
| 5 | IPC : ORIGIN = 0x20000000, LENGTH = 64K | ||
| 5 | } | 6 | } |
| 7 | |||
| 8 | PROVIDE(__start_ipc = ORIGIN(IPC)); | ||
| 9 | PROVIDE(__end_ipc = ORIGIN(IPC) + LENGTH(IPC)); | ||
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs new file mode 100644 index 000000000..5335b6b51 --- /dev/null +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | use core::net::IpAddr; | ||
| 6 | use core::ptr::addr_of_mut; | ||
| 7 | use core::slice; | ||
| 8 | use core::str::FromStr; | ||
| 9 | |||
| 10 | use defmt::{info, unwrap, warn}; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | ||
| 13 | use embassy_net_nrf91::context::Status; | ||
| 14 | use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader}; | ||
| 15 | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; | ||
| 16 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; | ||
| 17 | use embassy_nrf::uarte::Baudrate; | ||
| 18 | use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; | ||
| 19 | use embassy_time::{Duration, Timer}; | ||
| 20 | use embedded_io_async::Write; | ||
| 21 | use heapless::Vec; | ||
| 22 | use static_cell::StaticCell; | ||
| 23 | use {defmt_rtt as _, panic_probe as _}; | ||
| 24 | |||
| 25 | #[interrupt] | ||
| 26 | fn IPC() { | ||
| 27 | embassy_net_nrf91::on_ipc_irq(); | ||
| 28 | } | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[embassy_executor::task] | ||
| 35 | async fn trace_task(mut uart: BufferedUarteTx<'static, peripherals::SERIAL0>, reader: TraceReader<'static>) -> ! { | ||
| 36 | let mut rx = [0u8; 1024]; | ||
| 37 | loop { | ||
| 38 | let n = reader.read(&mut rx[..]).await; | ||
| 39 | unwrap!(uart.write_all(&rx[..n]).await); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | #[embassy_executor::task] | ||
| 44 | async fn modem_task(runner: Runner<'static>) -> ! { | ||
| 45 | runner.run().await | ||
| 46 | } | ||
| 47 | |||
| 48 | #[embassy_executor::task] | ||
| 49 | async fn net_task(stack: &'static Stack<embassy_net_nrf91::NetDriver<'static>>) -> ! { | ||
| 50 | stack.run().await | ||
| 51 | } | ||
| 52 | |||
| 53 | #[embassy_executor::task] | ||
| 54 | async fn control_task( | ||
| 55 | control: &'static context::Control<'static>, | ||
| 56 | config: context::Config<'static>, | ||
| 57 | stack: &'static Stack<embassy_net_nrf91::NetDriver<'static>>, | ||
| 58 | ) { | ||
| 59 | unwrap!(control.configure(&config).await); | ||
| 60 | unwrap!( | ||
| 61 | control | ||
| 62 | .run(|status| { | ||
| 63 | stack.set_config_v4(status_to_config(status)); | ||
| 64 | }) | ||
| 65 | .await | ||
| 66 | ); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn status_to_config(status: &Status) -> embassy_net::ConfigV4 { | ||
| 70 | let Some(IpAddr::V4(addr)) = status.ip else { | ||
| 71 | panic!("Unexpected IP address"); | ||
| 72 | }; | ||
| 73 | let addr = Ipv4Address(addr.octets()); | ||
| 74 | |||
| 75 | let gateway = if let Some(IpAddr::V4(addr)) = status.gateway { | ||
| 76 | Some(Ipv4Address(addr.octets())) | ||
| 77 | } else { | ||
| 78 | None | ||
| 79 | }; | ||
| 80 | |||
| 81 | let mut dns_servers = Vec::new(); | ||
| 82 | for dns in status.dns.iter() { | ||
| 83 | if let IpAddr::V4(ip) = dns { | ||
| 84 | unwrap!(dns_servers.push(Ipv4Address(ip.octets()))); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | embassy_net::ConfigV4::Static(embassy_net::StaticConfigV4 { | ||
| 89 | address: Ipv4Cidr::new(addr, 32), | ||
| 90 | gateway, | ||
| 91 | dns_servers, | ||
| 92 | }) | ||
| 93 | } | ||
| 94 | |||
| 95 | #[embassy_executor::task] | ||
| 96 | async fn blink_task(pin: AnyPin) { | ||
| 97 | let mut led = Output::new(pin, Level::Low, OutputDrive::Standard); | ||
| 98 | loop { | ||
| 99 | led.set_high(); | ||
| 100 | Timer::after_millis(1000).await; | ||
| 101 | led.set_low(); | ||
| 102 | Timer::after_millis(1000).await; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | extern "C" { | ||
| 107 | static __start_ipc: u8; | ||
| 108 | static __end_ipc: u8; | ||
| 109 | } | ||
| 110 | |||
| 111 | #[embassy_executor::main] | ||
| 112 | async fn main(spawner: Spawner) { | ||
| 113 | let p = embassy_nrf::init(Default::default()); | ||
| 114 | |||
| 115 | info!("Hello World!"); | ||
| 116 | |||
| 117 | unwrap!(spawner.spawn(blink_task(p.P0_02.degrade()))); | ||
| 118 | |||
| 119 | let ipc_mem = unsafe { | ||
| 120 | let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit<u8>; | ||
| 121 | let ipc_end = &__end_ipc as *const u8 as *mut MaybeUninit<u8>; | ||
| 122 | let ipc_len = ipc_end.offset_from(ipc_start) as usize; | ||
| 123 | slice::from_raw_parts_mut(ipc_start, ipc_len) | ||
| 124 | }; | ||
| 125 | |||
| 126 | static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; | ||
| 127 | let mut config = uarte::Config::default(); | ||
| 128 | config.baudrate = Baudrate::BAUD1M; | ||
| 129 | let uart = BufferedUarteTx::new( | ||
| 130 | //let trace_uart = BufferedUarteTx::new( | ||
| 131 | unsafe { peripherals::SERIAL0::steal() }, | ||
| 132 | Irqs, | ||
| 133 | unsafe { peripherals::P0_01::steal() }, | ||
| 134 | //unsafe { peripherals::P0_14::steal() }, | ||
| 135 | config, | ||
| 136 | unsafe { &mut *addr_of_mut!(TRACE_BUF) }, | ||
| 137 | ); | ||
| 138 | |||
| 139 | static STATE: StaticCell<State> = StaticCell::new(); | ||
| 140 | static TRACE: StaticCell<TraceBuffer> = StaticCell::new(); | ||
| 141 | let (device, control, runner, tracer) = | ||
| 142 | embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; | ||
| 143 | unwrap!(spawner.spawn(modem_task(runner))); | ||
| 144 | unwrap!(spawner.spawn(trace_task(uart, tracer))); | ||
| 145 | |||
| 146 | let config = embassy_net::Config::default(); | ||
| 147 | |||
| 148 | // Generate "random" seed. nRF91 has no RNG, TODO figure out something... | ||
| 149 | let seed = 123456; | ||
| 150 | |||
| 151 | // Init network stack | ||
| 152 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | ||
| 153 | static STACK: StaticCell<Stack<embassy_net_nrf91::NetDriver<'static>>> = StaticCell::new(); | ||
| 154 | let stack = &*STACK.init(Stack::new( | ||
| 155 | device, | ||
| 156 | config, | ||
| 157 | RESOURCES.init(StackResources::<2>::new()), | ||
| 158 | seed, | ||
| 159 | )); | ||
| 160 | |||
| 161 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 162 | |||
| 163 | static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); | ||
| 164 | let control = CONTROL.init(context::Control::new(control, 0).await); | ||
| 165 | |||
| 166 | unwrap!(spawner.spawn(control_task( | ||
| 167 | control, | ||
| 168 | context::Config { | ||
| 169 | apn: b"iot.nat.es", | ||
| 170 | auth_prot: context::AuthProt::Pap, | ||
| 171 | auth: Some((b"orange", b"orange")), | ||
| 172 | }, | ||
| 173 | stack | ||
| 174 | ))); | ||
| 175 | |||
| 176 | stack.wait_config_up().await; | ||
| 177 | |||
| 178 | let mut rx_buffer = [0; 4096]; | ||
| 179 | let mut tx_buffer = [0; 4096]; | ||
| 180 | loop { | ||
| 181 | let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 182 | socket.set_timeout(Some(Duration::from_secs(10))); | ||
| 183 | |||
| 184 | info!("Connecting..."); | ||
| 185 | let host_addr = embassy_net::Ipv4Address::from_str("45.79.112.203").unwrap(); | ||
| 186 | if let Err(e) = socket.connect((host_addr, 4242)).await { | ||
| 187 | warn!("connect error: {:?}", e); | ||
| 188 | Timer::after_secs(10).await; | ||
| 189 | continue; | ||
| 190 | } | ||
| 191 | info!("Connected to {:?}", socket.remote_endpoint()); | ||
| 192 | |||
| 193 | let msg = b"Hello world!\n"; | ||
| 194 | for _ in 0..10 { | ||
| 195 | if let Err(e) = socket.write_all(msg).await { | ||
| 196 | warn!("write error: {:?}", e); | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | info!("txd: {}", core::str::from_utf8(msg).unwrap()); | ||
| 200 | Timer::after_secs(1).await; | ||
| 201 | } | ||
| 202 | Timer::after_secs(4).await; | ||
| 203 | } | ||
| 204 | } | ||
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 9bd403f02..04b4c6317 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -6,18 +6,18 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } | 9 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal", features = ["defmt"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } | 13 | embassy-rp = { version = "0.2.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } | 15 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } |
| 16 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | 16 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 18 | embassy-usb-logger = { version = "0.2.0", path = "../../embassy-usb-logger" } | 18 | embassy-usb-logger = { version = "0.2.0", path = "../../embassy-usb-logger" } |
| 19 | cyw43 = { version = "0.1.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } | 19 | cyw43 = { version = "0.2.0", path = "../../cyw43", features = ["defmt", "firmware-logs", "bluetooth"] } |
| 20 | cyw43-pio = { version = "0.1.0", path = "../../cyw43-pio", features = ["defmt", "overclock"] } | 20 | cyw43-pio = { version = "0.2.0", path = "../../cyw43-pio", features = ["defmt"] } |
| 21 | 21 | ||
| 22 | defmt = "0.3" | 22 | defmt = "0.3" |
| 23 | defmt-rtt = "0.4" | 23 | defmt-rtt = "0.4" |
| @@ -29,6 +29,9 @@ reqwless = { version = "0.12.0", features = ["defmt",]} | |||
| 29 | serde = { version = "1.0.203", default-features = false, features = ["derive"] } | 29 | serde = { version = "1.0.203", default-features = false, features = ["derive"] } |
| 30 | serde-json-core = "0.5.1" | 30 | serde-json-core = "0.5.1" |
| 31 | 31 | ||
| 32 | # for assign resources example | ||
| 33 | assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" } | ||
| 34 | |||
| 32 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 35 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 33 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | 36 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } |
| 34 | cortex-m-rt = "0.7.0" | 37 | cortex-m-rt = "0.7.0" |
| @@ -41,14 +44,14 @@ display-interface = "0.4.1" | |||
| 41 | byte-slice-cast = { version = "1.2.0", default-features = false } | 44 | byte-slice-cast = { version = "1.2.0", default-features = false } |
| 42 | smart-leds = "0.3.0" | 45 | smart-leds = "0.3.0" |
| 43 | heapless = "0.8" | 46 | heapless = "0.8" |
| 44 | usbd-hid = "0.7.0" | 47 | usbd-hid = "0.8.1" |
| 45 | 48 | ||
| 46 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 49 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 47 | embedded-hal-async = "1.0" | 50 | embedded-hal-async = "1.0" |
| 48 | embedded-hal-bus = { version = "0.1", features = ["async"] } | 51 | embedded-hal-bus = { version = "0.1", features = ["async"] } |
| 49 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | 52 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } |
| 50 | embedded-storage = { version = "0.3" } | 53 | embedded-storage = { version = "0.3" } |
| 51 | static_cell = "2" | 54 | static_cell = "2.1" |
| 52 | portable-atomic = { version = "1.5", features = ["critical-section"] } | 55 | portable-atomic = { version = "1.5", features = ["critical-section"] } |
| 53 | log = "0.4" | 56 | log = "0.4" |
| 54 | pio-proc = "0.2" | 57 | pio-proc = "0.2" |
| @@ -56,9 +59,24 @@ pio = "0.2.1" | |||
| 56 | rand = { version = "0.8.5", default-features = false } | 59 | rand = { version = "0.8.5", default-features = false } |
| 57 | embedded-sdmmc = "0.7.0" | 60 | embedded-sdmmc = "0.7.0" |
| 58 | 61 | ||
| 62 | bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] } | ||
| 63 | trouble-host = { version = "0.1.0", features = ["defmt", "gatt"] } | ||
| 64 | |||
| 59 | [profile.release] | 65 | [profile.release] |
| 60 | debug = 2 | 66 | debug = 2 |
| 67 | lto = true | ||
| 68 | opt-level = 'z' | ||
| 61 | 69 | ||
| 62 | [profile.dev] | 70 | [profile.dev] |
| 71 | debug = 2 | ||
| 63 | lto = true | 72 | lto = true |
| 64 | opt-level = "z" | 73 | opt-level = "z" |
| 74 | |||
| 75 | [patch.crates-io] | ||
| 76 | trouble-host = { git = "https://github.com/embassy-rs/trouble.git", rev = "4b8c0f499b34e46ca23a56e2d1640ede371722cf" } | ||
| 77 | embassy-executor = { path = "../../embassy-executor" } | ||
| 78 | embassy-sync = { path = "../../embassy-sync" } | ||
| 79 | embassy-futures = { path = "../../embassy-futures" } | ||
| 80 | embassy-time = { path = "../../embassy-time" } | ||
| 81 | embassy-time-driver = { path = "../../embassy-time-driver" } | ||
| 82 | embassy-embedded-hal = { path = "../../embassy-embedded-hal" } | ||
diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs new file mode 100644 index 000000000..ff6eff4a2 --- /dev/null +++ b/examples/rp/src/bin/assign_resources.rs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | //! This example demonstrates how to assign resources to multiple tasks by splitting up the peripherals. | ||
| 2 | //! It is not about sharing the same resources between tasks, see sharing.rs for that or head to https://embassy.dev/book/#_sharing_peripherals_between_tasks) | ||
| 3 | //! Of course splitting up resources and sharing resources can be combined, yet this example is only about splitting up resources. | ||
| 4 | //! | ||
| 5 | //! There are basically two ways we demonstrate here: | ||
| 6 | //! 1) Assigning resources to a task by passing parts of the peripherals | ||
| 7 | //! 2) Assigning resources to a task by passing a struct with the split up peripherals, using the assign-resources macro | ||
| 8 | //! | ||
| 9 | //! using four LEDs on Pins 10, 11, 20 and 21 | ||
| 10 | |||
| 11 | #![no_std] | ||
| 12 | #![no_main] | ||
| 13 | |||
| 14 | use assign_resources::assign_resources; | ||
| 15 | use defmt::*; | ||
| 16 | use embassy_executor::Spawner; | ||
| 17 | use embassy_rp::gpio::{Level, Output}; | ||
| 18 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; | ||
| 19 | use embassy_time::Timer; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(spawner: Spawner) { | ||
| 24 | // initialize the peripherals | ||
| 25 | let p = embassy_rp::init(Default::default()); | ||
| 26 | |||
| 27 | // 1) Assigning a resource to a task by passing parts of the peripherals. | ||
| 28 | spawner | ||
| 29 | .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) | ||
| 30 | .unwrap(); | ||
| 31 | |||
| 32 | // 2) Using the assign-resources macro to assign resources to a task. | ||
| 33 | // we perform the split, see further below for the definition of the resources struct | ||
| 34 | let r = split_resources!(p); | ||
| 35 | // and then we can use them | ||
| 36 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); | ||
| 37 | } | ||
| 38 | |||
| 39 | // 1) Assigning a resource to a task by passing parts of the peripherals. | ||
| 40 | #[embassy_executor::task] | ||
| 41 | async fn double_blinky_manually_assigned(_spawner: Spawner, pin_20: PIN_20, pin_21: PIN_21) { | ||
| 42 | let mut led_20 = Output::new(pin_20, Level::Low); | ||
| 43 | let mut led_21 = Output::new(pin_21, Level::High); | ||
| 44 | |||
| 45 | loop { | ||
| 46 | info!("toggling leds"); | ||
| 47 | led_20.toggle(); | ||
| 48 | led_21.toggle(); | ||
| 49 | Timer::after_secs(1).await; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | // 2) Using the assign-resources macro to assign resources to a task. | ||
| 54 | // first we define the resources we want to assign to the task using the assign_resources! macro | ||
| 55 | // basically this will split up the peripherals struct into smaller structs, that we define here | ||
| 56 | // naming is up to you, make sure your future self understands what you did here | ||
| 57 | assign_resources! { | ||
| 58 | leds: Leds{ | ||
| 59 | led_10: PIN_10, | ||
| 60 | led_11: PIN_11, | ||
| 61 | } | ||
| 62 | // add more resources to more structs if needed, for example defining one struct for each task | ||
| 63 | } | ||
| 64 | // this could be done in another file and imported here, but for the sake of simplicity we do it here | ||
| 65 | // see https://github.com/adamgreig/assign-resources for more information | ||
| 66 | |||
| 67 | // 2) Using the split resources in a task | ||
| 68 | #[embassy_executor::task] | ||
| 69 | async fn double_blinky_macro_assigned(_spawner: Spawner, r: Leds) { | ||
| 70 | let mut led_10 = Output::new(r.led_10, Level::Low); | ||
| 71 | let mut led_11 = Output::new(r.led_11, Level::High); | ||
| 72 | |||
| 73 | loop { | ||
| 74 | info!("toggling leds"); | ||
| 75 | led_10.toggle(); | ||
| 76 | led_11.toggle(); | ||
| 77 | Timer::after_secs(1).await; | ||
| 78 | } | ||
| 79 | } | ||
diff --git a/examples/rp/src/bin/bluetooth.rs b/examples/rp/src/bin/bluetooth.rs new file mode 100644 index 000000000..7524e7929 --- /dev/null +++ b/examples/rp/src/bin/bluetooth.rs | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | //! This example test the RP Pico W on board LED. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico board. See blinky.rs. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use bt_hci::controller::ExternalController; | ||
| 9 | use cyw43_pio::PioSpi; | ||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_futures::join::join3; | ||
| 13 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::gpio::{Level, Output}; | ||
| 15 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | ||
| 16 | use embassy_rp::pio::{InterruptHandler, Pio}; | ||
| 17 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 18 | use embassy_time::{Duration, Timer}; | ||
| 19 | use static_cell::StaticCell; | ||
| 20 | use trouble_host::advertise::{AdStructure, Advertisement, BR_EDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE}; | ||
| 21 | use trouble_host::attribute::{AttributeTable, CharacteristicProp, Service, Uuid}; | ||
| 22 | use trouble_host::gatt::GattEvent; | ||
| 23 | use trouble_host::{Address, BleHost, BleHostResources, PacketQos}; | ||
| 24 | use {defmt_rtt as _, embassy_time as _, panic_probe as _}; | ||
| 25 | |||
| 26 | bind_interrupts!(struct Irqs { | ||
| 27 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 28 | }); | ||
| 29 | |||
| 30 | #[embassy_executor::task] | ||
| 31 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | ||
| 32 | runner.run().await | ||
| 33 | } | ||
| 34 | |||
| 35 | #[embassy_executor::main] | ||
| 36 | async fn main(spawner: Spawner) { | ||
| 37 | let p = embassy_rp::init(Default::default()); | ||
| 38 | let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); | ||
| 39 | let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); | ||
| 40 | let btfw = include_bytes!("../../../../cyw43-firmware/43439A0_btfw.bin"); | ||
| 41 | |||
| 42 | // To make flashing faster for development, you may want to flash the firmwares independently | ||
| 43 | // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: | ||
| 44 | // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 | ||
| 45 | // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 | ||
| 46 | // probe-rs download 43439A0_btfw.bin --format bin --chip RP2040 --base-address 0x10141400 | ||
| 47 | //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; | ||
| 48 | //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; | ||
| 49 | //let btfw = unsafe { core::slice::from_raw_parts(0x10141400 as *const u8, 6164) }; | ||
| 50 | |||
| 51 | let pwr = Output::new(p.PIN_23, Level::Low); | ||
| 52 | let cs = Output::new(p.PIN_25, Level::High); | ||
| 53 | let mut pio = Pio::new(p.PIO0, Irqs); | ||
| 54 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | ||
| 55 | |||
| 56 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | ||
| 57 | let state = STATE.init(cyw43::State::new()); | ||
| 58 | let (_net_device, bt_device, mut control, runner) = cyw43::new_with_bluetooth(state, pwr, spi, fw, btfw).await; | ||
| 59 | unwrap!(spawner.spawn(cyw43_task(runner))); | ||
| 60 | control.init(clm).await; | ||
| 61 | |||
| 62 | let controller: ExternalController<_, 10> = ExternalController::new(bt_device); | ||
| 63 | static HOST_RESOURCES: StaticCell<BleHostResources<4, 32, 27>> = StaticCell::new(); | ||
| 64 | let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None)); | ||
| 65 | |||
| 66 | let mut ble: BleHost<'_, _> = BleHost::new(controller, host_resources); | ||
| 67 | |||
| 68 | ble.set_random_address(Address::random([0xff, 0x9f, 0x1a, 0x05, 0xe4, 0xff])); | ||
| 69 | let mut table: AttributeTable<'_, NoopRawMutex, 10> = AttributeTable::new(); | ||
| 70 | |||
| 71 | // Generic Access Service (mandatory) | ||
| 72 | let id = b"Pico W Bluetooth"; | ||
| 73 | let appearance = [0x80, 0x07]; | ||
| 74 | let mut bat_level = [0; 1]; | ||
| 75 | let handle = { | ||
| 76 | let mut svc = table.add_service(Service::new(0x1800)); | ||
| 77 | let _ = svc.add_characteristic_ro(0x2a00, id); | ||
| 78 | let _ = svc.add_characteristic_ro(0x2a01, &appearance[..]); | ||
| 79 | svc.build(); | ||
| 80 | |||
| 81 | // Generic attribute service (mandatory) | ||
| 82 | table.add_service(Service::new(0x1801)); | ||
| 83 | |||
| 84 | // Battery service | ||
| 85 | let mut svc = table.add_service(Service::new(0x180f)); | ||
| 86 | |||
| 87 | svc.add_characteristic( | ||
| 88 | 0x2a19, | ||
| 89 | &[CharacteristicProp::Read, CharacteristicProp::Notify], | ||
| 90 | &mut bat_level, | ||
| 91 | ) | ||
| 92 | .build() | ||
| 93 | }; | ||
| 94 | |||
| 95 | let mut adv_data = [0; 31]; | ||
| 96 | AdStructure::encode_slice( | ||
| 97 | &[ | ||
| 98 | AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), | ||
| 99 | AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]), | ||
| 100 | AdStructure::CompleteLocalName(b"Pico W Bluetooth"), | ||
| 101 | ], | ||
| 102 | &mut adv_data[..], | ||
| 103 | ) | ||
| 104 | .unwrap(); | ||
| 105 | |||
| 106 | let server = ble.gatt_server(&table); | ||
| 107 | |||
| 108 | info!("Starting advertising and GATT service"); | ||
| 109 | let _ = join3( | ||
| 110 | ble.run(), | ||
| 111 | async { | ||
| 112 | loop { | ||
| 113 | match server.next().await { | ||
| 114 | Ok(GattEvent::Write { handle, connection: _ }) => { | ||
| 115 | let _ = table.get(handle, |value| { | ||
| 116 | info!("Write event. Value written: {:?}", value); | ||
| 117 | }); | ||
| 118 | } | ||
| 119 | Ok(GattEvent::Read { .. }) => { | ||
| 120 | info!("Read event"); | ||
| 121 | } | ||
| 122 | Err(e) => { | ||
| 123 | error!("Error processing GATT events: {:?}", e); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | }, | ||
| 128 | async { | ||
| 129 | let mut advertiser = ble | ||
| 130 | .advertise( | ||
| 131 | &Default::default(), | ||
| 132 | Advertisement::ConnectableScannableUndirected { | ||
| 133 | adv_data: &adv_data[..], | ||
| 134 | scan_data: &[], | ||
| 135 | }, | ||
| 136 | ) | ||
| 137 | .await | ||
| 138 | .unwrap(); | ||
| 139 | let conn = advertiser.accept().await.unwrap(); | ||
| 140 | // Keep connection alive | ||
| 141 | let mut tick: u8 = 0; | ||
| 142 | loop { | ||
| 143 | Timer::after(Duration::from_secs(10)).await; | ||
| 144 | tick += 1; | ||
| 145 | server.notify(handle, &conn, &[tick]).await.unwrap(); | ||
| 146 | } | ||
| 147 | }, | ||
| 148 | ) | ||
| 149 | .await; | ||
| 150 | } | ||
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index def26b53d..aaa035a72 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs | |||
| @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) { | |||
| 76 | let stack = &*STACK.init(Stack::new( | 76 | let stack = &*STACK.init(Stack::new( |
| 77 | device, | 77 | device, |
| 78 | embassy_net::Config::dhcpv4(Default::default()), | 78 | embassy_net::Config::dhcpv4(Default::default()), |
| 79 | RESOURCES.init(StackResources::<3>::new()), | 79 | RESOURCES.init(StackResources::new()), |
| 80 | seed, | 80 | seed, |
| 81 | )); | 81 | )); |
| 82 | 82 | ||
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 6c4a78361..8e96a114c 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs | |||
| @@ -75,11 +75,11 @@ async fn main(spawner: Spawner) { | |||
| 75 | 75 | ||
| 76 | // Init network stack | 76 | // Init network stack |
| 77 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | 77 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); |
| 78 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 78 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 79 | let stack = &*STACK.init(Stack::new( | 79 | let stack = &*STACK.init(Stack::new( |
| 80 | device, | 80 | device, |
| 81 | embassy_net::Config::dhcpv4(Default::default()), | 81 | embassy_net::Config::dhcpv4(Default::default()), |
| 82 | RESOURCES.init(StackResources::<2>::new()), | 82 | RESOURCES.init(StackResources::new()), |
| 83 | seed, | 83 | seed, |
| 84 | )); | 84 | )); |
| 85 | 85 | ||
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 30a3a7463..40736bf3c 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs | |||
| @@ -74,11 +74,11 @@ async fn main(spawner: Spawner) { | |||
| 74 | 74 | ||
| 75 | // Init network stack | 75 | // Init network stack |
| 76 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | 76 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); |
| 77 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 77 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 78 | let stack = &*STACK.init(Stack::new( | 78 | let stack = &*STACK.init(Stack::new( |
| 79 | device, | 79 | device, |
| 80 | embassy_net::Config::dhcpv4(Default::default()), | 80 | embassy_net::Config::dhcpv4(Default::default()), |
| 81 | RESOURCES.init(StackResources::<2>::new()), | 81 | RESOURCES.init(StackResources::new()), |
| 82 | seed, | 82 | seed, |
| 83 | )); | 83 | )); |
| 84 | 84 | ||
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 1613ed887..c79f01538 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs | |||
| @@ -72,11 +72,11 @@ async fn main(spawner: Spawner) { | |||
| 72 | 72 | ||
| 73 | // Init network stack | 73 | // Init network stack |
| 74 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | 74 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); |
| 75 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 75 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 76 | let stack = &*STACK.init(Stack::new( | 76 | let stack = &*STACK.init(Stack::new( |
| 77 | device, | 77 | device, |
| 78 | embassy_net::Config::dhcpv4(Default::default()), | 78 | embassy_net::Config::dhcpv4(Default::default()), |
| 79 | RESOURCES.init(StackResources::<2>::new()), | 79 | RESOURCES.init(StackResources::new()), |
| 80 | seed, | 80 | seed, |
| 81 | )); | 81 | )); |
| 82 | 82 | ||
diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs new file mode 100644 index 000000000..0e21d5833 --- /dev/null +++ b/examples/rp/src/bin/orchestrate_tasks.rs | |||
| @@ -0,0 +1,318 @@ | |||
| 1 | //! This example demonstrates some approaches to communicate between tasks in order to orchestrate the state of the system. | ||
| 2 | //! | ||
| 3 | //! We demonstrate how to: | ||
| 4 | //! - use a channel to send messages between tasks, in this case here in order to have one task control the state of the system. | ||
| 5 | //! - use a signal to terminate a task. | ||
| 6 | //! - use command channels to send commands to another task. | ||
| 7 | //! - use different ways to receive messages, from a straightforwar awaiting on one channel to a more complex awaiting on multiple futures. | ||
| 8 | //! | ||
| 9 | //! There are more patterns to orchestrate tasks, this is just one example. | ||
| 10 | //! | ||
| 11 | //! We will use these tasks to generate example "state information": | ||
| 12 | //! - a task that generates random numbers in intervals of 60s | ||
| 13 | //! - a task that generates random numbers in intervals of 30s | ||
| 14 | //! - a task that generates random numbers in intervals of 90s | ||
| 15 | //! - a task that notifies about being attached/disattached from usb power | ||
| 16 | //! - a task that measures vsys voltage in intervals of 30s | ||
| 17 | //! - a task that consumes the state information and reacts to it | ||
| 18 | |||
| 19 | #![no_std] | ||
| 20 | #![no_main] | ||
| 21 | |||
| 22 | use assign_resources::assign_resources; | ||
| 23 | use defmt::*; | ||
| 24 | use embassy_executor::Spawner; | ||
| 25 | use embassy_futures::select::{select, Either}; | ||
| 26 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; | ||
| 27 | use embassy_rp::clocks::RoscRng; | ||
| 28 | use embassy_rp::gpio::{Input, Pull}; | ||
| 29 | use embassy_rp::{bind_interrupts, peripherals}; | ||
| 30 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 31 | use embassy_sync::{channel, signal}; | ||
| 32 | use embassy_time::{Duration, Timer}; | ||
| 33 | use rand::RngCore; | ||
| 34 | use {defmt_rtt as _, panic_probe as _}; | ||
| 35 | |||
| 36 | // This is just some preparation, see example `assign_resources.rs` for more information on this. We prep the rresources that we will be using in different tasks. | ||
| 37 | // **Note**: This will not work with a board that has a wifi chip, because the wifi chip uses pins 24 and 29 for its own purposes. A way around this in software | ||
| 38 | // is not trivial, at least if you intend to use wifi, too. Workaround is to wire from vsys and vbus pins to appropriate pins on the board through a voltage divider. Then use those pins. | ||
| 39 | // For this example it will not matter much, the concept of what we are showing remains valid. | ||
| 40 | assign_resources! { | ||
| 41 | vsys: Vsys { | ||
| 42 | adc: ADC, | ||
| 43 | pin_29: PIN_29, | ||
| 44 | }, | ||
| 45 | vbus: Vbus { | ||
| 46 | pin_24: PIN_24, | ||
| 47 | }, | ||
| 48 | } | ||
| 49 | |||
| 50 | bind_interrupts!(struct Irqs { | ||
| 51 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 52 | }); | ||
| 53 | |||
| 54 | /// This is the type of Events that we will send from the worker tasks to the orchestrating task. | ||
| 55 | enum Events { | ||
| 56 | UsbPowered(bool), | ||
| 57 | VsysVoltage(f32), | ||
| 58 | FirstRandomSeed(u32), | ||
| 59 | SecondRandomSeed(u32), | ||
| 60 | ThirdRandomSeed(u32), | ||
| 61 | ResetFirstRandomSeed, | ||
| 62 | } | ||
| 63 | |||
| 64 | /// This is the type of Commands that we will send from the orchestrating task to the worker tasks. | ||
| 65 | /// Note that we are lazy here and only have one command, you might want to have more. | ||
| 66 | enum Commands { | ||
| 67 | /// This command will stop the appropriate worker task | ||
| 68 | Stop, | ||
| 69 | } | ||
| 70 | |||
| 71 | /// This is the state of the system, we will use this to orchestrate the system. This is a simple example, in a real world application this would be more complex. | ||
| 72 | #[derive(Default, Debug, Clone, Format)] | ||
| 73 | struct State { | ||
| 74 | usb_powered: bool, | ||
| 75 | vsys_voltage: f32, | ||
| 76 | first_random_seed: u32, | ||
| 77 | second_random_seed: u32, | ||
| 78 | third_random_seed: u32, | ||
| 79 | times_we_got_first_random_seed: u8, | ||
| 80 | maximum_times_we_want_first_random_seed: u8, | ||
| 81 | } | ||
| 82 | |||
| 83 | impl State { | ||
| 84 | fn new() -> Self { | ||
| 85 | Self { | ||
| 86 | usb_powered: false, | ||
| 87 | vsys_voltage: 0.0, | ||
| 88 | first_random_seed: 0, | ||
| 89 | second_random_seed: 0, | ||
| 90 | third_random_seed: 0, | ||
| 91 | times_we_got_first_random_seed: 0, | ||
| 92 | maximum_times_we_want_first_random_seed: 3, | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Channel for the events that we want the orchestrator to react to, all state events are of the type Enum Events. | ||
| 98 | /// We use a channel with an arbitrary size of 10, the precise size of the queue depends on your use case. This depends on how many events we | ||
| 99 | /// expect to be generated in a given time frame and how fast the orchestrator can react to them. And then if we rather want the senders to wait for | ||
| 100 | /// new slots in the queue or if we want the orchestrator to have a backlog of events to process. In this case here we expect to always be enough slots | ||
| 101 | /// in the queue, so the worker tasks can in all nominal cases send their events and continue with their work without waiting. | ||
| 102 | /// For the events we - in this case here - do not want to loose any events, so a channel is a good choice. See embassy_sync docs for other options. | ||
| 103 | static EVENT_CHANNEL: channel::Channel<CriticalSectionRawMutex, Events, 10> = channel::Channel::new(); | ||
| 104 | |||
| 105 | /// Signal for stopping the first random signal task. We use a signal here, because we need no queue. It is suffiient to have one signal active. | ||
| 106 | static STOP_FIRST_RANDOM_SIGNAL: signal::Signal<CriticalSectionRawMutex, Commands> = signal::Signal::new(); | ||
| 107 | |||
| 108 | /// Channel for the state that we want the consumer task to react to. We use a channel here, because we want to have a queue of state changes, although | ||
| 109 | /// we want the queue to be of size 1, because we want to finish rwacting to the state change before the next one comes in. This is just a design choice | ||
| 110 | /// and depends on your use case. | ||
| 111 | static CONSUMER_CHANNEL: channel::Channel<CriticalSectionRawMutex, State, 1> = channel::Channel::new(); | ||
| 112 | |||
| 113 | // And now we can put all this into use | ||
| 114 | |||
| 115 | /// This is the main task, that will not do very much besides spawning the other tasks. This is a design choice, you could do the | ||
| 116 | /// orchestrating here. This is to show that we do not need a main loop here, the system will run indefinitely as long as at least one task is running. | ||
| 117 | #[embassy_executor::main] | ||
| 118 | async fn main(spawner: Spawner) { | ||
| 119 | // initialize the peripherals | ||
| 120 | let p = embassy_rp::init(Default::default()); | ||
| 121 | // split the resources, for convenience - see above | ||
| 122 | let r = split_resources! {p}; | ||
| 123 | |||
| 124 | // spawn the tasks | ||
| 125 | spawner.spawn(orchestrate(spawner)).unwrap(); | ||
| 126 | spawner.spawn(random_60s(spawner)).unwrap(); | ||
| 127 | spawner.spawn(random_90s(spawner)).unwrap(); | ||
| 128 | spawner.spawn(usb_power(spawner, r.vbus)).unwrap(); | ||
| 129 | spawner.spawn(vsys_voltage(spawner, r.vsys)).unwrap(); | ||
| 130 | spawner.spawn(consumer(spawner)).unwrap(); | ||
| 131 | } | ||
| 132 | |||
| 133 | /// This is the task handling the system state and orchestrating the other tasks. WEe can regard this as the "main loop" of the system. | ||
| 134 | #[embassy_executor::task] | ||
| 135 | async fn orchestrate(_spawner: Spawner) { | ||
| 136 | let mut state = State::new(); | ||
| 137 | |||
| 138 | // we need to have a receiver for the events | ||
| 139 | let receiver = EVENT_CHANNEL.receiver(); | ||
| 140 | |||
| 141 | // and we need a sender for the consumer task | ||
| 142 | let state_sender = CONSUMER_CHANNEL.sender(); | ||
| 143 | |||
| 144 | loop { | ||
| 145 | // we await on the receiver, this will block until a new event is available | ||
| 146 | // as an alternative to this, we could also await on multiple channels, this would block until at least one of the channels has an event | ||
| 147 | // see the embassy_futures docs: https://docs.embassy.dev/embassy-futures/git/default/select/index.html | ||
| 148 | // The task random_30s does a select, if you want to have a look at that. | ||
| 149 | // Another reason to use select may also be that we want to have a timeout, so we can react to the absence of events within a time frame. | ||
| 150 | // We keep it simple here. | ||
| 151 | let event = receiver.receive().await; | ||
| 152 | |||
| 153 | // react to the events | ||
| 154 | match event { | ||
| 155 | Events::UsbPowered(usb_powered) => { | ||
| 156 | // update the state and/or react to the event here | ||
| 157 | state.usb_powered = usb_powered; | ||
| 158 | info!("Usb powered: {}", usb_powered); | ||
| 159 | } | ||
| 160 | Events::VsysVoltage(voltage) => { | ||
| 161 | // update the state and/or react to the event here | ||
| 162 | state.vsys_voltage = voltage; | ||
| 163 | info!("Vsys voltage: {}", voltage); | ||
| 164 | } | ||
| 165 | Events::FirstRandomSeed(seed) => { | ||
| 166 | // update the state and/or react to the event here | ||
| 167 | state.first_random_seed = seed; | ||
| 168 | // here we change some meta state, we count how many times we got the first random seed | ||
| 169 | state.times_we_got_first_random_seed += 1; | ||
| 170 | info!( | ||
| 171 | "First random seed: {}, and that was iteration {} of receiving this.", | ||
| 172 | seed, &state.times_we_got_first_random_seed | ||
| 173 | ); | ||
| 174 | } | ||
| 175 | Events::SecondRandomSeed(seed) => { | ||
| 176 | // update the state and/or react to the event here | ||
| 177 | state.second_random_seed = seed; | ||
| 178 | info!("Second random seed: {}", seed); | ||
| 179 | } | ||
| 180 | Events::ThirdRandomSeed(seed) => { | ||
| 181 | // update the state and/or react to the event here | ||
| 182 | state.third_random_seed = seed; | ||
| 183 | info!("Third random seed: {}", seed); | ||
| 184 | } | ||
| 185 | Events::ResetFirstRandomSeed => { | ||
| 186 | // update the state and/or react to the event here | ||
| 187 | state.times_we_got_first_random_seed = 0; | ||
| 188 | state.first_random_seed = 0; | ||
| 189 | info!("Resetting the first random seed counter"); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | // we now have an altered state | ||
| 193 | // there is a crate for detecting field changes on crates.io (https://crates.io/crates/fieldset) that might be useful here | ||
| 194 | // for now we just keep it simple | ||
| 195 | |||
| 196 | // we send the state to the consumer task | ||
| 197 | // since the channel has a size of 1, this will block until the consumer task has received the state, which is what we want here in this example | ||
| 198 | // **Note:** It is bad design to send too much data between tasks, with no clear definition of what "too much" is. In this example we send the | ||
| 199 | // whole state, in a real world application you might want to send only the data, that is relevant to the consumer task AND only when it has changed. | ||
| 200 | // We keep it simple here. | ||
| 201 | state_sender.send(state.clone()).await; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | /// This task will consume the state information and react to it. This is a simple example, in a real world application this would be more complex | ||
| 206 | /// and we could have multiple consumer tasks, each reacting to different parts of the state. | ||
| 207 | #[embassy_executor::task] | ||
| 208 | async fn consumer(spawner: Spawner) { | ||
| 209 | // we need to have a receiver for the state | ||
| 210 | let receiver = CONSUMER_CHANNEL.receiver(); | ||
| 211 | let sender = EVENT_CHANNEL.sender(); | ||
| 212 | loop { | ||
| 213 | // we await on the receiver, this will block until a new state is available | ||
| 214 | let state = receiver.receive().await; | ||
| 215 | // react to the state, in this case here we just log it | ||
| 216 | info!("The consumer has reveived this state: {:?}", &state); | ||
| 217 | |||
| 218 | // here we react to the state, in this case here we want to start or stop the first random signal task depending on the state of the system | ||
| 219 | match state.times_we_got_first_random_seed { | ||
| 220 | max if max == state.maximum_times_we_want_first_random_seed => { | ||
| 221 | info!("Stopping the first random signal task"); | ||
| 222 | // we send a command to the task | ||
| 223 | STOP_FIRST_RANDOM_SIGNAL.signal(Commands::Stop); | ||
| 224 | // we notify the orchestrator that we have sent the command | ||
| 225 | sender.send(Events::ResetFirstRandomSeed).await; | ||
| 226 | } | ||
| 227 | 0 => { | ||
| 228 | // we start the task, which presents us with an interesting problem, because we may return here before the task has started | ||
| 229 | // here we just try and log if the task has started, in a real world application you might want to handle this more gracefully | ||
| 230 | info!("Starting the first random signal task"); | ||
| 231 | match spawner.spawn(random_30s(spawner)) { | ||
| 232 | Ok(_) => info!("Successfully spawned random_30s task"), | ||
| 233 | Err(e) => info!("Failed to spawn random_30s task: {:?}", e), | ||
| 234 | } | ||
| 235 | } | ||
| 236 | _ => {} | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | /// This task will generate random numbers in intervals of 30s | ||
| 242 | /// The task will terminate after it has received a command signal to stop, see the orchestrate task for that. | ||
| 243 | /// Note that we are not spawning this task from main, as we will show how such a task can be spawned and closed dynamically. | ||
| 244 | #[embassy_executor::task] | ||
| 245 | async fn random_30s(_spawner: Spawner) { | ||
| 246 | let mut rng = RoscRng; | ||
| 247 | let sender = EVENT_CHANNEL.sender(); | ||
| 248 | loop { | ||
| 249 | // we either await on the timer or the signal, whichever comes first. | ||
| 250 | let futures = select(Timer::after(Duration::from_secs(30)), STOP_FIRST_RANDOM_SIGNAL.wait()).await; | ||
| 251 | match futures { | ||
| 252 | Either::First(_) => { | ||
| 253 | // we received are operating on the timer | ||
| 254 | info!("30s are up, generating random number"); | ||
| 255 | let random_number = rng.next_u32(); | ||
| 256 | sender.send(Events::FirstRandomSeed(random_number)).await; | ||
| 257 | } | ||
| 258 | Either::Second(_) => { | ||
| 259 | // we received the signal to stop | ||
| 260 | info!("Received signal to stop, goodbye!"); | ||
| 261 | break; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | /// This task will generate random numbers in intervals of 60s | ||
| 268 | #[embassy_executor::task] | ||
| 269 | async fn random_60s(_spawner: Spawner) { | ||
| 270 | let mut rng = RoscRng; | ||
| 271 | let sender = EVENT_CHANNEL.sender(); | ||
| 272 | loop { | ||
| 273 | Timer::after(Duration::from_secs(60)).await; | ||
| 274 | let random_number = rng.next_u32(); | ||
| 275 | sender.send(Events::SecondRandomSeed(random_number)).await; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | /// This task will generate random numbers in intervals of 90s | ||
| 280 | #[embassy_executor::task] | ||
| 281 | async fn random_90s(_spawner: Spawner) { | ||
| 282 | let mut rng = RoscRng; | ||
| 283 | let sender = EVENT_CHANNEL.sender(); | ||
| 284 | loop { | ||
| 285 | Timer::after(Duration::from_secs(90)).await; | ||
| 286 | let random_number = rng.next_u32(); | ||
| 287 | sender.send(Events::ThirdRandomSeed(random_number)).await; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | /// This task will notify if we are connected to usb power | ||
| 292 | #[embassy_executor::task] | ||
| 293 | pub async fn usb_power(_spawner: Spawner, r: Vbus) { | ||
| 294 | let mut vbus_in = Input::new(r.pin_24, Pull::None); | ||
| 295 | let sender = EVENT_CHANNEL.sender(); | ||
| 296 | loop { | ||
| 297 | sender.send(Events::UsbPowered(vbus_in.is_high())).await; | ||
| 298 | vbus_in.wait_for_any_edge().await; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | /// This task will measure the vsys voltage in intervals of 30s | ||
| 303 | #[embassy_executor::task] | ||
| 304 | pub async fn vsys_voltage(_spawner: Spawner, r: Vsys) { | ||
| 305 | let mut adc = Adc::new(r.adc, Irqs, Config::default()); | ||
| 306 | let vsys_in = r.pin_29; | ||
| 307 | let mut channel = Channel::new_pin(vsys_in, Pull::None); | ||
| 308 | let sender = EVENT_CHANNEL.sender(); | ||
| 309 | loop { | ||
| 310 | // read the adc value | ||
| 311 | let adc_value = adc.read(&mut channel).await.unwrap(); | ||
| 312 | // convert the adc value to voltage. | ||
| 313 | // 3.3 is the reference voltage, 3.0 is the factor for the inbuilt voltage divider and 4096 is the resolution of the adc | ||
| 314 | let voltage = (adc_value as f32) * 3.3 * 3.0 / 4096.0; | ||
| 315 | sender.send(Events::VsysVoltage(voltage)).await; | ||
| 316 | Timer::after(Duration::from_secs(30)).await; | ||
| 317 | } | ||
| 318 | } | ||
diff --git a/examples/rp/src/bin/shared_bus.rs b/examples/rp/src/bin/shared_bus.rs new file mode 100644 index 000000000..c6cb5d64c --- /dev/null +++ b/examples/rp/src/bin/shared_bus.rs | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | //! This example shows how to share (async) I2C and SPI buses between multiple devices. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; | ||
| 8 | use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::gpio::{AnyPin, Level, Output}; | ||
| 12 | use embassy_rp::i2c::{self, I2c, InterruptHandler}; | ||
| 13 | use embassy_rp::peripherals::{I2C1, SPI1}; | ||
| 14 | use embassy_rp::spi::{self, Spi}; | ||
| 15 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 16 | use embassy_sync::mutex::Mutex; | ||
| 17 | use embassy_time::Timer; | ||
| 18 | use static_cell::StaticCell; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | type Spi1Bus = Mutex<NoopRawMutex, Spi<'static, SPI1, spi::Async>>; | ||
| 22 | type I2c1Bus = Mutex<NoopRawMutex, I2c<'static, I2C1, i2c::Async>>; | ||
| 23 | |||
| 24 | bind_interrupts!(struct Irqs { | ||
| 25 | I2C1_IRQ => InterruptHandler<I2C1>; | ||
| 26 | }); | ||
| 27 | |||
| 28 | #[embassy_executor::main] | ||
| 29 | async fn main(spawner: Spawner) { | ||
| 30 | let p = embassy_rp::init(Default::default()); | ||
| 31 | info!("Here we go!"); | ||
| 32 | |||
| 33 | // Shared I2C bus | ||
| 34 | let i2c = I2c::new_async(p.I2C1, p.PIN_15, p.PIN_14, Irqs, i2c::Config::default()); | ||
| 35 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); | ||
| 36 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); | ||
| 37 | |||
| 38 | spawner.must_spawn(i2c_task_a(i2c_bus)); | ||
| 39 | spawner.must_spawn(i2c_task_b(i2c_bus)); | ||
| 40 | |||
| 41 | // Shared SPI bus | ||
| 42 | let spi_cfg = spi::Config::default(); | ||
| 43 | let spi = Spi::new(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 44 | static SPI_BUS: StaticCell<Spi1Bus> = StaticCell::new(); | ||
| 45 | let spi_bus = SPI_BUS.init(Mutex::new(spi)); | ||
| 46 | |||
| 47 | // Chip select pins for the SPI devices | ||
| 48 | let cs_a = Output::new(AnyPin::from(p.PIN_0), Level::High); | ||
| 49 | let cs_b = Output::new(AnyPin::from(p.PIN_1), Level::High); | ||
| 50 | |||
| 51 | spawner.must_spawn(spi_task_a(spi_bus, cs_a)); | ||
| 52 | spawner.must_spawn(spi_task_b(spi_bus, cs_b)); | ||
| 53 | } | ||
| 54 | |||
| 55 | #[embassy_executor::task] | ||
| 56 | async fn i2c_task_a(i2c_bus: &'static I2c1Bus) { | ||
| 57 | let i2c_dev = I2cDevice::new(i2c_bus); | ||
| 58 | let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xC0); | ||
| 59 | loop { | ||
| 60 | info!("i2c task A"); | ||
| 61 | Timer::after_secs(1).await; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | #[embassy_executor::task] | ||
| 66 | async fn i2c_task_b(i2c_bus: &'static I2c1Bus) { | ||
| 67 | let i2c_dev = I2cDevice::new(i2c_bus); | ||
| 68 | let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xDE); | ||
| 69 | loop { | ||
| 70 | info!("i2c task B"); | ||
| 71 | Timer::after_secs(1).await; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | #[embassy_executor::task] | ||
| 76 | async fn spi_task_a(spi_bus: &'static Spi1Bus, cs: Output<'static>) { | ||
| 77 | let spi_dev = SpiDevice::new(spi_bus, cs); | ||
| 78 | let _sensor = DummySpiDeviceDriver::new(spi_dev); | ||
| 79 | loop { | ||
| 80 | info!("spi task A"); | ||
| 81 | Timer::after_secs(1).await; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | #[embassy_executor::task] | ||
| 86 | async fn spi_task_b(spi_bus: &'static Spi1Bus, cs: Output<'static>) { | ||
| 87 | let spi_dev = SpiDevice::new(spi_bus, cs); | ||
| 88 | let _sensor = DummySpiDeviceDriver::new(spi_dev); | ||
| 89 | loop { | ||
| 90 | info!("spi task B"); | ||
| 91 | Timer::after_secs(1).await; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | // Dummy I2C device driver, using `embedded-hal-async` | ||
| 96 | struct DummyI2cDeviceDriver<I2C: embedded_hal_async::i2c::I2c> { | ||
| 97 | _i2c: I2C, | ||
| 98 | } | ||
| 99 | |||
| 100 | impl<I2C: embedded_hal_async::i2c::I2c> DummyI2cDeviceDriver<I2C> { | ||
| 101 | fn new(i2c_dev: I2C, _address: u8) -> Self { | ||
| 102 | Self { _i2c: i2c_dev } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | // Dummy SPI device driver, using `embedded-hal-async` | ||
| 107 | struct DummySpiDeviceDriver<SPI: embedded_hal_async::spi::SpiDevice> { | ||
| 108 | _spi: SPI, | ||
| 109 | } | ||
| 110 | |||
| 111 | impl<SPI: embedded_hal_async::spi::SpiDevice> DummySpiDeviceDriver<SPI> { | ||
| 112 | fn new(spi_dev: SPI) -> Self { | ||
| 113 | Self { _spi: spi_dev } | ||
| 114 | } | ||
| 115 | } | ||
diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs new file mode 100644 index 000000000..5416e20ce --- /dev/null +++ b/examples/rp/src/bin/sharing.rs | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | //! This example shows some common strategies for sharing resources between tasks. | ||
| 2 | //! | ||
| 3 | //! We demonstrate five different ways of sharing, covering different use cases: | ||
| 4 | //! - Atomics: This method is used for simple values, such as bool and u8..u32 | ||
| 5 | //! - Blocking Mutex: This is used for sharing non-async things, using Cell/RefCell for interior mutability. | ||
| 6 | //! - Async Mutex: This is used for sharing async resources, where you need to hold the lock across await points. | ||
| 7 | //! The async Mutex has interior mutability built-in, so no RefCell is needed. | ||
| 8 | //! - Cell: For sharing Copy types between tasks running on the same executor. | ||
| 9 | //! - RefCell: When you want &mut access to a value shared between tasks running on the same executor. | ||
| 10 | //! | ||
| 11 | //! More information: https://embassy.dev/book/#_sharing_peripherals_between_tasks | ||
| 12 | |||
| 13 | #![no_std] | ||
| 14 | #![no_main] | ||
| 15 | |||
| 16 | use core::cell::{Cell, RefCell}; | ||
| 17 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 18 | |||
| 19 | use cortex_m_rt::entry; | ||
| 20 | use defmt::info; | ||
| 21 | use embassy_executor::{Executor, InterruptExecutor}; | ||
| 22 | use embassy_rp::clocks::RoscRng; | ||
| 23 | use embassy_rp::interrupt::{InterruptExt, Priority}; | ||
| 24 | use embassy_rp::peripherals::UART0; | ||
| 25 | use embassy_rp::uart::{self, InterruptHandler, UartTx}; | ||
| 26 | use embassy_rp::{bind_interrupts, interrupt}; | ||
| 27 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 28 | use embassy_sync::{blocking_mutex, mutex}; | ||
| 29 | use embassy_time::{Duration, Ticker}; | ||
| 30 | use rand::RngCore; | ||
| 31 | use static_cell::{ConstStaticCell, StaticCell}; | ||
| 32 | use {defmt_rtt as _, panic_probe as _}; | ||
| 33 | |||
| 34 | type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>; | ||
| 35 | |||
| 36 | struct MyType { | ||
| 37 | inner: u32, | ||
| 38 | } | ||
| 39 | |||
| 40 | static EXECUTOR_HI: InterruptExecutor = InterruptExecutor::new(); | ||
| 41 | static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | ||
| 42 | |||
| 43 | // Use Atomics for simple values | ||
| 44 | static ATOMIC: AtomicU32 = AtomicU32::new(0); | ||
| 45 | |||
| 46 | // Use blocking Mutex with Cell/RefCell for sharing non-async things | ||
| 47 | static MUTEX_BLOCKING: blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<MyType>> = | ||
| 48 | blocking_mutex::Mutex::new(RefCell::new(MyType { inner: 0 })); | ||
| 49 | |||
| 50 | bind_interrupts!(struct Irqs { | ||
| 51 | UART0_IRQ => InterruptHandler<UART0>; | ||
| 52 | }); | ||
| 53 | |||
| 54 | #[interrupt] | ||
| 55 | unsafe fn SWI_IRQ_0() { | ||
| 56 | EXECUTOR_HI.on_interrupt() | ||
| 57 | } | ||
| 58 | |||
| 59 | #[entry] | ||
| 60 | fn main() -> ! { | ||
| 61 | let p = embassy_rp::init(Default::default()); | ||
| 62 | info!("Here we go!"); | ||
| 63 | |||
| 64 | let uart = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, uart::Config::default()); | ||
| 65 | // Use the async Mutex for sharing async things (built-in interior mutability) | ||
| 66 | static UART: StaticCell<UartAsyncMutex> = StaticCell::new(); | ||
| 67 | let uart = UART.init(mutex::Mutex::new(uart)); | ||
| 68 | |||
| 69 | // High-priority executor: runs in interrupt mode | ||
| 70 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | ||
| 71 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); | ||
| 72 | spawner.must_spawn(task_a(uart)); | ||
| 73 | |||
| 74 | // Low priority executor: runs in thread mode | ||
| 75 | let executor = EXECUTOR_LOW.init(Executor::new()); | ||
| 76 | executor.run(|spawner| { | ||
| 77 | // No Mutex needed when sharing between tasks running on the same executor | ||
| 78 | |||
| 79 | // Use Cell for Copy-types | ||
| 80 | static CELL: ConstStaticCell<Cell<[u8; 4]>> = ConstStaticCell::new(Cell::new([0; 4])); | ||
| 81 | let cell = CELL.take(); | ||
| 82 | |||
| 83 | // Use RefCell for &mut access | ||
| 84 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); | ||
| 85 | let ref_cell = REF_CELL.take(); | ||
| 86 | |||
| 87 | spawner.must_spawn(task_b(uart, cell, ref_cell)); | ||
| 88 | spawner.must_spawn(task_c(cell, ref_cell)); | ||
| 89 | }); | ||
| 90 | } | ||
| 91 | |||
| 92 | #[embassy_executor::task] | ||
| 93 | async fn task_a(uart: &'static UartAsyncMutex) { | ||
| 94 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 95 | loop { | ||
| 96 | let random = RoscRng.next_u32(); | ||
| 97 | |||
| 98 | { | ||
| 99 | let mut uart = uart.lock().await; | ||
| 100 | uart.write(b"task a").await.unwrap(); | ||
| 101 | // The uart lock is released when it goes out of scope | ||
| 102 | } | ||
| 103 | |||
| 104 | ATOMIC.store(random, Ordering::Relaxed); | ||
| 105 | |||
| 106 | MUTEX_BLOCKING.lock(|x| x.borrow_mut().inner = random); | ||
| 107 | |||
| 108 | ticker.next().await; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | #[embassy_executor::task] | ||
| 113 | async fn task_b(uart: &'static UartAsyncMutex, cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell<MyType>) { | ||
| 114 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 115 | loop { | ||
| 116 | let random = RoscRng.next_u32(); | ||
| 117 | |||
| 118 | uart.lock().await.write(b"task b").await.unwrap(); | ||
| 119 | |||
| 120 | cell.set(random.to_be_bytes()); | ||
| 121 | |||
| 122 | ref_cell.borrow_mut().inner = random; | ||
| 123 | |||
| 124 | ticker.next().await; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | #[embassy_executor::task] | ||
| 129 | async fn task_c(cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell<MyType>) { | ||
| 130 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 131 | loop { | ||
| 132 | info!("======================="); | ||
| 133 | |||
| 134 | let atomic_val = ATOMIC.load(Ordering::Relaxed); | ||
| 135 | info!("atomic: {}", atomic_val); | ||
| 136 | |||
| 137 | MUTEX_BLOCKING.lock(|x| { | ||
| 138 | let val = x.borrow().inner; | ||
| 139 | info!("blocking mutex: {}", val); | ||
| 140 | }); | ||
| 141 | |||
| 142 | let cell_val = cell.get(); | ||
| 143 | info!("cell: {:?}", cell_val); | ||
| 144 | |||
| 145 | let ref_cell_val = ref_cell.borrow().inner; | ||
| 146 | info!("ref_cell: {:?}", ref_cell_val); | ||
| 147 | |||
| 148 | ticker.next().await; | ||
| 149 | } | ||
| 150 | } | ||
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index fac61aa04..468d2b61a 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs | |||
| @@ -31,7 +31,7 @@ async fn main(spawner: Spawner) { | |||
| 31 | static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new(); | 31 | static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new(); |
| 32 | let rx_buf = &mut RX_BUF.init([0; 16])[..]; | 32 | let rx_buf = &mut RX_BUF.init([0; 16])[..]; |
| 33 | let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); | 33 | let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); |
| 34 | let (rx, mut tx) = uart.split(); | 34 | let (mut tx, rx) = uart.split(); |
| 35 | 35 | ||
| 36 | unwrap!(spawner.spawn(reader(rx))); | 36 | unwrap!(spawner.spawn(reader(rx))); |
| 37 | 37 | ||
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 22dc88d28..03c510f37 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -109,13 +109,8 @@ async fn main(spawner: Spawner) { | |||
| 109 | 109 | ||
| 110 | // Init network stack | 110 | // Init network stack |
| 111 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | 111 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); |
| 112 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 112 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 113 | let stack = &*STACK.init(Stack::new( | 113 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 114 | device, | ||
| 115 | config, | ||
| 116 | RESOURCES.init(StackResources::<2>::new()), | ||
| 117 | seed, | ||
| 118 | )); | ||
| 119 | 114 | ||
| 120 | unwrap!(spawner.spawn(net_task(stack))); | 115 | unwrap!(spawner.spawn(net_task(stack))); |
| 121 | 116 | ||
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index cce344fb0..5ee650910 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs | |||
| @@ -8,7 +8,6 @@ use embassy_executor::Spawner; | |||
| 8 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 9 | use embassy_rp::bind_interrupts; | 9 | use embassy_rp::bind_interrupts; |
| 10 | use embassy_rp::clocks::RoscRng; | 10 | use embassy_rp::clocks::RoscRng; |
| 11 | use embassy_rp::gpio::{Input, Pull}; | ||
| 12 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 13 | use embassy_rp::usb::{Driver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| 14 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| @@ -75,12 +74,6 @@ async fn main(_spawner: Spawner) { | |||
| 75 | // Run the USB device. | 74 | // Run the USB device. |
| 76 | let usb_fut = usb.run(); | 75 | let usb_fut = usb.run(); |
| 77 | 76 | ||
| 78 | // Set up the signal pin that will be used to trigger the keyboard. | ||
| 79 | let mut signal_pin = Input::new(p.PIN_16, Pull::None); | ||
| 80 | |||
| 81 | // Enable the schmitt trigger to slightly debounce. | ||
| 82 | signal_pin.set_schmitt(true); | ||
| 83 | |||
| 84 | let (reader, mut writer) = hid.split(); | 77 | let (reader, mut writer) = hid.split(); |
| 85 | 78 | ||
| 86 | // Do stuff with the class! | 79 | // Do stuff with the class! |
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 4fc2690e3..00f404a9b 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -28,7 +28,7 @@ bind_interrupts!(struct Irqs { | |||
| 28 | }); | 28 | }); |
| 29 | 29 | ||
| 30 | #[embassy_executor::task] | 30 | #[embassy_executor::task] |
| 31 | async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | 31 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { |
| 32 | runner.run().await | 32 | runner.run().await |
| 33 | } | 33 | } |
| 34 | 34 | ||
| @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { | |||
| 62 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 62 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 63 | let state = STATE.init(cyw43::State::new()); | 63 | let state = STATE.init(cyw43::State::new()); |
| 64 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 64 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 65 | unwrap!(spawner.spawn(wifi_task(runner))); | 65 | unwrap!(spawner.spawn(cyw43_task(runner))); |
| 66 | 66 | ||
| 67 | control.init(clm).await; | 67 | control.init(clm).await; |
| 68 | control | 68 | control |
| @@ -81,11 +81,11 @@ async fn main(spawner: Spawner) { | |||
| 81 | 81 | ||
| 82 | // Init network stack | 82 | // Init network stack |
| 83 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | 83 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); |
| 84 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 84 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 85 | let stack = &*STACK.init(Stack::new( | 85 | let stack = &*STACK.init(Stack::new( |
| 86 | net_device, | 86 | net_device, |
| 87 | config, | 87 | config, |
| 88 | RESOURCES.init(StackResources::<2>::new()), | 88 | RESOURCES.init(StackResources::new()), |
| 89 | seed, | 89 | seed, |
| 90 | )); | 90 | )); |
| 91 | 91 | ||
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index 471349639..04a61bbd5 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs | |||
| @@ -21,7 +21,7 @@ bind_interrupts!(struct Irqs { | |||
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | #[embassy_executor::task] | 23 | #[embassy_executor::task] |
| 24 | async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | 24 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { |
| 25 | runner.run().await | 25 | runner.run().await |
| 26 | } | 26 | } |
| 27 | 27 | ||
| @@ -46,7 +46,7 @@ async fn main(spawner: Spawner) { | |||
| 46 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 46 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 47 | let state = STATE.init(cyw43::State::new()); | 47 | let state = STATE.init(cyw43::State::new()); |
| 48 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 48 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 49 | unwrap!(spawner.spawn(wifi_task(runner))); | 49 | unwrap!(spawner.spawn(cyw43_task(runner))); |
| 50 | 50 | ||
| 51 | control.init(clm).await; | 51 | control.init(clm).await; |
| 52 | control | 52 | control |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 5f4c848a2..ab3529112 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -23,7 +23,7 @@ bind_interrupts!(struct Irqs { | |||
| 23 | }); | 23 | }); |
| 24 | 24 | ||
| 25 | #[embassy_executor::task] | 25 | #[embassy_executor::task] |
| 26 | async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | 26 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { |
| 27 | runner.run().await | 27 | runner.run().await |
| 28 | } | 28 | } |
| 29 | 29 | ||
| @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) { | |||
| 56 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 56 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 57 | let state = STATE.init(cyw43::State::new()); | 57 | let state = STATE.init(cyw43::State::new()); |
| 58 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 58 | let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 59 | unwrap!(spawner.spawn(wifi_task(runner))); | 59 | unwrap!(spawner.spawn(cyw43_task(runner))); |
| 60 | 60 | ||
| 61 | control.init(clm).await; | 61 | control.init(clm).await; |
| 62 | control | 62 | control |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 5575df677..b2950d98a 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use core::str::from_utf8; | 8 | use core::str::from_utf8; |
| 9 | 9 | ||
| 10 | use cyw43::JoinOptions; | ||
| 10 | use cyw43_pio::PioSpi; | 11 | use cyw43_pio::PioSpi; |
| 11 | use defmt::*; | 12 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| @@ -27,11 +28,11 @@ bind_interrupts!(struct Irqs { | |||
| 27 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | 28 | PIO0_IRQ_0 => InterruptHandler<PIO0>; |
| 28 | }); | 29 | }); |
| 29 | 30 | ||
| 30 | const WIFI_NETWORK: &str = "EmbassyTest"; | 31 | const WIFI_NETWORK: &str = "LadronDeWifi"; |
| 31 | const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; | 32 | const WIFI_PASSWORD: &str = "MBfcaedHmyRFE4kaQ1O5SsY8"; |
| 32 | 33 | ||
| 33 | #[embassy_executor::task] | 34 | #[embassy_executor::task] |
| 34 | async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | 35 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { |
| 35 | runner.run().await | 36 | runner.run().await |
| 36 | } | 37 | } |
| 37 | 38 | ||
| @@ -65,7 +66,7 @@ async fn main(spawner: Spawner) { | |||
| 65 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 66 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 66 | let state = STATE.init(cyw43::State::new()); | 67 | let state = STATE.init(cyw43::State::new()); |
| 67 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; | 68 | let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; |
| 68 | unwrap!(spawner.spawn(wifi_task(runner))); | 69 | unwrap!(spawner.spawn(cyw43_task(runner))); |
| 69 | 70 | ||
| 70 | control.init(clm).await; | 71 | control.init(clm).await; |
| 71 | control | 72 | control |
| @@ -84,19 +85,21 @@ async fn main(spawner: Spawner) { | |||
| 84 | 85 | ||
| 85 | // Init network stack | 86 | // Init network stack |
| 86 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); | 87 | static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new(); |
| 87 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 88 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 88 | let stack = &*STACK.init(Stack::new( | 89 | let stack = &*STACK.init(Stack::new( |
| 89 | net_device, | 90 | net_device, |
| 90 | config, | 91 | config, |
| 91 | RESOURCES.init(StackResources::<2>::new()), | 92 | RESOURCES.init(StackResources::new()), |
| 92 | seed, | 93 | seed, |
| 93 | )); | 94 | )); |
| 94 | 95 | ||
| 95 | unwrap!(spawner.spawn(net_task(stack))); | 96 | unwrap!(spawner.spawn(net_task(stack))); |
| 96 | 97 | ||
| 97 | loop { | 98 | loop { |
| 98 | //control.join_open(WIFI_NETWORK).await; | 99 | match control |
| 99 | match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { | 100 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 101 | .await | ||
| 102 | { | ||
| 100 | Ok(_) => break, | 103 | Ok(_) => break, |
| 101 | Err(err) => { | 104 | Err(err) => { |
| 102 | info!("join failed with status={}", err.status); | 105 | info!("join failed with status={}", err.status); |
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index 70b6f0949..b43be8905 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use core::str::from_utf8; | 8 | use core::str::from_utf8; |
| 9 | 9 | ||
| 10 | use cyw43::JoinOptions; | ||
| 10 | use cyw43_pio::PioSpi; | 11 | use cyw43_pio::PioSpi; |
| 11 | use defmt::*; | 12 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| @@ -34,7 +35,7 @@ const WIFI_NETWORK: &str = "ssid"; // change to your network SSID | |||
| 34 | const WIFI_PASSWORD: &str = "pwd"; // change to your network password | 35 | const WIFI_PASSWORD: &str = "pwd"; // change to your network password |
| 35 | 36 | ||
| 36 | #[embassy_executor::task] | 37 | #[embassy_executor::task] |
| 37 | async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { | 38 | async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { |
| 38 | runner.run().await | 39 | runner.run().await |
| 39 | } | 40 | } |
| 40 | 41 | ||
| @@ -67,7 +68,7 @@ async fn main(spawner: Spawner) { | |||
| 67 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); | 68 | static STATE: StaticCell<cyw43::State> = StaticCell::new(); |
| 68 | let state = STATE.init(cyw43::State::new()); | 69 | let state = STATE.init(cyw43::State::new()); |
| 69 | 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; |
| 70 | unwrap!(spawner.spawn(wifi_task(runner))); | 71 | unwrap!(spawner.spawn(cyw43_task(runner))); |
| 71 | 72 | ||
| 72 | control.init(clm).await; | 73 | control.init(clm).await; |
| 73 | control | 74 | control |
| @@ -91,15 +92,17 @@ async fn main(spawner: Spawner) { | |||
| 91 | let stack = &*STACK.init(Stack::new( | 92 | let stack = &*STACK.init(Stack::new( |
| 92 | net_device, | 93 | net_device, |
| 93 | config, | 94 | config, |
| 94 | RESOURCES.init(StackResources::<5>::new()), | 95 | RESOURCES.init(StackResources::new()), |
| 95 | seed, | 96 | seed, |
| 96 | )); | 97 | )); |
| 97 | 98 | ||
| 98 | unwrap!(spawner.spawn(net_task(stack))); | 99 | unwrap!(spawner.spawn(net_task(stack))); |
| 99 | 100 | ||
| 100 | loop { | 101 | loop { |
| 101 | //match control.join_open(WIFI_NETWORK).await { // for open networks | 102 | match control |
| 102 | match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { | 103 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 104 | .await | ||
| 105 | { | ||
| 103 | Ok(_) => break, | 106 | Ok(_) => break, |
| 104 | Err(err) => { | 107 | Err(err) => { |
| 105 | info!("join failed with status={}", err.status); | 108 | info!("join failed with status={}", err.status); |
diff --git a/examples/rp23/.cargo/config.toml b/examples/rp23/.cargo/config.toml new file mode 100644 index 000000000..9a92b1ce2 --- /dev/null +++ b/examples/rp23/.cargo/config.toml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | #runner = "probe-rs run --chip RP2040" | ||
| 3 | #runner = "elf2uf2-rs -d" | ||
| 4 | runner = "picotool load -u -v -x -t elf" | ||
| 5 | |||
| 6 | [build] | ||
| 7 | target = "thumbv8m.main-none-eabihf" | ||
| 8 | |||
| 9 | [env] | ||
| 10 | DEFMT_LOG = "debug" | ||
diff --git a/examples/rp23/Cargo.toml b/examples/rp23/Cargo.toml new file mode 100644 index 000000000..087f6fd69 --- /dev/null +++ b/examples/rp23/Cargo.toml | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-rp2350-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal", features = ["defmt"] } | ||
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | ||
| 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||
| 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||
| 13 | embassy-rp = { version = "0.2.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } | ||
| 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } | ||
| 15 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } | ||
| 16 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | ||
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 18 | embassy-usb-logger = { version = "0.2.0", path = "../../embassy-usb-logger" } | ||
| 19 | cyw43 = { version = "0.2.0", path = "../../cyw43", features = ["defmt", "firmware-logs", "bluetooth"] } | ||
| 20 | cyw43-pio = { version = "0.2.0", path = "../../cyw43-pio", features = ["defmt"] } | ||
| 21 | |||
| 22 | defmt = "0.3" | ||
| 23 | defmt-rtt = "0.4" | ||
| 24 | fixed = "1.23.1" | ||
| 25 | fixed-macro = "1.2" | ||
| 26 | |||
| 27 | # for web request example | ||
| 28 | reqwless = { version = "0.12.0", features = ["defmt",]} | ||
| 29 | serde = { version = "1.0.203", default-features = false, features = ["derive"] } | ||
| 30 | serde-json-core = "0.5.1" | ||
| 31 | |||
| 32 | # for assign resources example | ||
| 33 | assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" } | ||
| 34 | |||
| 35 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | ||
| 36 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | ||
| 37 | cortex-m-rt = "0.7.0" | ||
| 38 | critical-section = "1.1" | ||
| 39 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 40 | display-interface-spi = "0.4.1" | ||
| 41 | embedded-graphics = "0.7.1" | ||
| 42 | st7789 = "0.6.1" | ||
| 43 | display-interface = "0.4.1" | ||
| 44 | byte-slice-cast = { version = "1.2.0", default-features = false } | ||
| 45 | smart-leds = "0.3.0" | ||
| 46 | heapless = "0.8" | ||
| 47 | usbd-hid = "0.8.1" | ||
| 48 | |||
| 49 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 50 | embedded-hal-async = "1.0" | ||
| 51 | embedded-hal-bus = { version = "0.1", features = ["async"] } | ||
| 52 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | ||
| 53 | embedded-storage = { version = "0.3" } | ||
| 54 | static_cell = "2.1" | ||
| 55 | portable-atomic = { version = "1.5", features = ["critical-section"] } | ||
| 56 | log = "0.4" | ||
| 57 | pio-proc = "0.2" | ||
| 58 | pio = "0.2.1" | ||
| 59 | rand = { version = "0.8.5", default-features = false } | ||
| 60 | embedded-sdmmc = "0.7.0" | ||
| 61 | |||
| 62 | bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] } | ||
| 63 | trouble-host = { version = "0.1.0", features = ["defmt", "gatt"] } | ||
| 64 | |||
| 65 | [profile.release] | ||
| 66 | debug = 2 | ||
| 67 | |||
| 68 | [profile.dev] | ||
| 69 | lto = true | ||
| 70 | opt-level = "z" | ||
| 71 | |||
| 72 | [patch.crates-io] | ||
| 73 | trouble-host = { git = "https://github.com/embassy-rs/trouble.git", rev = "4b8c0f499b34e46ca23a56e2d1640ede371722cf" } | ||
| 74 | embassy-executor = { path = "../../embassy-executor" } | ||
| 75 | embassy-sync = { path = "../../embassy-sync" } | ||
| 76 | embassy-futures = { path = "../../embassy-futures" } | ||
| 77 | embassy-time = { path = "../../embassy-time" } | ||
| 78 | embassy-time-driver = { path = "../../embassy-time-driver" } | ||
| 79 | embassy-embedded-hal = { path = "../../embassy-embedded-hal" } | ||
diff --git a/examples/rp23/assets/ferris.raw b/examples/rp23/assets/ferris.raw new file mode 100644 index 000000000..9733889c5 --- /dev/null +++ b/examples/rp23/assets/ferris.raw | |||
| Binary files differ | |||
diff --git a/examples/rp23/build.rs b/examples/rp23/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/rp23/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/rp23/memory.x b/examples/rp23/memory.x new file mode 100644 index 000000000..777492062 --- /dev/null +++ b/examples/rp23/memory.x | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | MEMORY { | ||
| 2 | /* | ||
| 3 | * The RP2350 has either external or internal flash. | ||
| 4 | * | ||
| 5 | * 2 MiB is a safe default here, although a Pico 2 has 4 MiB. | ||
| 6 | */ | ||
| 7 | FLASH : ORIGIN = 0x10000000, LENGTH = 2048K | ||
| 8 | /* | ||
| 9 | * RAM consists of 8 banks, SRAM0-SRAM7, with a striped mapping. | ||
| 10 | * This is usually good for performance, as it distributes load on | ||
| 11 | * those banks evenly. | ||
| 12 | */ | ||
| 13 | RAM : ORIGIN = 0x20000000, LENGTH = 512K | ||
| 14 | /* | ||
| 15 | * RAM banks 8 and 9 use a direct mapping. They can be used to have | ||
| 16 | * memory areas dedicated for some specific job, improving predictability | ||
| 17 | * of access times. | ||
| 18 | * Example: Separate stacks for core0 and core1. | ||
| 19 | */ | ||
| 20 | SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K | ||
| 21 | SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K | ||
| 22 | } | ||
| 23 | |||
| 24 | SECTIONS { | ||
| 25 | /* ### Boot ROM info | ||
| 26 | * | ||
| 27 | * Goes after .vector_table, to keep it in the first 4K of flash | ||
| 28 | * where the Boot ROM (and picotool) can find it | ||
| 29 | */ | ||
| 30 | .start_block : ALIGN(4) | ||
| 31 | { | ||
| 32 | __start_block_addr = .; | ||
| 33 | KEEP(*(.start_block)); | ||
| 34 | } > FLASH | ||
| 35 | |||
| 36 | } INSERT AFTER .vector_table; | ||
| 37 | |||
| 38 | /* move .text to start /after/ the boot info */ | ||
| 39 | _stext = ADDR(.start_block) + SIZEOF(.start_block); | ||
| 40 | |||
| 41 | SECTIONS { | ||
| 42 | /* ### Picotool 'Binary Info' Entries | ||
| 43 | * | ||
| 44 | * Picotool looks through this block (as we have pointers to it in our | ||
| 45 | * header) to find interesting information. | ||
| 46 | */ | ||
| 47 | .bi_entries : ALIGN(4) | ||
| 48 | { | ||
| 49 | /* We put this in the header */ | ||
| 50 | __bi_entries_start = .; | ||
| 51 | /* Here are the entries */ | ||
| 52 | KEEP(*(.bi_entries)); | ||
| 53 | /* Keep this block a nice round size */ | ||
| 54 | . = ALIGN(4); | ||
| 55 | /* We put this in the header */ | ||
| 56 | __bi_entries_end = .; | ||
| 57 | } > FLASH | ||
| 58 | } INSERT AFTER .text; | ||
| 59 | |||
| 60 | SECTIONS { | ||
| 61 | /* ### Boot ROM extra info | ||
| 62 | * | ||
| 63 | * Goes after everything in our program, so it can contain a signature. | ||
| 64 | */ | ||
| 65 | .end_block : ALIGN(4) | ||
| 66 | { | ||
| 67 | __end_block_addr = .; | ||
| 68 | KEEP(*(.end_block)); | ||
| 69 | } > FLASH | ||
| 70 | |||
| 71 | } INSERT AFTER .uninit; | ||
| 72 | |||
| 73 | PROVIDE(start_to_end = __end_block_addr - __start_block_addr); | ||
| 74 | PROVIDE(end_to_start = __start_block_addr - __end_block_addr); | ||
diff --git a/examples/rp23/src/bin/adc.rs b/examples/rp23/src/bin/adc.rs new file mode 100644 index 000000000..d1f053d39 --- /dev/null +++ b/examples/rp23/src/bin/adc.rs | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | //! This example test the ADC (Analog to Digital Conversion) of the RS2040 pin 26, 27 and 28. | ||
| 2 | //! It also reads the temperature sensor in the chip. | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::gpio::Pull; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[embassy_executor::main] | ||
| 35 | async fn main(_spawner: Spawner) { | ||
| 36 | let p = embassy_rp::init(Default::default()); | ||
| 37 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | ||
| 38 | |||
| 39 | let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); | ||
| 40 | let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); | ||
| 41 | let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); | ||
| 42 | let mut ts = Channel::new_temp_sensor(p.ADC_TEMP_SENSOR); | ||
| 43 | |||
| 44 | loop { | ||
| 45 | let level = adc.read(&mut p26).await.unwrap(); | ||
| 46 | info!("Pin 26 ADC: {}", level); | ||
| 47 | let level = adc.read(&mut p27).await.unwrap(); | ||
| 48 | info!("Pin 27 ADC: {}", level); | ||
| 49 | let level = adc.read(&mut p28).await.unwrap(); | ||
| 50 | info!("Pin 28 ADC: {}", level); | ||
| 51 | let temp = adc.read(&mut ts).await.unwrap(); | ||
| 52 | info!("Temp: {} degrees", convert_to_celsius(temp)); | ||
| 53 | Timer::after_secs(1).await; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | fn convert_to_celsius(raw_temp: u16) -> f32 { | ||
| 58 | // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet | ||
| 59 | let temp = 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721; | ||
| 60 | let sign = if temp < 0.0 { -1.0 } else { 1.0 }; | ||
| 61 | let rounded_temp_x10: i16 = ((temp * 10.0) + 0.5 * sign) as i16; | ||
| 62 | (rounded_temp_x10 as f32) / 10.0 | ||
| 63 | } | ||
diff --git a/examples/rp23/src/bin/adc_dma.rs b/examples/rp23/src/bin/adc_dma.rs new file mode 100644 index 000000000..5046e5530 --- /dev/null +++ b/examples/rp23/src/bin/adc_dma.rs | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | //! This example shows how to use the RP2040 ADC with DMA, both single- and multichannel reads. | ||
| 2 | //! For multichannel, the samples are interleaved in the buffer: | ||
| 3 | //! `[ch1, ch2, ch3, ch4, ch1, ch2, ch3, ch4, ...]` | ||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::gpio::Pull; | ||
| 13 | use embassy_time::{Duration, Ticker}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[embassy_executor::main] | ||
| 35 | async fn main(_spawner: Spawner) { | ||
| 36 | let p = embassy_rp::init(Default::default()); | ||
| 37 | info!("Here we go!"); | ||
| 38 | |||
| 39 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | ||
| 40 | let mut dma = p.DMA_CH0; | ||
| 41 | let mut pin = Channel::new_pin(p.PIN_26, Pull::Up); | ||
| 42 | let mut pins = [ | ||
| 43 | Channel::new_pin(p.PIN_27, Pull::Down), | ||
| 44 | Channel::new_pin(p.PIN_28, Pull::None), | ||
| 45 | Channel::new_pin(p.PIN_29, Pull::Up), | ||
| 46 | Channel::new_temp_sensor(p.ADC_TEMP_SENSOR), | ||
| 47 | ]; | ||
| 48 | |||
| 49 | const BLOCK_SIZE: usize = 100; | ||
| 50 | const NUM_CHANNELS: usize = 4; | ||
| 51 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 52 | loop { | ||
| 53 | // Read 100 samples from a single channel | ||
| 54 | let mut buf = [0_u16; BLOCK_SIZE]; | ||
| 55 | let div = 479; // 100kHz sample rate (48Mhz / 100kHz - 1) | ||
| 56 | adc.read_many(&mut pin, &mut buf, div, &mut dma).await.unwrap(); | ||
| 57 | info!("single: {:?} ...etc", buf[..8]); | ||
| 58 | |||
| 59 | // Read 100 samples from 4 channels interleaved | ||
| 60 | let mut buf = [0_u16; { BLOCK_SIZE * NUM_CHANNELS }]; | ||
| 61 | let div = 119; // 100kHz sample rate (48Mhz / 100kHz * 4ch - 1) | ||
| 62 | adc.read_many_multichannel(&mut pins, &mut buf, div, &mut dma) | ||
| 63 | .await | ||
| 64 | .unwrap(); | ||
| 65 | info!("multi: {:?} ...etc", buf[..NUM_CHANNELS * 2]); | ||
| 66 | |||
| 67 | ticker.next().await; | ||
| 68 | } | ||
| 69 | } | ||
diff --git a/examples/rp23/src/bin/assign_resources.rs b/examples/rp23/src/bin/assign_resources.rs new file mode 100644 index 000000000..2f9783917 --- /dev/null +++ b/examples/rp23/src/bin/assign_resources.rs | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | //! This example demonstrates how to assign resources to multiple tasks by splitting up the peripherals. | ||
| 2 | //! It is not about sharing the same resources between tasks, see sharing.rs for that or head to https://embassy.dev/book/#_sharing_peripherals_between_tasks) | ||
| 3 | //! Of course splitting up resources and sharing resources can be combined, yet this example is only about splitting up resources. | ||
| 4 | //! | ||
| 5 | //! There are basically two ways we demonstrate here: | ||
| 6 | //! 1) Assigning resources to a task by passing parts of the peripherals | ||
| 7 | //! 2) Assigning resources to a task by passing a struct with the split up peripherals, using the assign-resources macro | ||
| 8 | //! | ||
| 9 | //! using four LEDs on Pins 10, 11, 20 and 21 | ||
| 10 | |||
| 11 | #![no_std] | ||
| 12 | #![no_main] | ||
| 13 | |||
| 14 | use assign_resources::assign_resources; | ||
| 15 | use defmt::*; | ||
| 16 | use embassy_executor::Spawner; | ||
| 17 | use embassy_rp::block::ImageDef; | ||
| 18 | use embassy_rp::gpio::{Level, Output}; | ||
| 19 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; | ||
| 20 | use embassy_time::Timer; | ||
| 21 | use {defmt_rtt as _, panic_probe as _}; | ||
| 22 | |||
| 23 | #[link_section = ".start_block"] | ||
| 24 | #[used] | ||
| 25 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 26 | |||
| 27 | // Program metadata for `picotool info` | ||
| 28 | #[link_section = ".bi_entries"] | ||
| 29 | #[used] | ||
| 30 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 31 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 32 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 33 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 34 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 35 | ]; | ||
| 36 | |||
| 37 | #[embassy_executor::main] | ||
| 38 | async fn main(spawner: Spawner) { | ||
| 39 | // initialize the peripherals | ||
| 40 | let p = embassy_rp::init(Default::default()); | ||
| 41 | |||
| 42 | // 1) Assigning a resource to a task by passing parts of the peripherals. | ||
| 43 | spawner | ||
| 44 | .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) | ||
| 45 | .unwrap(); | ||
| 46 | |||
| 47 | // 2) Using the assign-resources macro to assign resources to a task. | ||
| 48 | // we perform the split, see further below for the definition of the resources struct | ||
| 49 | let r = split_resources!(p); | ||
| 50 | // and then we can use them | ||
| 51 | spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); | ||
| 52 | } | ||
| 53 | |||
| 54 | // 1) Assigning a resource to a task by passing parts of the peripherals. | ||
| 55 | #[embassy_executor::task] | ||
| 56 | async fn double_blinky_manually_assigned(_spawner: Spawner, pin_20: PIN_20, pin_21: PIN_21) { | ||
| 57 | let mut led_20 = Output::new(pin_20, Level::Low); | ||
| 58 | let mut led_21 = Output::new(pin_21, Level::High); | ||
| 59 | |||
| 60 | loop { | ||
| 61 | info!("toggling leds"); | ||
| 62 | led_20.toggle(); | ||
| 63 | led_21.toggle(); | ||
| 64 | Timer::after_secs(1).await; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | // 2) Using the assign-resources macro to assign resources to a task. | ||
| 69 | // first we define the resources we want to assign to the task using the assign_resources! macro | ||
| 70 | // basically this will split up the peripherals struct into smaller structs, that we define here | ||
| 71 | // naming is up to you, make sure your future self understands what you did here | ||
| 72 | assign_resources! { | ||
| 73 | leds: Leds{ | ||
| 74 | led_10: PIN_10, | ||
| 75 | led_11: PIN_11, | ||
| 76 | } | ||
| 77 | // add more resources to more structs if needed, for example defining one struct for each task | ||
| 78 | } | ||
| 79 | // this could be done in another file and imported here, but for the sake of simplicity we do it here | ||
| 80 | // see https://github.com/adamgreig/assign-resources for more information | ||
| 81 | |||
| 82 | // 2) Using the split resources in a task | ||
| 83 | #[embassy_executor::task] | ||
| 84 | async fn double_blinky_macro_assigned(_spawner: Spawner, r: Leds) { | ||
| 85 | let mut led_10 = Output::new(r.led_10, Level::Low); | ||
| 86 | let mut led_11 = Output::new(r.led_11, Level::High); | ||
| 87 | |||
| 88 | loop { | ||
| 89 | info!("toggling leds"); | ||
| 90 | led_10.toggle(); | ||
| 91 | led_11.toggle(); | ||
| 92 | Timer::after_secs(1).await; | ||
| 93 | } | ||
| 94 | } | ||
diff --git a/examples/rp23/src/bin/blinky.rs b/examples/rp23/src/bin/blinky.rs new file mode 100644 index 000000000..9e45679c8 --- /dev/null +++ b/examples/rp23/src/bin/blinky.rs | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | //! This example test the RP Pico on board LED. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. See wifi_blinky.rs. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use gpio::{Level, Output}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(_spawner: Spawner) { | ||
| 32 | let p = embassy_rp::init(Default::default()); | ||
| 33 | let mut led = Output::new(p.PIN_2, Level::Low); | ||
| 34 | |||
| 35 | loop { | ||
| 36 | info!("led on!"); | ||
| 37 | led.set_high(); | ||
| 38 | Timer::after_millis(250).await; | ||
| 39 | |||
| 40 | info!("led off!"); | ||
| 41 | led.set_low(); | ||
| 42 | Timer::after_millis(250).await; | ||
| 43 | } | ||
| 44 | } | ||
diff --git a/examples/rp23/src/bin/blinky_two_channels.rs b/examples/rp23/src/bin/blinky_two_channels.rs new file mode 100644 index 000000000..87fc58bbc --- /dev/null +++ b/examples/rp23/src/bin/blinky_two_channels.rs | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | /// This example demonstrates how to access a given pin from more than one embassy task | ||
| 4 | /// The on-board LED is toggled by two tasks with slightly different periods, leading to the | ||
| 5 | /// apparent duty cycle of the LED increasing, then decreasing, linearly. The phenomenon is similar | ||
| 6 | /// to interference and the 'beats' you can hear if you play two frequencies close to one another | ||
| 7 | /// [Link explaining it](https://www.physicsclassroom.com/class/sound/Lesson-3/Interference-and-Beats) | ||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio; | ||
| 12 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||
| 13 | use embassy_sync::channel::{Channel, Sender}; | ||
| 14 | use embassy_time::{Duration, Ticker}; | ||
| 15 | use gpio::{AnyPin, Level, Output}; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | #[link_section = ".start_block"] | ||
| 19 | #[used] | ||
| 20 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 21 | |||
| 22 | // Program metadata for `picotool info` | ||
| 23 | #[link_section = ".bi_entries"] | ||
| 24 | #[used] | ||
| 25 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 26 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 27 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 28 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 29 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 30 | ]; | ||
| 31 | |||
| 32 | enum LedState { | ||
| 33 | Toggle, | ||
| 34 | } | ||
| 35 | static CHANNEL: Channel<ThreadModeRawMutex, LedState, 64> = Channel::new(); | ||
| 36 | |||
| 37 | #[embassy_executor::main] | ||
| 38 | async fn main(spawner: Spawner) { | ||
| 39 | let p = embassy_rp::init(Default::default()); | ||
| 40 | let mut led = Output::new(AnyPin::from(p.PIN_25), Level::High); | ||
| 41 | |||
| 42 | let dt = 100 * 1_000_000; | ||
| 43 | let k = 1.003; | ||
| 44 | |||
| 45 | unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); | ||
| 46 | unwrap!(spawner.spawn(toggle_led( | ||
| 47 | CHANNEL.sender(), | ||
| 48 | Duration::from_nanos((dt as f64 * k) as u64) | ||
| 49 | ))); | ||
| 50 | |||
| 51 | loop { | ||
| 52 | match CHANNEL.receive().await { | ||
| 53 | LedState::Toggle => led.toggle(), | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | #[embassy_executor::task(pool_size = 2)] | ||
| 59 | async fn toggle_led(control: Sender<'static, ThreadModeRawMutex, LedState, 64>, delay: Duration) { | ||
| 60 | let mut ticker = Ticker::every(delay); | ||
| 61 | loop { | ||
| 62 | control.send(LedState::Toggle).await; | ||
| 63 | ticker.next().await; | ||
| 64 | } | ||
| 65 | } | ||
diff --git a/examples/rp23/src/bin/blinky_two_tasks.rs b/examples/rp23/src/bin/blinky_two_tasks.rs new file mode 100644 index 000000000..40236c53b --- /dev/null +++ b/examples/rp23/src/bin/blinky_two_tasks.rs | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | /// This example demonstrates how to access a given pin from more than one embassy task | ||
| 4 | /// The on-board LED is toggled by two tasks with slightly different periods, leading to the | ||
| 5 | /// apparent duty cycle of the LED increasing, then decreasing, linearly. The phenomenon is similar | ||
| 6 | /// to interference and the 'beats' you can hear if you play two frequencies close to one another | ||
| 7 | /// [Link explaining it](https://www.physicsclassroom.com/class/sound/Lesson-3/Interference-and-Beats) | ||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio; | ||
| 12 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||
| 13 | use embassy_sync::mutex::Mutex; | ||
| 14 | use embassy_time::{Duration, Ticker}; | ||
| 15 | use gpio::{AnyPin, Level, Output}; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | #[link_section = ".start_block"] | ||
| 19 | #[used] | ||
| 20 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 21 | |||
| 22 | // Program metadata for `picotool info` | ||
| 23 | #[link_section = ".bi_entries"] | ||
| 24 | #[used] | ||
| 25 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 26 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 27 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 28 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 29 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 30 | ]; | ||
| 31 | |||
| 32 | type LedType = Mutex<ThreadModeRawMutex, Option<Output<'static>>>; | ||
| 33 | static LED: LedType = Mutex::new(None); | ||
| 34 | |||
| 35 | #[embassy_executor::main] | ||
| 36 | async fn main(spawner: Spawner) { | ||
| 37 | let p = embassy_rp::init(Default::default()); | ||
| 38 | // set the content of the global LED reference to the real LED pin | ||
| 39 | let led = Output::new(AnyPin::from(p.PIN_25), Level::High); | ||
| 40 | // inner scope is so that once the mutex is written to, the MutexGuard is dropped, thus the | ||
| 41 | // Mutex is released | ||
| 42 | { | ||
| 43 | *(LED.lock().await) = Some(led); | ||
| 44 | } | ||
| 45 | let dt = 100 * 1_000_000; | ||
| 46 | let k = 1.003; | ||
| 47 | |||
| 48 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); | ||
| 49 | unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); | ||
| 50 | } | ||
| 51 | |||
| 52 | #[embassy_executor::task(pool_size = 2)] | ||
| 53 | async fn toggle_led(led: &'static LedType, delay: Duration) { | ||
| 54 | let mut ticker = Ticker::every(delay); | ||
| 55 | loop { | ||
| 56 | { | ||
| 57 | let mut led_unlocked = led.lock().await; | ||
| 58 | if let Some(pin_ref) = led_unlocked.as_mut() { | ||
| 59 | pin_ref.toggle(); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | ticker.next().await; | ||
| 63 | } | ||
| 64 | } | ||
diff --git a/examples/rp23/src/bin/button.rs b/examples/rp23/src/bin/button.rs new file mode 100644 index 000000000..fb067a370 --- /dev/null +++ b/examples/rp23/src/bin/button.rs | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | //! This example uses the RP Pico on board LED to test input pin 28. This is not the button on the board. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. Use wifi_blinky.rs and add input pin. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::block::ImageDef; | ||
| 10 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[link_section = ".start_block"] | ||
| 14 | #[used] | ||
| 15 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 16 | |||
| 17 | // Program metadata for `picotool info` | ||
| 18 | #[link_section = ".bi_entries"] | ||
| 19 | #[used] | ||
| 20 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 21 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 22 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 23 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 24 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 25 | ]; | ||
| 26 | |||
| 27 | #[embassy_executor::main] | ||
| 28 | async fn main(_spawner: Spawner) { | ||
| 29 | let p = embassy_rp::init(Default::default()); | ||
| 30 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 31 | |||
| 32 | // Use PIN_28, Pin34 on J0 for RP Pico, as a input. | ||
| 33 | // You need to add your own button. | ||
| 34 | let button = Input::new(p.PIN_28, Pull::Up); | ||
| 35 | |||
| 36 | loop { | ||
| 37 | if button.is_high() { | ||
| 38 | led.set_high(); | ||
| 39 | } else { | ||
| 40 | led.set_low(); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | } | ||
diff --git a/examples/rp23/src/bin/debounce.rs b/examples/rp23/src/bin/debounce.rs new file mode 100644 index 000000000..e672521ec --- /dev/null +++ b/examples/rp23/src/bin/debounce.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | //! This example shows the ease of debouncing a button with async rust. | ||
| 2 | //! Hook up a button or switch between pin 9 and ground. | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::info; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::block::ImageDef; | ||
| 10 | use embassy_rp::gpio::{Input, Level, Pull}; | ||
| 11 | use embassy_time::{with_deadline, Duration, Instant, Timer}; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | pub struct Debouncer<'a> { | ||
| 29 | input: Input<'a>, | ||
| 30 | debounce: Duration, | ||
| 31 | } | ||
| 32 | |||
| 33 | impl<'a> Debouncer<'a> { | ||
| 34 | pub fn new(input: Input<'a>, debounce: Duration) -> Self { | ||
| 35 | Self { input, debounce } | ||
| 36 | } | ||
| 37 | |||
| 38 | pub async fn debounce(&mut self) -> Level { | ||
| 39 | loop { | ||
| 40 | let l1 = self.input.get_level(); | ||
| 41 | |||
| 42 | self.input.wait_for_any_edge().await; | ||
| 43 | |||
| 44 | Timer::after(self.debounce).await; | ||
| 45 | |||
| 46 | let l2 = self.input.get_level(); | ||
| 47 | if l1 != l2 { | ||
| 48 | break l2; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | #[embassy_executor::main] | ||
| 55 | async fn main(_spawner: Spawner) { | ||
| 56 | let p = embassy_rp::init(Default::default()); | ||
| 57 | let mut btn = Debouncer::new(Input::new(p.PIN_9, Pull::Up), Duration::from_millis(20)); | ||
| 58 | |||
| 59 | info!("Debounce Demo"); | ||
| 60 | |||
| 61 | loop { | ||
| 62 | // button pressed | ||
| 63 | btn.debounce().await; | ||
| 64 | let start = Instant::now(); | ||
| 65 | info!("Button Press"); | ||
| 66 | |||
| 67 | match with_deadline(start + Duration::from_secs(1), btn.debounce()).await { | ||
| 68 | // Button Released < 1s | ||
| 69 | Ok(_) => { | ||
| 70 | info!("Button pressed for: {}ms", start.elapsed().as_millis()); | ||
| 71 | continue; | ||
| 72 | } | ||
| 73 | // button held for > 1s | ||
| 74 | Err(_) => { | ||
| 75 | info!("Button Held"); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | match with_deadline(start + Duration::from_secs(5), btn.debounce()).await { | ||
| 80 | // Button released <5s | ||
| 81 | Ok(_) => { | ||
| 82 | info!("Button pressed for: {}ms", start.elapsed().as_millis()); | ||
| 83 | continue; | ||
| 84 | } | ||
| 85 | // button held for > >5s | ||
| 86 | Err(_) => { | ||
| 87 | info!("Button Long Held"); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | // wait for button release before handling another press | ||
| 92 | btn.debounce().await; | ||
| 93 | info!("Button pressed for: {}ms", start.elapsed().as_millis()); | ||
| 94 | } | ||
| 95 | } | ||
diff --git a/examples/rp23/src/bin/flash.rs b/examples/rp23/src/bin/flash.rs new file mode 100644 index 000000000..84011e394 --- /dev/null +++ b/examples/rp23/src/bin/flash.rs | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | //! This example test the flash connected to the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE}; | ||
| 10 | use embassy_rp::peripherals::FLASH; | ||
| 11 | use embassy_time::Timer; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Flash"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | const ADDR_OFFSET: u32 = 0x100000; | ||
| 29 | const FLASH_SIZE: usize = 2 * 1024 * 1024; | ||
| 30 | |||
| 31 | #[embassy_executor::main] | ||
| 32 | async fn main(_spawner: Spawner) { | ||
| 33 | let p = embassy_rp::init(Default::default()); | ||
| 34 | info!("Hello World!"); | ||
| 35 | |||
| 36 | // add some delay to give an attached debug probe time to parse the | ||
| 37 | // defmt RTT header. Reading that header might touch flash memory, which | ||
| 38 | // interferes with flash write operations. | ||
| 39 | // https://github.com/knurling-rs/defmt/pull/683 | ||
| 40 | Timer::after_millis(10).await; | ||
| 41 | |||
| 42 | let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0); | ||
| 43 | |||
| 44 | erase_write_sector(&mut flash, 0x00); | ||
| 45 | |||
| 46 | multiwrite_bytes(&mut flash, ERASE_SIZE as u32); | ||
| 47 | |||
| 48 | background_read(&mut flash, (ERASE_SIZE * 2) as u32).await; | ||
| 49 | |||
| 50 | info!("Flash Works!"); | ||
| 51 | } | ||
| 52 | |||
| 53 | fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { | ||
| 54 | info!(">>>> [multiwrite_bytes]"); | ||
| 55 | let mut read_buf = [0u8; ERASE_SIZE]; | ||
| 56 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut read_buf)); | ||
| 57 | |||
| 58 | info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); | ||
| 59 | info!("Contents start with {=[u8]}", read_buf[0..4]); | ||
| 60 | |||
| 61 | defmt::unwrap!(flash.blocking_erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); | ||
| 62 | |||
| 63 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut read_buf)); | ||
| 64 | info!("Contents after erase starts with {=[u8]}", read_buf[0..4]); | ||
| 65 | if read_buf.iter().any(|x| *x != 0xFF) { | ||
| 66 | defmt::panic!("unexpected"); | ||
| 67 | } | ||
| 68 | |||
| 69 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset, &[0x01])); | ||
| 70 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset + 1, &[0x02])); | ||
| 71 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset + 2, &[0x03])); | ||
| 72 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset + 3, &[0x04])); | ||
| 73 | |||
| 74 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut read_buf)); | ||
| 75 | info!("Contents after write starts with {=[u8]}", read_buf[0..4]); | ||
| 76 | if read_buf[0..4] != [0x01, 0x02, 0x03, 0x04] { | ||
| 77 | defmt::panic!("unexpected"); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { | ||
| 82 | info!(">>>> [erase_write_sector]"); | ||
| 83 | let mut buf = [0u8; ERASE_SIZE]; | ||
| 84 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut buf)); | ||
| 85 | |||
| 86 | info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); | ||
| 87 | info!("Contents start with {=[u8]}", buf[0..4]); | ||
| 88 | |||
| 89 | defmt::unwrap!(flash.blocking_erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); | ||
| 90 | |||
| 91 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut buf)); | ||
| 92 | info!("Contents after erase starts with {=[u8]}", buf[0..4]); | ||
| 93 | if buf.iter().any(|x| *x != 0xFF) { | ||
| 94 | defmt::panic!("unexpected"); | ||
| 95 | } | ||
| 96 | |||
| 97 | for b in buf.iter_mut() { | ||
| 98 | *b = 0xDA; | ||
| 99 | } | ||
| 100 | |||
| 101 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset, &buf)); | ||
| 102 | |||
| 103 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut buf)); | ||
| 104 | info!("Contents after write starts with {=[u8]}", buf[0..4]); | ||
| 105 | if buf.iter().any(|x| *x != 0xDA) { | ||
| 106 | defmt::panic!("unexpected"); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | async fn background_read(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { | ||
| 111 | info!(">>>> [background_read]"); | ||
| 112 | |||
| 113 | let mut buf = [0u32; 8]; | ||
| 114 | defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; | ||
| 115 | |||
| 116 | info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); | ||
| 117 | info!("Contents start with {=u32:x}", buf[0]); | ||
| 118 | |||
| 119 | defmt::unwrap!(flash.blocking_erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); | ||
| 120 | |||
| 121 | defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; | ||
| 122 | info!("Contents after erase starts with {=u32:x}", buf[0]); | ||
| 123 | if buf.iter().any(|x| *x != 0xFFFFFFFF) { | ||
| 124 | defmt::panic!("unexpected"); | ||
| 125 | } | ||
| 126 | |||
| 127 | for b in buf.iter_mut() { | ||
| 128 | *b = 0xDABA1234; | ||
| 129 | } | ||
| 130 | |||
| 131 | defmt::unwrap!(flash.blocking_write(ADDR_OFFSET + offset, unsafe { | ||
| 132 | core::slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4) | ||
| 133 | })); | ||
| 134 | |||
| 135 | defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; | ||
| 136 | info!("Contents after write starts with {=u32:x}", buf[0]); | ||
| 137 | if buf.iter().any(|x| *x != 0xDABA1234) { | ||
| 138 | defmt::panic!("unexpected"); | ||
| 139 | } | ||
| 140 | } | ||
diff --git a/examples/rp23/src/bin/gpio_async.rs b/examples/rp23/src/bin/gpio_async.rs new file mode 100644 index 000000000..ff12367bf --- /dev/null +++ b/examples/rp23/src/bin/gpio_async.rs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | //! This example shows how async gpio can be used with a RP2040. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use gpio::{Input, Level, Output, Pull}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | /// It requires an external signal to be manually triggered on PIN 16. For | ||
| 31 | /// example, this could be accomplished using an external power source with a | ||
| 32 | /// button so that it is possible to toggle the signal from low to high. | ||
| 33 | /// | ||
| 34 | /// This example will begin with turning on the LED on the board and wait for a | ||
| 35 | /// high signal on PIN 16. Once the high event/signal occurs the program will | ||
| 36 | /// continue and turn off the LED, and then wait for 2 seconds before completing | ||
| 37 | /// the loop and starting over again. | ||
| 38 | #[embassy_executor::main] | ||
| 39 | async fn main(_spawner: Spawner) { | ||
| 40 | let p = embassy_rp::init(Default::default()); | ||
| 41 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 42 | let mut async_input = Input::new(p.PIN_16, Pull::None); | ||
| 43 | |||
| 44 | loop { | ||
| 45 | info!("wait_for_high. Turn on LED"); | ||
| 46 | led.set_high(); | ||
| 47 | |||
| 48 | async_input.wait_for_high().await; | ||
| 49 | |||
| 50 | info!("done wait_for_high. Turn off LED"); | ||
| 51 | led.set_low(); | ||
| 52 | |||
| 53 | Timer::after_secs(2).await; | ||
| 54 | } | ||
| 55 | } | ||
diff --git a/examples/rp23/src/bin/gpout.rs b/examples/rp23/src/bin/gpout.rs new file mode 100644 index 000000000..d2ee55197 --- /dev/null +++ b/examples/rp23/src/bin/gpout.rs | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | //! This example shows how GPOUT (General purpose clock outputs) can toggle a output pin. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::clocks; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | #[link_section = ".start_block"] | ||
| 16 | #[used] | ||
| 17 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 18 | |||
| 19 | // Program metadata for `picotool info` | ||
| 20 | #[link_section = ".bi_entries"] | ||
| 21 | #[used] | ||
| 22 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 23 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 24 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 25 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 26 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 27 | ]; | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | let p = embassy_rp::init(Default::default()); | ||
| 32 | |||
| 33 | let gpout3 = clocks::Gpout::new(p.PIN_25); | ||
| 34 | gpout3.set_div(1000, 0); | ||
| 35 | gpout3.enable(); | ||
| 36 | |||
| 37 | loop { | ||
| 38 | gpout3.set_src(clocks::GpoutSrc::Sys); | ||
| 39 | info!( | ||
| 40 | "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", | ||
| 41 | gpout3.get_freq() | ||
| 42 | ); | ||
| 43 | Timer::after_secs(2).await; | ||
| 44 | |||
| 45 | gpout3.set_src(clocks::GpoutSrc::Ref); | ||
| 46 | info!( | ||
| 47 | "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", | ||
| 48 | gpout3.get_freq() | ||
| 49 | ); | ||
| 50 | Timer::after_secs(2).await; | ||
| 51 | } | ||
| 52 | } | ||
diff --git a/examples/rp23/src/bin/i2c_async.rs b/examples/rp23/src/bin/i2c_async.rs new file mode 100644 index 000000000..c8d918b56 --- /dev/null +++ b/examples/rp23/src/bin/i2c_async.rs | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | //! This example shows how to communicate asynchronous using i2c with external chips. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. | ||
| 4 | //! (https://www.microchip.com/en-us/product/mcp23017) | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_rp::bind_interrupts; | ||
| 12 | use embassy_rp::block::ImageDef; | ||
| 13 | use embassy_rp::i2c::{self, Config, InterruptHandler}; | ||
| 14 | use embassy_rp::peripherals::I2C1; | ||
| 15 | use embassy_time::Timer; | ||
| 16 | use embedded_hal_async::i2c::I2c; | ||
| 17 | use {defmt_rtt as _, panic_probe as _}; | ||
| 18 | |||
| 19 | #[link_section = ".start_block"] | ||
| 20 | #[used] | ||
| 21 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 22 | |||
| 23 | // Program metadata for `picotool info` | ||
| 24 | #[link_section = ".bi_entries"] | ||
| 25 | #[used] | ||
| 26 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 27 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 28 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 29 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 30 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 31 | ]; | ||
| 32 | |||
| 33 | bind_interrupts!(struct Irqs { | ||
| 34 | I2C1_IRQ => InterruptHandler<I2C1>; | ||
| 35 | }); | ||
| 36 | |||
| 37 | #[allow(dead_code)] | ||
| 38 | mod mcp23017 { | ||
| 39 | pub const ADDR: u8 = 0x20; // default addr | ||
| 40 | |||
| 41 | macro_rules! mcpregs { | ||
| 42 | ($($name:ident : $val:expr),* $(,)?) => { | ||
| 43 | $( | ||
| 44 | pub const $name: u8 = $val; | ||
| 45 | )* | ||
| 46 | |||
| 47 | pub fn regname(reg: u8) -> &'static str { | ||
| 48 | match reg { | ||
| 49 | $( | ||
| 50 | $val => stringify!($name), | ||
| 51 | )* | ||
| 52 | _ => panic!("bad reg"), | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | // These are correct for IOCON.BANK=0 | ||
| 59 | mcpregs! { | ||
| 60 | IODIRA: 0x00, | ||
| 61 | IPOLA: 0x02, | ||
| 62 | GPINTENA: 0x04, | ||
| 63 | DEFVALA: 0x06, | ||
| 64 | INTCONA: 0x08, | ||
| 65 | IOCONA: 0x0A, | ||
| 66 | GPPUA: 0x0C, | ||
| 67 | INTFA: 0x0E, | ||
| 68 | INTCAPA: 0x10, | ||
| 69 | GPIOA: 0x12, | ||
| 70 | OLATA: 0x14, | ||
| 71 | IODIRB: 0x01, | ||
| 72 | IPOLB: 0x03, | ||
| 73 | GPINTENB: 0x05, | ||
| 74 | DEFVALB: 0x07, | ||
| 75 | INTCONB: 0x09, | ||
| 76 | IOCONB: 0x0B, | ||
| 77 | GPPUB: 0x0D, | ||
| 78 | INTFB: 0x0F, | ||
| 79 | INTCAPB: 0x11, | ||
| 80 | GPIOB: 0x13, | ||
| 81 | OLATB: 0x15, | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | #[embassy_executor::main] | ||
| 86 | async fn main(_spawner: Spawner) { | ||
| 87 | let p = embassy_rp::init(Default::default()); | ||
| 88 | |||
| 89 | let sda = p.PIN_14; | ||
| 90 | let scl = p.PIN_15; | ||
| 91 | |||
| 92 | info!("set up i2c "); | ||
| 93 | let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, Config::default()); | ||
| 94 | |||
| 95 | use mcp23017::*; | ||
| 96 | |||
| 97 | info!("init mcp23017 config for IxpandO"); | ||
| 98 | // init - a outputs, b inputs | ||
| 99 | i2c.write(ADDR, &[IODIRA, 0x00]).await.unwrap(); | ||
| 100 | i2c.write(ADDR, &[IODIRB, 0xff]).await.unwrap(); | ||
| 101 | i2c.write(ADDR, &[GPPUB, 0xff]).await.unwrap(); // pullups | ||
| 102 | |||
| 103 | let mut val = 1; | ||
| 104 | loop { | ||
| 105 | let mut portb = [0]; | ||
| 106 | |||
| 107 | i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).await.unwrap(); | ||
| 108 | info!("portb = {:02x}", portb[0]); | ||
| 109 | i2c.write(mcp23017::ADDR, &[GPIOA, val | portb[0]]).await.unwrap(); | ||
| 110 | val = val.rotate_left(1); | ||
| 111 | |||
| 112 | // get a register dump | ||
| 113 | info!("getting register dump"); | ||
| 114 | let mut regs = [0; 22]; | ||
| 115 | i2c.write_read(ADDR, &[0], &mut regs).await.unwrap(); | ||
| 116 | // always get the regdump but only display it if portb'0 is set | ||
| 117 | if portb[0] & 1 != 0 { | ||
| 118 | for (idx, reg) in regs.into_iter().enumerate() { | ||
| 119 | info!("{} => {:02x}", regname(idx as u8), reg); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | Timer::after_millis(100).await; | ||
| 124 | } | ||
| 125 | } | ||
diff --git a/examples/rp23/src/bin/i2c_async_embassy.rs b/examples/rp23/src/bin/i2c_async_embassy.rs new file mode 100644 index 000000000..cce0abcde --- /dev/null +++ b/examples/rp23/src/bin/i2c_async_embassy.rs | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | //! This example shows how to communicate asynchronous using i2c with external chip. | ||
| 2 | //! | ||
| 3 | //! It's using embassy's functions directly instead of traits from embedded_hal_async::i2c::I2c. | ||
| 4 | //! While most of i2c devices are addressed using 7 bits, an extension allows 10 bits too. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::i2c::InterruptHandler; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | // Our anonymous hypotetical temperature sensor could be: | ||
| 29 | // a 12-bit sensor, with 100ms startup time, range of -40*C - 125*C, and precision 0.25*C | ||
| 30 | // It requires no configuration or calibration, works with all i2c bus speeds, | ||
| 31 | // never stretches clock or does anything complicated. Replies with one u16. | ||
| 32 | // It requires only one write to take it out of suspend mode, and stays on. | ||
| 33 | // Often result would be just on 12 bits, but here we'll simplify it to 16. | ||
| 34 | |||
| 35 | enum UncomplicatedSensorId { | ||
| 36 | A(UncomplicatedSensorU8), | ||
| 37 | B(UncomplicatedSensorU16), | ||
| 38 | } | ||
| 39 | enum UncomplicatedSensorU8 { | ||
| 40 | First = 0x48, | ||
| 41 | } | ||
| 42 | enum UncomplicatedSensorU16 { | ||
| 43 | Other = 0x0049, | ||
| 44 | } | ||
| 45 | |||
| 46 | impl Into<u16> for UncomplicatedSensorU16 { | ||
| 47 | fn into(self) -> u16 { | ||
| 48 | self as u16 | ||
| 49 | } | ||
| 50 | } | ||
| 51 | impl Into<u16> for UncomplicatedSensorU8 { | ||
| 52 | fn into(self) -> u16 { | ||
| 53 | 0x48 | ||
| 54 | } | ||
| 55 | } | ||
| 56 | impl From<UncomplicatedSensorId> for u16 { | ||
| 57 | fn from(t: UncomplicatedSensorId) -> Self { | ||
| 58 | match t { | ||
| 59 | UncomplicatedSensorId::A(x) => x.into(), | ||
| 60 | UncomplicatedSensorId::B(x) => x.into(), | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | embassy_rp::bind_interrupts!(struct Irqs { | ||
| 66 | I2C1_IRQ => InterruptHandler<embassy_rp::peripherals::I2C1>; | ||
| 67 | }); | ||
| 68 | |||
| 69 | #[embassy_executor::main] | ||
| 70 | async fn main(_task_spawner: embassy_executor::Spawner) { | ||
| 71 | let p = embassy_rp::init(Default::default()); | ||
| 72 | let sda = p.PIN_14; | ||
| 73 | let scl = p.PIN_15; | ||
| 74 | let config = embassy_rp::i2c::Config::default(); | ||
| 75 | let mut bus = embassy_rp::i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, config); | ||
| 76 | |||
| 77 | const WAKEYWAKEY: u16 = 0xBABE; | ||
| 78 | let mut result: [u8; 2] = [0, 0]; | ||
| 79 | // wait for sensors to initialize | ||
| 80 | embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await; | ||
| 81 | |||
| 82 | let _res_1 = bus | ||
| 83 | .write_async(UncomplicatedSensorU8::First, WAKEYWAKEY.to_be_bytes()) | ||
| 84 | .await; | ||
| 85 | let _res_2 = bus | ||
| 86 | .write_async(UncomplicatedSensorU16::Other, WAKEYWAKEY.to_be_bytes()) | ||
| 87 | .await; | ||
| 88 | |||
| 89 | loop { | ||
| 90 | let s1 = UncomplicatedSensorId::A(UncomplicatedSensorU8::First); | ||
| 91 | let s2 = UncomplicatedSensorId::B(UncomplicatedSensorU16::Other); | ||
| 92 | let sensors = [s1, s2]; | ||
| 93 | for sensor in sensors { | ||
| 94 | if bus.read_async(sensor, &mut result).await.is_ok() { | ||
| 95 | info!("Result {}", u16::from_be_bytes(result.into())); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | embassy_time::Timer::after(embassy_time::Duration::from_millis(200)).await; | ||
| 99 | } | ||
| 100 | } | ||
diff --git a/examples/rp23/src/bin/i2c_blocking.rs b/examples/rp23/src/bin/i2c_blocking.rs new file mode 100644 index 000000000..85c33bf0d --- /dev/null +++ b/examples/rp23/src/bin/i2c_blocking.rs | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | //! This example shows how to communicate using i2c with external chips. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. | ||
| 4 | //! (https://www.microchip.com/en-us/product/mcp23017) | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::i2c::{self, Config}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use embedded_hal_1::i2c::I2c; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | #[link_section = ".start_block"] | ||
| 18 | #[used] | ||
| 19 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 20 | |||
| 21 | // Program metadata for `picotool info` | ||
| 22 | #[link_section = ".bi_entries"] | ||
| 23 | #[used] | ||
| 24 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 25 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 26 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 27 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 28 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 29 | ]; | ||
| 30 | |||
| 31 | #[allow(dead_code)] | ||
| 32 | mod mcp23017 { | ||
| 33 | pub const ADDR: u8 = 0x20; // default addr | ||
| 34 | |||
| 35 | pub const IODIRA: u8 = 0x00; | ||
| 36 | pub const IPOLA: u8 = 0x02; | ||
| 37 | pub const GPINTENA: u8 = 0x04; | ||
| 38 | pub const DEFVALA: u8 = 0x06; | ||
| 39 | pub const INTCONA: u8 = 0x08; | ||
| 40 | pub const IOCONA: u8 = 0x0A; | ||
| 41 | pub const GPPUA: u8 = 0x0C; | ||
| 42 | pub const INTFA: u8 = 0x0E; | ||
| 43 | pub const INTCAPA: u8 = 0x10; | ||
| 44 | pub const GPIOA: u8 = 0x12; | ||
| 45 | pub const OLATA: u8 = 0x14; | ||
| 46 | pub const IODIRB: u8 = 0x01; | ||
| 47 | pub const IPOLB: u8 = 0x03; | ||
| 48 | pub const GPINTENB: u8 = 0x05; | ||
| 49 | pub const DEFVALB: u8 = 0x07; | ||
| 50 | pub const INTCONB: u8 = 0x09; | ||
| 51 | pub const IOCONB: u8 = 0x0B; | ||
| 52 | pub const GPPUB: u8 = 0x0D; | ||
| 53 | pub const INTFB: u8 = 0x0F; | ||
| 54 | pub const INTCAPB: u8 = 0x11; | ||
| 55 | pub const GPIOB: u8 = 0x13; | ||
| 56 | pub const OLATB: u8 = 0x15; | ||
| 57 | } | ||
| 58 | |||
| 59 | #[embassy_executor::main] | ||
| 60 | async fn main(_spawner: Spawner) { | ||
| 61 | let p = embassy_rp::init(Default::default()); | ||
| 62 | |||
| 63 | let sda = p.PIN_14; | ||
| 64 | let scl = p.PIN_15; | ||
| 65 | |||
| 66 | info!("set up i2c "); | ||
| 67 | let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); | ||
| 68 | |||
| 69 | use mcp23017::*; | ||
| 70 | |||
| 71 | info!("init mcp23017 config for IxpandO"); | ||
| 72 | // init - a outputs, b inputs | ||
| 73 | i2c.write(ADDR, &[IODIRA, 0x00]).unwrap(); | ||
| 74 | i2c.write(ADDR, &[IODIRB, 0xff]).unwrap(); | ||
| 75 | i2c.write(ADDR, &[GPPUB, 0xff]).unwrap(); // pullups | ||
| 76 | |||
| 77 | let mut val = 0xaa; | ||
| 78 | loop { | ||
| 79 | let mut portb = [0]; | ||
| 80 | |||
| 81 | i2c.write(mcp23017::ADDR, &[GPIOA, val]).unwrap(); | ||
| 82 | i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).unwrap(); | ||
| 83 | |||
| 84 | info!("portb = {:02x}", portb[0]); | ||
| 85 | val = !val; | ||
| 86 | |||
| 87 | Timer::after_secs(1).await; | ||
| 88 | } | ||
| 89 | } | ||
diff --git a/examples/rp23/src/bin/i2c_slave.rs b/examples/rp23/src/bin/i2c_slave.rs new file mode 100644 index 000000000..fb5f3cda1 --- /dev/null +++ b/examples/rp23/src/bin/i2c_slave.rs | |||
| @@ -0,0 +1,132 @@ | |||
| 1 | //! This example shows how to use the 2040 as an i2c slave. | ||
| 2 | #![no_std] | ||
| 3 | #![no_main] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_rp::block::ImageDef; | ||
| 8 | use embassy_rp::peripherals::{I2C0, I2C1}; | ||
| 9 | use embassy_rp::{bind_interrupts, i2c, i2c_slave}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use embedded_hal_async::i2c::I2c; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | bind_interrupts!(struct Irqs { | ||
| 29 | I2C0_IRQ => i2c::InterruptHandler<I2C0>; | ||
| 30 | I2C1_IRQ => i2c::InterruptHandler<I2C1>; | ||
| 31 | }); | ||
| 32 | |||
| 33 | const DEV_ADDR: u8 = 0x42; | ||
| 34 | |||
| 35 | #[embassy_executor::task] | ||
| 36 | async fn device_task(mut dev: i2c_slave::I2cSlave<'static, I2C1>) -> ! { | ||
| 37 | info!("Device start"); | ||
| 38 | |||
| 39 | let mut state = 0; | ||
| 40 | |||
| 41 | loop { | ||
| 42 | let mut buf = [0u8; 128]; | ||
| 43 | match dev.listen(&mut buf).await { | ||
| 44 | Ok(i2c_slave::Command::GeneralCall(len)) => info!("Device received general call write: {}", buf[..len]), | ||
| 45 | Ok(i2c_slave::Command::Read) => loop { | ||
| 46 | match dev.respond_to_read(&[state]).await { | ||
| 47 | Ok(x) => match x { | ||
| 48 | i2c_slave::ReadStatus::Done => break, | ||
| 49 | i2c_slave::ReadStatus::NeedMoreBytes => (), | ||
| 50 | i2c_slave::ReadStatus::LeftoverBytes(x) => { | ||
| 51 | info!("tried to write {} extra bytes", x); | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | }, | ||
| 55 | Err(e) => error!("error while responding {}", e), | ||
| 56 | } | ||
| 57 | }, | ||
| 58 | Ok(i2c_slave::Command::Write(len)) => info!("Device received write: {}", buf[..len]), | ||
| 59 | Ok(i2c_slave::Command::WriteRead(len)) => { | ||
| 60 | info!("device received write read: {:x}", buf[..len]); | ||
| 61 | match buf[0] { | ||
| 62 | // Set the state | ||
| 63 | 0xC2 => { | ||
| 64 | state = buf[1]; | ||
| 65 | match dev.respond_and_fill(&[state], 0x00).await { | ||
| 66 | Ok(read_status) => info!("response read status {}", read_status), | ||
| 67 | Err(e) => error!("error while responding {}", e), | ||
| 68 | } | ||
| 69 | } | ||
| 70 | // Reset State | ||
| 71 | 0xC8 => { | ||
| 72 | state = 0; | ||
| 73 | match dev.respond_and_fill(&[state], 0x00).await { | ||
| 74 | Ok(read_status) => info!("response read status {}", read_status), | ||
| 75 | Err(e) => error!("error while responding {}", e), | ||
| 76 | } | ||
| 77 | } | ||
| 78 | x => error!("Invalid Write Read {:x}", x), | ||
| 79 | } | ||
| 80 | } | ||
| 81 | Err(e) => error!("{}", e), | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | #[embassy_executor::task] | ||
| 87 | async fn controller_task(mut con: i2c::I2c<'static, I2C0, i2c::Async>) { | ||
| 88 | info!("Controller start"); | ||
| 89 | |||
| 90 | loop { | ||
| 91 | let mut resp_buff = [0u8; 2]; | ||
| 92 | for i in 0..10 { | ||
| 93 | match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await { | ||
| 94 | Ok(_) => info!("write_read response: {}", resp_buff), | ||
| 95 | Err(e) => error!("Error writing {}", e), | ||
| 96 | } | ||
| 97 | |||
| 98 | Timer::after_millis(100).await; | ||
| 99 | } | ||
| 100 | match con.read(DEV_ADDR, &mut resp_buff).await { | ||
| 101 | Ok(_) => info!("read response: {}", resp_buff), | ||
| 102 | Err(e) => error!("Error writing {}", e), | ||
| 103 | } | ||
| 104 | match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await { | ||
| 105 | Ok(_) => info!("write_read response: {}", resp_buff), | ||
| 106 | Err(e) => error!("Error writing {}", e), | ||
| 107 | } | ||
| 108 | Timer::after_millis(100).await; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | #[embassy_executor::main] | ||
| 113 | async fn main(spawner: Spawner) { | ||
| 114 | let p = embassy_rp::init(Default::default()); | ||
| 115 | info!("Hello World!"); | ||
| 116 | |||
| 117 | let d_sda = p.PIN_3; | ||
| 118 | let d_scl = p.PIN_2; | ||
| 119 | let mut config = i2c_slave::Config::default(); | ||
| 120 | config.addr = DEV_ADDR as u16; | ||
| 121 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); | ||
| 122 | |||
| 123 | unwrap!(spawner.spawn(device_task(device))); | ||
| 124 | |||
| 125 | let c_sda = p.PIN_1; | ||
| 126 | let c_scl = p.PIN_0; | ||
| 127 | let mut config = i2c::Config::default(); | ||
| 128 | config.frequency = 1_000_000; | ||
| 129 | let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); | ||
| 130 | |||
| 131 | unwrap!(spawner.spawn(controller_task(controller))); | ||
| 132 | } | ||
diff --git a/examples/rp23/src/bin/interrupt.rs b/examples/rp23/src/bin/interrupt.rs new file mode 100644 index 000000000..ee3d9bfe7 --- /dev/null +++ b/examples/rp23/src/bin/interrupt.rs | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | //! This example shows how you can use raw interrupt handlers alongside embassy. | ||
| 2 | //! The example also showcases some of the options available for sharing resources/data. | ||
| 3 | //! | ||
| 4 | //! In the example, an ADC reading is triggered every time the PWM wraps around. | ||
| 5 | //! The sample data is sent down a channel, to be processed inside a low priority task. | ||
| 6 | //! The processed data is then used to adjust the PWM duty cycle, once every second. | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use core::cell::{Cell, RefCell}; | ||
| 12 | |||
| 13 | use defmt::*; | ||
| 14 | use embassy_executor::Spawner; | ||
| 15 | use embassy_rp::adc::{self, Adc, Blocking}; | ||
| 16 | use embassy_rp::block::ImageDef; | ||
| 17 | use embassy_rp::gpio::Pull; | ||
| 18 | use embassy_rp::interrupt; | ||
| 19 | use embassy_rp::pwm::{Config, Pwm}; | ||
| 20 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 21 | use embassy_sync::blocking_mutex::Mutex; | ||
| 22 | use embassy_sync::channel::Channel; | ||
| 23 | use embassy_time::{Duration, Ticker}; | ||
| 24 | use portable_atomic::{AtomicU32, Ordering}; | ||
| 25 | use static_cell::StaticCell; | ||
| 26 | use {defmt_rtt as _, panic_probe as _}; | ||
| 27 | |||
| 28 | #[link_section = ".start_block"] | ||
| 29 | #[used] | ||
| 30 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 31 | |||
| 32 | // Program metadata for `picotool info` | ||
| 33 | #[link_section = ".bi_entries"] | ||
| 34 | #[used] | ||
| 35 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 36 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 37 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 38 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 39 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 40 | ]; | ||
| 41 | |||
| 42 | static COUNTER: AtomicU32 = AtomicU32::new(0); | ||
| 43 | static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm>>> = Mutex::new(RefCell::new(None)); | ||
| 44 | static ADC: Mutex<CriticalSectionRawMutex, RefCell<Option<(Adc<Blocking>, adc::Channel)>>> = | ||
| 45 | Mutex::new(RefCell::new(None)); | ||
| 46 | static ADC_VALUES: Channel<CriticalSectionRawMutex, u16, 2048> = Channel::new(); | ||
| 47 | |||
| 48 | #[embassy_executor::main] | ||
| 49 | async fn main(spawner: Spawner) { | ||
| 50 | embassy_rp::pac::SIO.spinlock(31).write_value(1); | ||
| 51 | let p = embassy_rp::init(Default::default()); | ||
| 52 | |||
| 53 | let adc = Adc::new_blocking(p.ADC, Default::default()); | ||
| 54 | let p26 = adc::Channel::new_pin(p.PIN_26, Pull::None); | ||
| 55 | ADC.lock(|a| a.borrow_mut().replace((adc, p26))); | ||
| 56 | |||
| 57 | let pwm = Pwm::new_output_b(p.PWM_SLICE4, p.PIN_25, Default::default()); | ||
| 58 | PWM.lock(|p| p.borrow_mut().replace(pwm)); | ||
| 59 | |||
| 60 | // Enable the interrupt for pwm slice 4 | ||
| 61 | embassy_rp::pac::PWM.irq0_inte().modify(|w| w.set_ch4(true)); | ||
| 62 | unsafe { | ||
| 63 | cortex_m::peripheral::NVIC::unmask(interrupt::PWM_IRQ_WRAP_0); | ||
| 64 | } | ||
| 65 | |||
| 66 | // Tasks require their resources to have 'static lifetime | ||
| 67 | // No Mutex needed when sharing within the same executor/prio level | ||
| 68 | static AVG: StaticCell<Cell<u32>> = StaticCell::new(); | ||
| 69 | let avg = AVG.init(Default::default()); | ||
| 70 | spawner.must_spawn(processing(avg)); | ||
| 71 | |||
| 72 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 73 | loop { | ||
| 74 | ticker.next().await; | ||
| 75 | let freq = COUNTER.swap(0, Ordering::Relaxed); | ||
| 76 | info!("pwm freq: {:?} Hz", freq); | ||
| 77 | info!("adc average: {:?}", avg.get()); | ||
| 78 | |||
| 79 | // Update the pwm duty cycle, based on the averaged adc reading | ||
| 80 | let mut config = Config::default(); | ||
| 81 | config.compare_b = ((avg.get() as f32 / 4095.0) * config.top as f32) as _; | ||
| 82 | PWM.lock(|p| p.borrow_mut().as_mut().unwrap().set_config(&config)); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | #[embassy_executor::task] | ||
| 87 | async fn processing(avg: &'static Cell<u32>) { | ||
| 88 | let mut buffer: heapless::HistoryBuffer<u16, 100> = Default::default(); | ||
| 89 | loop { | ||
| 90 | let val = ADC_VALUES.receive().await; | ||
| 91 | buffer.write(val); | ||
| 92 | let sum: u32 = buffer.iter().map(|x| *x as u32).sum(); | ||
| 93 | avg.set(sum / buffer.len() as u32); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | #[interrupt] | ||
| 98 | fn PWM_IRQ_WRAP_0() { | ||
| 99 | critical_section::with(|cs| { | ||
| 100 | let mut adc = ADC.borrow(cs).borrow_mut(); | ||
| 101 | let (adc, p26) = adc.as_mut().unwrap(); | ||
| 102 | let val = adc.blocking_read(p26).unwrap(); | ||
| 103 | ADC_VALUES.try_send(val).ok(); | ||
| 104 | |||
| 105 | // Clear the interrupt, so we don't immediately re-enter this irq handler | ||
| 106 | PWM.borrow(cs).borrow_mut().as_mut().unwrap().clear_wrapped(); | ||
| 107 | }); | ||
| 108 | COUNTER.fetch_add(1, Ordering::Relaxed); | ||
| 109 | } | ||
diff --git a/examples/rp23/src/bin/multicore.rs b/examples/rp23/src/bin/multicore.rs new file mode 100644 index 000000000..9ab43d7a5 --- /dev/null +++ b/examples/rp23/src/bin/multicore.rs | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | //! This example shows how to send messages between the two cores in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Executor; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio::{Level, Output}; | ||
| 12 | use embassy_rp::multicore::{spawn_core1, Stack}; | ||
| 13 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 14 | use embassy_sync::channel::Channel; | ||
| 15 | use embassy_time::Timer; | ||
| 16 | use static_cell::StaticCell; | ||
| 17 | use {defmt_rtt as _, panic_probe as _}; | ||
| 18 | |||
| 19 | #[link_section = ".start_block"] | ||
| 20 | #[used] | ||
| 21 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 22 | |||
| 23 | // Program metadata for `picotool info` | ||
| 24 | #[link_section = ".bi_entries"] | ||
| 25 | #[used] | ||
| 26 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 27 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 28 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 29 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 30 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 31 | ]; | ||
| 32 | |||
| 33 | static mut CORE1_STACK: Stack<4096> = Stack::new(); | ||
| 34 | static EXECUTOR0: StaticCell<Executor> = StaticCell::new(); | ||
| 35 | static EXECUTOR1: StaticCell<Executor> = StaticCell::new(); | ||
| 36 | static CHANNEL: Channel<CriticalSectionRawMutex, LedState, 1> = Channel::new(); | ||
| 37 | |||
| 38 | enum LedState { | ||
| 39 | On, | ||
| 40 | Off, | ||
| 41 | } | ||
| 42 | |||
| 43 | #[cortex_m_rt::entry] | ||
| 44 | fn main() -> ! { | ||
| 45 | let p = embassy_rp::init(Default::default()); | ||
| 46 | let led = Output::new(p.PIN_25, Level::Low); | ||
| 47 | |||
| 48 | spawn_core1( | ||
| 49 | p.CORE1, | ||
| 50 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, | ||
| 51 | move || { | ||
| 52 | let executor1 = EXECUTOR1.init(Executor::new()); | ||
| 53 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); | ||
| 54 | }, | ||
| 55 | ); | ||
| 56 | |||
| 57 | let executor0 = EXECUTOR0.init(Executor::new()); | ||
| 58 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); | ||
| 59 | } | ||
| 60 | |||
| 61 | #[embassy_executor::task] | ||
| 62 | async fn core0_task() { | ||
| 63 | info!("Hello from core 0"); | ||
| 64 | loop { | ||
| 65 | CHANNEL.send(LedState::On).await; | ||
| 66 | Timer::after_millis(100).await; | ||
| 67 | CHANNEL.send(LedState::Off).await; | ||
| 68 | Timer::after_millis(400).await; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | #[embassy_executor::task] | ||
| 73 | async fn core1_task(mut led: Output<'static>) { | ||
| 74 | info!("Hello from core 1"); | ||
| 75 | loop { | ||
| 76 | match CHANNEL.receive().await { | ||
| 77 | LedState::On => led.set_high(), | ||
| 78 | LedState::Off => led.set_low(), | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
diff --git a/examples/rp23/src/bin/multiprio.rs b/examples/rp23/src/bin/multiprio.rs new file mode 100644 index 000000000..27cd3656e --- /dev/null +++ b/examples/rp23/src/bin/multiprio.rs | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | //! This example showcases how to create multiple Executor instances to run tasks at | ||
| 2 | //! different priority levels. | ||
| 3 | //! | ||
| 4 | //! Low priority executor runs in thread mode (not interrupt), and uses `sev` for signaling | ||
| 5 | //! there's work in the queue, and `wfe` for waiting for work. | ||
| 6 | //! | ||
| 7 | //! Medium and high priority executors run in two interrupts with different priorities. | ||
| 8 | //! Signaling work is done by pending the interrupt. No "waiting" needs to be done explicitly, since | ||
| 9 | //! when there's work the interrupt will trigger and run the executor. | ||
| 10 | //! | ||
| 11 | //! Sample output below. Note that high priority ticks can interrupt everything else, and | ||
| 12 | //! medium priority computations can interrupt low priority computations, making them to appear | ||
| 13 | //! to take significantly longer time. | ||
| 14 | //! | ||
| 15 | //! ```not_rust | ||
| 16 | //! [med] Starting long computation | ||
| 17 | //! [med] done in 992 ms | ||
| 18 | //! [high] tick! | ||
| 19 | //! [low] Starting long computation | ||
| 20 | //! [med] Starting long computation | ||
| 21 | //! [high] tick! | ||
| 22 | //! [high] tick! | ||
| 23 | //! [med] done in 993 ms | ||
| 24 | //! [med] Starting long computation | ||
| 25 | //! [high] tick! | ||
| 26 | //! [high] tick! | ||
| 27 | //! [med] done in 993 ms | ||
| 28 | //! [low] done in 3972 ms | ||
| 29 | //! [med] Starting long computation | ||
| 30 | //! [high] tick! | ||
| 31 | //! [high] tick! | ||
| 32 | //! [med] done in 993 ms | ||
| 33 | //! ``` | ||
| 34 | //! | ||
| 35 | //! For comparison, try changing the code so all 3 tasks get spawned on the low priority executor. | ||
| 36 | //! You will get an output like the following. Note that no computation is ever interrupted. | ||
| 37 | //! | ||
| 38 | //! ```not_rust | ||
| 39 | //! [high] tick! | ||
| 40 | //! [med] Starting long computation | ||
| 41 | //! [med] done in 496 ms | ||
| 42 | //! [low] Starting long computation | ||
| 43 | //! [low] done in 992 ms | ||
| 44 | //! [med] Starting long computation | ||
| 45 | //! [med] done in 496 ms | ||
| 46 | //! [high] tick! | ||
| 47 | //! [low] Starting long computation | ||
| 48 | //! [low] done in 992 ms | ||
| 49 | //! [high] tick! | ||
| 50 | //! [med] Starting long computation | ||
| 51 | //! [med] done in 496 ms | ||
| 52 | //! [high] tick! | ||
| 53 | //! ``` | ||
| 54 | //! | ||
| 55 | |||
| 56 | #![no_std] | ||
| 57 | #![no_main] | ||
| 58 | |||
| 59 | use cortex_m_rt::entry; | ||
| 60 | use defmt::{info, unwrap}; | ||
| 61 | use embassy_executor::{Executor, InterruptExecutor}; | ||
| 62 | use embassy_rp::block::ImageDef; | ||
| 63 | use embassy_rp::interrupt; | ||
| 64 | use embassy_rp::interrupt::{InterruptExt, Priority}; | ||
| 65 | use embassy_time::{Instant, Timer, TICK_HZ}; | ||
| 66 | use static_cell::StaticCell; | ||
| 67 | use {defmt_rtt as _, panic_probe as _}; | ||
| 68 | |||
| 69 | #[link_section = ".start_block"] | ||
| 70 | #[used] | ||
| 71 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 72 | |||
| 73 | // Program metadata for `picotool info` | ||
| 74 | #[link_section = ".bi_entries"] | ||
| 75 | #[used] | ||
| 76 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 77 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 78 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 79 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 80 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 81 | ]; | ||
| 82 | |||
| 83 | #[embassy_executor::task] | ||
| 84 | async fn run_high() { | ||
| 85 | loop { | ||
| 86 | info!(" [high] tick!"); | ||
| 87 | Timer::after_ticks(673740).await; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | #[embassy_executor::task] | ||
| 92 | async fn run_med() { | ||
| 93 | loop { | ||
| 94 | let start = Instant::now(); | ||
| 95 | info!(" [med] Starting long computation"); | ||
| 96 | |||
| 97 | // Spin-wait to simulate a long CPU computation | ||
| 98 | embassy_time::block_for(embassy_time::Duration::from_secs(1)); // ~1 second | ||
| 99 | |||
| 100 | let end = Instant::now(); | ||
| 101 | let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; | ||
| 102 | info!(" [med] done in {} ms", ms); | ||
| 103 | |||
| 104 | Timer::after_ticks(53421).await; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | #[embassy_executor::task] | ||
| 109 | async fn run_low() { | ||
| 110 | loop { | ||
| 111 | let start = Instant::now(); | ||
| 112 | info!("[low] Starting long computation"); | ||
| 113 | |||
| 114 | // Spin-wait to simulate a long CPU computation | ||
| 115 | embassy_time::block_for(embassy_time::Duration::from_secs(2)); // ~2 seconds | ||
| 116 | |||
| 117 | let end = Instant::now(); | ||
| 118 | let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; | ||
| 119 | info!("[low] done in {} ms", ms); | ||
| 120 | |||
| 121 | Timer::after_ticks(82983).await; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new(); | ||
| 126 | static EXECUTOR_MED: InterruptExecutor = InterruptExecutor::new(); | ||
| 127 | static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | ||
| 128 | |||
| 129 | #[interrupt] | ||
| 130 | unsafe fn SWI_IRQ_1() { | ||
| 131 | EXECUTOR_HIGH.on_interrupt() | ||
| 132 | } | ||
| 133 | |||
| 134 | #[interrupt] | ||
| 135 | unsafe fn SWI_IRQ_0() { | ||
| 136 | EXECUTOR_MED.on_interrupt() | ||
| 137 | } | ||
| 138 | |||
| 139 | #[entry] | ||
| 140 | fn main() -> ! { | ||
| 141 | info!("Hello World!"); | ||
| 142 | |||
| 143 | let _p = embassy_rp::init(Default::default()); | ||
| 144 | |||
| 145 | // High-priority executor: SWI_IRQ_1, priority level 2 | ||
| 146 | interrupt::SWI_IRQ_1.set_priority(Priority::P2); | ||
| 147 | let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); | ||
| 148 | unwrap!(spawner.spawn(run_high())); | ||
| 149 | |||
| 150 | // Medium-priority executor: SWI_IRQ_0, priority level 3 | ||
| 151 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | ||
| 152 | let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); | ||
| 153 | unwrap!(spawner.spawn(run_med())); | ||
| 154 | |||
| 155 | // Low priority executor: runs in thread mode, using WFE/SEV | ||
| 156 | let executor = EXECUTOR_LOW.init(Executor::new()); | ||
| 157 | executor.run(|spawner| { | ||
| 158 | unwrap!(spawner.spawn(run_low())); | ||
| 159 | }); | ||
| 160 | } | ||
diff --git a/examples/rp23/src/bin/otp.rs b/examples/rp23/src/bin/otp.rs new file mode 100644 index 000000000..106e514ca --- /dev/null +++ b/examples/rp23/src/bin/otp.rs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | //! This example shows reading the OTP constants on the RP235x. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::otp; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[link_section = ".start_block"] | ||
| 14 | #[used] | ||
| 15 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 16 | |||
| 17 | // Program metadata for `picotool info` | ||
| 18 | #[link_section = ".bi_entries"] | ||
| 19 | #[used] | ||
| 20 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 21 | embassy_rp::binary_info::rp_program_name!(c"OTP Read Example"), | ||
| 22 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 23 | embassy_rp::binary_info::rp_program_description!(c"OTP Read Example"), | ||
| 24 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 25 | ]; | ||
| 26 | |||
| 27 | #[embassy_executor::main] | ||
| 28 | async fn main(_spawner: Spawner) { | ||
| 29 | let _ = embassy_rp::init(Default::default()); | ||
| 30 | // | ||
| 31 | // add some delay to give an attached debug probe time to parse the | ||
| 32 | // defmt RTT header. Reading that header might touch flash memory, which | ||
| 33 | // interferes with flash write operations. | ||
| 34 | // https://github.com/knurling-rs/defmt/pull/683 | ||
| 35 | Timer::after_millis(10).await; | ||
| 36 | |||
| 37 | let chip_id = unwrap!(otp::get_chipid()); | ||
| 38 | info!("Unique id:{:X}", chip_id); | ||
| 39 | |||
| 40 | let private_rand = unwrap!(otp::get_private_random_number()); | ||
| 41 | info!("Private Rand:{:X}", private_rand); | ||
| 42 | |||
| 43 | loop { | ||
| 44 | Timer::after_secs(1).await; | ||
| 45 | } | ||
| 46 | } | ||
diff --git a/examples/rp23/src/bin/pio_async.rs b/examples/rp23/src/bin/pio_async.rs new file mode 100644 index 000000000..231afc80e --- /dev/null +++ b/examples/rp23/src/bin/pio_async.rs | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | use defmt::info; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_rp::bind_interrupts; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::peripherals::PIO0; | ||
| 10 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | ||
| 11 | use fixed::traits::ToFixed; | ||
| 12 | use fixed_macro::types::U56F8; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | #[link_section = ".start_block"] | ||
| 16 | #[used] | ||
| 17 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 18 | |||
| 19 | // Program metadata for `picotool info` | ||
| 20 | #[link_section = ".bi_entries"] | ||
| 21 | #[used] | ||
| 22 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 23 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 24 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 25 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 26 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 27 | ]; | ||
| 28 | |||
| 29 | bind_interrupts!(struct Irqs { | ||
| 30 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 31 | }); | ||
| 32 | |||
| 33 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { | ||
| 34 | // Setup sm0 | ||
| 35 | |||
| 36 | // Send data serially to pin | ||
| 37 | let prg = pio_proc::pio_asm!( | ||
| 38 | ".origin 16", | ||
| 39 | "set pindirs, 1", | ||
| 40 | ".wrap_target", | ||
| 41 | "out pins,1 [19]", | ||
| 42 | ".wrap", | ||
| 43 | ); | ||
| 44 | |||
| 45 | let mut cfg = Config::default(); | ||
| 46 | cfg.use_program(&pio.load_program(&prg.program), &[]); | ||
| 47 | let out_pin = pio.make_pio_pin(pin); | ||
| 48 | cfg.set_out_pins(&[&out_pin]); | ||
| 49 | cfg.set_set_pins(&[&out_pin]); | ||
| 50 | cfg.clock_divider = (U56F8!(125_000_000) / 20 / 200).to_fixed(); | ||
| 51 | cfg.shift_out.auto_fill = true; | ||
| 52 | sm.set_config(&cfg); | ||
| 53 | } | ||
| 54 | |||
| 55 | #[embassy_executor::task] | ||
| 56 | async fn pio_task_sm0(mut sm: StateMachine<'static, PIO0, 0>) { | ||
| 57 | sm.set_enable(true); | ||
| 58 | |||
| 59 | let mut v = 0x0f0caffa; | ||
| 60 | loop { | ||
| 61 | sm.tx().wait_push(v).await; | ||
| 62 | v ^= 0xffff; | ||
| 63 | info!("Pushed {:032b} to FIFO", v); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 1>) { | ||
| 68 | // Setupm sm1 | ||
| 69 | |||
| 70 | // Read 0b10101 repeatedly until ISR is full | ||
| 71 | let prg = pio_proc::pio_asm!( | ||
| 72 | // | ||
| 73 | ".origin 8", | ||
| 74 | "set x, 0x15", | ||
| 75 | ".wrap_target", | ||
| 76 | "in x, 5 [31]", | ||
| 77 | ".wrap", | ||
| 78 | ); | ||
| 79 | |||
| 80 | let mut cfg = Config::default(); | ||
| 81 | cfg.use_program(&pio.load_program(&prg.program), &[]); | ||
| 82 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); | ||
| 83 | cfg.shift_in.auto_fill = true; | ||
| 84 | cfg.shift_in.direction = ShiftDirection::Right; | ||
| 85 | sm.set_config(&cfg); | ||
| 86 | } | ||
| 87 | |||
| 88 | #[embassy_executor::task] | ||
| 89 | async fn pio_task_sm1(mut sm: StateMachine<'static, PIO0, 1>) { | ||
| 90 | sm.set_enable(true); | ||
| 91 | loop { | ||
| 92 | let rx = sm.rx().wait_pull().await; | ||
| 93 | info!("Pulled {:032b} from FIFO", rx); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 2>) { | ||
| 98 | // Setup sm2 | ||
| 99 | |||
| 100 | // Repeatedly trigger IRQ 3 | ||
| 101 | let prg = pio_proc::pio_asm!( | ||
| 102 | ".origin 0", | ||
| 103 | ".wrap_target", | ||
| 104 | "set x,10", | ||
| 105 | "delay:", | ||
| 106 | "jmp x-- delay [15]", | ||
| 107 | "irq 3 [15]", | ||
| 108 | ".wrap", | ||
| 109 | ); | ||
| 110 | let mut cfg = Config::default(); | ||
| 111 | cfg.use_program(&pio.load_program(&prg.program), &[]); | ||
| 112 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); | ||
| 113 | sm.set_config(&cfg); | ||
| 114 | } | ||
| 115 | |||
| 116 | #[embassy_executor::task] | ||
| 117 | async fn pio_task_sm2(mut irq: Irq<'static, PIO0, 3>, mut sm: StateMachine<'static, PIO0, 2>) { | ||
| 118 | sm.set_enable(true); | ||
| 119 | loop { | ||
| 120 | irq.wait().await; | ||
| 121 | info!("IRQ trigged"); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | #[embassy_executor::main] | ||
| 126 | async fn main(spawner: Spawner) { | ||
| 127 | let p = embassy_rp::init(Default::default()); | ||
| 128 | let pio = p.PIO0; | ||
| 129 | |||
| 130 | let Pio { | ||
| 131 | mut common, | ||
| 132 | irq3, | ||
| 133 | mut sm0, | ||
| 134 | mut sm1, | ||
| 135 | mut sm2, | ||
| 136 | .. | ||
| 137 | } = Pio::new(pio, Irqs); | ||
| 138 | |||
| 139 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); | ||
| 140 | setup_pio_task_sm1(&mut common, &mut sm1); | ||
| 141 | setup_pio_task_sm2(&mut common, &mut sm2); | ||
| 142 | spawner.spawn(pio_task_sm0(sm0)).unwrap(); | ||
| 143 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); | ||
| 144 | spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); | ||
| 145 | } | ||
diff --git a/examples/rp23/src/bin/pio_dma.rs b/examples/rp23/src/bin/pio_dma.rs new file mode 100644 index 000000000..60fbcb83a --- /dev/null +++ b/examples/rp23/src/bin/pio_dma.rs | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | use defmt::info; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_futures::join::join; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::peripherals::PIO0; | ||
| 10 | use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; | ||
| 11 | use embassy_rp::{bind_interrupts, Peripheral}; | ||
| 12 | use fixed::traits::ToFixed; | ||
| 13 | use fixed_macro::types::U56F8; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | fn swap_nibbles(v: u32) -> u32 { | ||
| 35 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; | ||
| 36 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; | ||
| 37 | (v & 0x0000_ffff) << 16 | (v & 0xffff_0000) >> 16 | ||
| 38 | } | ||
| 39 | |||
| 40 | #[embassy_executor::main] | ||
| 41 | async fn main(_spawner: Spawner) { | ||
| 42 | let p = embassy_rp::init(Default::default()); | ||
| 43 | let pio = p.PIO0; | ||
| 44 | let Pio { | ||
| 45 | mut common, | ||
| 46 | sm0: mut sm, | ||
| 47 | .. | ||
| 48 | } = Pio::new(pio, Irqs); | ||
| 49 | |||
| 50 | let prg = pio_proc::pio_asm!( | ||
| 51 | ".origin 0", | ||
| 52 | "set pindirs,1", | ||
| 53 | ".wrap_target", | ||
| 54 | "set y,7", | ||
| 55 | "loop:", | ||
| 56 | "out x,4", | ||
| 57 | "in x,4", | ||
| 58 | "jmp y--, loop", | ||
| 59 | ".wrap", | ||
| 60 | ); | ||
| 61 | |||
| 62 | let mut cfg = Config::default(); | ||
| 63 | cfg.use_program(&common.load_program(&prg.program), &[]); | ||
| 64 | cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); | ||
| 65 | cfg.shift_in = ShiftConfig { | ||
| 66 | auto_fill: true, | ||
| 67 | threshold: 32, | ||
| 68 | direction: ShiftDirection::Left, | ||
| 69 | }; | ||
| 70 | cfg.shift_out = ShiftConfig { | ||
| 71 | auto_fill: true, | ||
| 72 | threshold: 32, | ||
| 73 | direction: ShiftDirection::Right, | ||
| 74 | }; | ||
| 75 | |||
| 76 | sm.set_config(&cfg); | ||
| 77 | sm.set_enable(true); | ||
| 78 | |||
| 79 | let mut dma_out_ref = p.DMA_CH0.into_ref(); | ||
| 80 | let mut dma_in_ref = p.DMA_CH1.into_ref(); | ||
| 81 | let mut dout = [0x12345678u32; 29]; | ||
| 82 | for i in 1..dout.len() { | ||
| 83 | dout[i] = (dout[i - 1] & 0x0fff_ffff) * 13 + 7; | ||
| 84 | } | ||
| 85 | let mut din = [0u32; 29]; | ||
| 86 | loop { | ||
| 87 | let (rx, tx) = sm.rx_tx(); | ||
| 88 | join( | ||
| 89 | tx.dma_push(dma_out_ref.reborrow(), &dout), | ||
| 90 | rx.dma_pull(dma_in_ref.reborrow(), &mut din), | ||
| 91 | ) | ||
| 92 | .await; | ||
| 93 | for i in 0..din.len() { | ||
| 94 | assert_eq!(din[i], swap_nibbles(dout[i])); | ||
| 95 | } | ||
| 96 | info!("Swapped {} words", dout.len()); | ||
| 97 | } | ||
| 98 | } | ||
diff --git a/examples/rp23/src/bin/pio_hd44780.rs b/examples/rp23/src/bin/pio_hd44780.rs new file mode 100644 index 000000000..92aa858f9 --- /dev/null +++ b/examples/rp23/src/bin/pio_hd44780.rs | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip to communicate with a HD44780 display. | ||
| 2 | //! See (https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use core::fmt::Write; | ||
| 8 | |||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::dma::{AnyChannel, Channel}; | ||
| 12 | use embassy_rp::peripherals::PIO0; | ||
| 13 | use embassy_rp::pio::{ | ||
| 14 | Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 15 | }; | ||
| 16 | use embassy_rp::pwm::{self, Pwm}; | ||
| 17 | use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; | ||
| 18 | use embassy_time::{Instant, Timer}; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | #[link_section = ".start_block"] | ||
| 22 | #[used] | ||
| 23 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 24 | |||
| 25 | // Program metadata for `picotool info` | ||
| 26 | #[link_section = ".bi_entries"] | ||
| 27 | #[used] | ||
| 28 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 29 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 30 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 31 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 32 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 33 | ]; | ||
| 34 | |||
| 35 | bind_interrupts!(pub struct Irqs { | ||
| 36 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 37 | }); | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(_spawner: Spawner) { | ||
| 41 | // this test assumes a 2x16 HD44780 display attached as follow: | ||
| 42 | // rs = PIN0 | ||
| 43 | // rw = PIN1 | ||
| 44 | // e = PIN2 | ||
| 45 | // db4 = PIN3 | ||
| 46 | // db5 = PIN4 | ||
| 47 | // db6 = PIN5 | ||
| 48 | // db7 = PIN6 | ||
| 49 | // additionally a pwm signal for a bias voltage charge pump is provided on pin 15, | ||
| 50 | // allowing direct connection of the display to the RP2040 without level shifters. | ||
| 51 | let p = embassy_rp::init(Default::default()); | ||
| 52 | |||
| 53 | let _pwm = Pwm::new_output_b(p.PWM_SLICE7, p.PIN_15, { | ||
| 54 | let mut c = pwm::Config::default(); | ||
| 55 | c.divider = 125.into(); | ||
| 56 | c.top = 100; | ||
| 57 | c.compare_b = 50; | ||
| 58 | c | ||
| 59 | }); | ||
| 60 | |||
| 61 | let mut hd = HD44780::new( | ||
| 62 | p.PIO0, Irqs, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, | ||
| 63 | ) | ||
| 64 | .await; | ||
| 65 | |||
| 66 | loop { | ||
| 67 | struct Buf<const N: usize>([u8; N], usize); | ||
| 68 | impl<const N: usize> Write for Buf<N> { | ||
| 69 | fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { | ||
| 70 | for b in s.as_bytes() { | ||
| 71 | if self.1 >= N { | ||
| 72 | return Err(core::fmt::Error); | ||
| 73 | } | ||
| 74 | self.0[self.1] = *b; | ||
| 75 | self.1 += 1; | ||
| 76 | } | ||
| 77 | Ok(()) | ||
| 78 | } | ||
| 79 | } | ||
| 80 | let mut buf = Buf([0; 16], 0); | ||
| 81 | write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap(); | ||
| 82 | hd.add_line(&buf.0[0..buf.1]).await; | ||
| 83 | Timer::after_secs(1).await; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | pub struct HD44780<'l> { | ||
| 88 | dma: PeripheralRef<'l, AnyChannel>, | ||
| 89 | sm: StateMachine<'l, PIO0, 0>, | ||
| 90 | |||
| 91 | buf: [u8; 40], | ||
| 92 | } | ||
| 93 | |||
| 94 | impl<'l> HD44780<'l> { | ||
| 95 | pub async fn new( | ||
| 96 | pio: impl Peripheral<P = PIO0> + 'l, | ||
| 97 | irq: Irqs, | ||
| 98 | dma: impl Peripheral<P = impl Channel> + 'l, | ||
| 99 | rs: impl PioPin, | ||
| 100 | rw: impl PioPin, | ||
| 101 | e: impl PioPin, | ||
| 102 | db4: impl PioPin, | ||
| 103 | db5: impl PioPin, | ||
| 104 | db6: impl PioPin, | ||
| 105 | db7: impl PioPin, | ||
| 106 | ) -> HD44780<'l> { | ||
| 107 | into_ref!(dma); | ||
| 108 | |||
| 109 | let Pio { | ||
| 110 | mut common, | ||
| 111 | mut irq0, | ||
| 112 | mut sm0, | ||
| 113 | .. | ||
| 114 | } = Pio::new(pio, irq); | ||
| 115 | |||
| 116 | // takes command words (<wait:24> <command:4> <0:4>) | ||
| 117 | let prg = pio_proc::pio_asm!( | ||
| 118 | r#" | ||
| 119 | .side_set 1 opt | ||
| 120 | .origin 20 | ||
| 121 | |||
| 122 | loop: | ||
| 123 | out x, 24 | ||
| 124 | delay: | ||
| 125 | jmp x--, delay | ||
| 126 | out pins, 4 side 1 | ||
| 127 | out null, 4 side 0 | ||
| 128 | jmp !osre, loop | ||
| 129 | irq 0 | ||
| 130 | "#, | ||
| 131 | ); | ||
| 132 | |||
| 133 | let rs = common.make_pio_pin(rs); | ||
| 134 | let rw = common.make_pio_pin(rw); | ||
| 135 | let e = common.make_pio_pin(e); | ||
| 136 | let db4 = common.make_pio_pin(db4); | ||
| 137 | let db5 = common.make_pio_pin(db5); | ||
| 138 | let db6 = common.make_pio_pin(db6); | ||
| 139 | let db7 = common.make_pio_pin(db7); | ||
| 140 | |||
| 141 | sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); | ||
| 142 | |||
| 143 | let mut cfg = Config::default(); | ||
| 144 | cfg.use_program(&common.load_program(&prg.program), &[&e]); | ||
| 145 | cfg.clock_divider = 125u8.into(); | ||
| 146 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); | ||
| 147 | cfg.shift_out = ShiftConfig { | ||
| 148 | auto_fill: true, | ||
| 149 | direction: ShiftDirection::Left, | ||
| 150 | threshold: 32, | ||
| 151 | }; | ||
| 152 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 153 | sm0.set_config(&cfg); | ||
| 154 | |||
| 155 | sm0.set_enable(true); | ||
| 156 | // init to 8 bit thrice | ||
| 157 | sm0.tx().push((50000 << 8) | 0x30); | ||
| 158 | sm0.tx().push((5000 << 8) | 0x30); | ||
| 159 | sm0.tx().push((200 << 8) | 0x30); | ||
| 160 | // init 4 bit | ||
| 161 | sm0.tx().push((200 << 8) | 0x20); | ||
| 162 | // set font and lines | ||
| 163 | sm0.tx().push((50 << 8) | 0x20); | ||
| 164 | sm0.tx().push(0b1100_0000); | ||
| 165 | |||
| 166 | irq0.wait().await; | ||
| 167 | sm0.set_enable(false); | ||
| 168 | |||
| 169 | // takes command sequences (<rs:1> <count:7>, data...) | ||
| 170 | // many side sets are only there to free up a delay bit! | ||
| 171 | let prg = pio_proc::pio_asm!( | ||
| 172 | r#" | ||
| 173 | .origin 27 | ||
| 174 | .side_set 1 | ||
| 175 | |||
| 176 | .wrap_target | ||
| 177 | pull side 0 | ||
| 178 | out x 1 side 0 ; !rs | ||
| 179 | out y 7 side 0 ; #data - 1 | ||
| 180 | |||
| 181 | ; rs/rw to e: >= 60ns | ||
| 182 | ; e high time: >= 500ns | ||
| 183 | ; e low time: >= 500ns | ||
| 184 | ; read data valid after e falling: ~5ns | ||
| 185 | ; write data hold after e falling: ~10ns | ||
| 186 | |||
| 187 | loop: | ||
| 188 | pull side 0 | ||
| 189 | jmp !x data side 0 | ||
| 190 | command: | ||
| 191 | set pins 0b00 side 0 | ||
| 192 | jmp shift side 0 | ||
| 193 | data: | ||
| 194 | set pins 0b01 side 0 | ||
| 195 | shift: | ||
| 196 | out pins 4 side 1 [9] | ||
| 197 | nop side 0 [9] | ||
| 198 | out pins 4 side 1 [9] | ||
| 199 | mov osr null side 0 [7] | ||
| 200 | out pindirs 4 side 0 | ||
| 201 | set pins 0b10 side 0 | ||
| 202 | busy: | ||
| 203 | nop side 1 [9] | ||
| 204 | jmp pin more side 0 [9] | ||
| 205 | mov osr ~osr side 1 [9] | ||
| 206 | nop side 0 [4] | ||
| 207 | out pindirs 4 side 0 | ||
| 208 | jmp y-- loop side 0 | ||
| 209 | .wrap | ||
| 210 | more: | ||
| 211 | nop side 1 [9] | ||
| 212 | jmp busy side 0 [9] | ||
| 213 | "# | ||
| 214 | ); | ||
| 215 | |||
| 216 | let mut cfg = Config::default(); | ||
| 217 | cfg.use_program(&common.load_program(&prg.program), &[&e]); | ||
| 218 | cfg.clock_divider = 8u8.into(); // ~64ns/insn | ||
| 219 | cfg.set_jmp_pin(&db7); | ||
| 220 | cfg.set_set_pins(&[&rs, &rw]); | ||
| 221 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); | ||
| 222 | cfg.shift_out.direction = ShiftDirection::Left; | ||
| 223 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 224 | sm0.set_config(&cfg); | ||
| 225 | |||
| 226 | sm0.set_enable(true); | ||
| 227 | |||
| 228 | // display on and cursor on and blinking, reset display | ||
| 229 | sm0.tx().dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await; | ||
| 230 | |||
| 231 | Self { | ||
| 232 | dma: dma.map_into(), | ||
| 233 | sm: sm0, | ||
| 234 | buf: [0x20; 40], | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | pub async fn add_line(&mut self, s: &[u8]) { | ||
| 239 | // move cursor to 0:0, prepare 16 characters | ||
| 240 | self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]); | ||
| 241 | // move line 2 up | ||
| 242 | self.buf.copy_within(22..38, 3); | ||
| 243 | // move cursor to 1:0, prepare 16 characters | ||
| 244 | self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]); | ||
| 245 | // file line 2 with spaces | ||
| 246 | self.buf[22..38].fill(0x20); | ||
| 247 | // copy input line | ||
| 248 | let len = s.len().min(16); | ||
| 249 | self.buf[22..22 + len].copy_from_slice(&s[0..len]); | ||
| 250 | // set cursor to 1:15 | ||
| 251 | self.buf[38..].copy_from_slice(&[0x80, 0xcf]); | ||
| 252 | |||
| 253 | self.sm.tx().dma_push(self.dma.reborrow(), &self.buf).await; | ||
| 254 | } | ||
| 255 | } | ||
diff --git a/examples/rp23/src/bin/pio_i2s.rs b/examples/rp23/src/bin/pio_i2s.rs new file mode 100644 index 000000000..d6d2d0ade --- /dev/null +++ b/examples/rp23/src/bin/pio_i2s.rs | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | //! This example shows generating audio and sending it to a connected i2s DAC using the PIO | ||
| 2 | //! module of the RP2040. | ||
| 3 | //! | ||
| 4 | //! Connect the i2s DAC as follows: | ||
| 5 | //! bclk : GPIO 18 | ||
| 6 | //! lrc : GPIO 19 | ||
| 7 | //! din : GPIO 20 | ||
| 8 | //! Then hold down the boot select button to trigger a rising triangle waveform. | ||
| 9 | |||
| 10 | #![no_std] | ||
| 11 | #![no_main] | ||
| 12 | |||
| 13 | use core::mem; | ||
| 14 | |||
| 15 | use embassy_executor::Spawner; | ||
| 16 | use embassy_rp::block::ImageDef; | ||
| 17 | use embassy_rp::peripherals::PIO0; | ||
| 18 | use embassy_rp::pio::{Config, FifoJoin, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; | ||
| 19 | use embassy_rp::{bind_interrupts, Peripheral}; | ||
| 20 | use fixed::traits::ToFixed; | ||
| 21 | use static_cell::StaticCell; | ||
| 22 | use {defmt_rtt as _, panic_probe as _}; | ||
| 23 | |||
| 24 | #[link_section = ".start_block"] | ||
| 25 | #[used] | ||
| 26 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 27 | |||
| 28 | // Program metadata for `picotool info` | ||
| 29 | #[link_section = ".bi_entries"] | ||
| 30 | #[used] | ||
| 31 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 32 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 33 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 34 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 35 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 36 | ]; | ||
| 37 | |||
| 38 | bind_interrupts!(struct Irqs { | ||
| 39 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 40 | }); | ||
| 41 | |||
| 42 | const SAMPLE_RATE: u32 = 48_000; | ||
| 43 | |||
| 44 | #[embassy_executor::main] | ||
| 45 | async fn main(_spawner: Spawner) { | ||
| 46 | let p = embassy_rp::init(Default::default()); | ||
| 47 | |||
| 48 | // Setup pio state machine for i2s output | ||
| 49 | let mut pio = Pio::new(p.PIO0, Irqs); | ||
| 50 | |||
| 51 | #[rustfmt::skip] | ||
| 52 | let pio_program = pio_proc::pio_asm!( | ||
| 53 | ".side_set 2", | ||
| 54 | " set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock | ||
| 55 | "left_data:", | ||
| 56 | " out pins, 1 side 0b00", | ||
| 57 | " jmp x-- left_data side 0b01", | ||
| 58 | " out pins 1 side 0b10", | ||
| 59 | " set x, 14 side 0b11", | ||
| 60 | "right_data:", | ||
| 61 | " out pins 1 side 0b10", | ||
| 62 | " jmp x-- right_data side 0b11", | ||
| 63 | " out pins 1 side 0b00", | ||
| 64 | ); | ||
| 65 | |||
| 66 | let bit_clock_pin = p.PIN_18; | ||
| 67 | let left_right_clock_pin = p.PIN_19; | ||
| 68 | let data_pin = p.PIN_20; | ||
| 69 | |||
| 70 | let data_pin = pio.common.make_pio_pin(data_pin); | ||
| 71 | let bit_clock_pin = pio.common.make_pio_pin(bit_clock_pin); | ||
| 72 | let left_right_clock_pin = pio.common.make_pio_pin(left_right_clock_pin); | ||
| 73 | |||
| 74 | let cfg = { | ||
| 75 | let mut cfg = Config::default(); | ||
| 76 | cfg.use_program( | ||
| 77 | &pio.common.load_program(&pio_program.program), | ||
| 78 | &[&bit_clock_pin, &left_right_clock_pin], | ||
| 79 | ); | ||
| 80 | cfg.set_out_pins(&[&data_pin]); | ||
| 81 | const BIT_DEPTH: u32 = 16; | ||
| 82 | const CHANNELS: u32 = 2; | ||
| 83 | let clock_frequency = SAMPLE_RATE * BIT_DEPTH * CHANNELS; | ||
| 84 | cfg.clock_divider = (125_000_000. / clock_frequency as f64 / 2.).to_fixed(); | ||
| 85 | cfg.shift_out = ShiftConfig { | ||
| 86 | threshold: 32, | ||
| 87 | direction: ShiftDirection::Left, | ||
| 88 | auto_fill: true, | ||
| 89 | }; | ||
| 90 | // join fifos to have twice the time to start the next dma transfer | ||
| 91 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 92 | cfg | ||
| 93 | }; | ||
| 94 | pio.sm0.set_config(&cfg); | ||
| 95 | pio.sm0.set_pin_dirs( | ||
| 96 | embassy_rp::pio::Direction::Out, | ||
| 97 | &[&data_pin, &left_right_clock_pin, &bit_clock_pin], | ||
| 98 | ); | ||
| 99 | |||
| 100 | // create two audio buffers (back and front) which will take turns being | ||
| 101 | // filled with new audio data and being sent to the pio fifo using dma | ||
| 102 | const BUFFER_SIZE: usize = 960; | ||
| 103 | static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new(); | ||
| 104 | let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]); | ||
| 105 | let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE); | ||
| 106 | |||
| 107 | // start pio state machine | ||
| 108 | pio.sm0.set_enable(true); | ||
| 109 | let tx = pio.sm0.tx(); | ||
| 110 | let mut dma_ref = p.DMA_CH0.into_ref(); | ||
| 111 | |||
| 112 | let mut fade_value: i32 = 0; | ||
| 113 | let mut phase: i32 = 0; | ||
| 114 | |||
| 115 | loop { | ||
| 116 | // trigger transfer of front buffer data to the pio fifo | ||
| 117 | // but don't await the returned future, yet | ||
| 118 | let dma_future = tx.dma_push(dma_ref.reborrow(), front_buffer); | ||
| 119 | |||
| 120 | // fade in audio | ||
| 121 | let fade_target = i32::MAX; | ||
| 122 | |||
| 123 | // fill back buffer with fresh audio samples before awaiting the dma future | ||
| 124 | for s in back_buffer.iter_mut() { | ||
| 125 | // exponential approach of fade_value => fade_target | ||
| 126 | fade_value += (fade_target - fade_value) >> 14; | ||
| 127 | // generate triangle wave with amplitude and frequency based on fade value | ||
| 128 | phase = (phase + (fade_value >> 22)) & 0xffff; | ||
| 129 | let triangle_sample = (phase as i16 as i32).abs() - 16384; | ||
| 130 | let sample = (triangle_sample * (fade_value >> 15)) >> 16; | ||
| 131 | // duplicate mono sample into lower and upper half of dma word | ||
| 132 | *s = (sample as u16 as u32) * 0x10001; | ||
| 133 | } | ||
| 134 | |||
| 135 | // now await the dma future. once the dma finishes, the next buffer needs to be queued | ||
| 136 | // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us | ||
| 137 | dma_future.await; | ||
| 138 | mem::swap(&mut back_buffer, &mut front_buffer); | ||
| 139 | } | ||
| 140 | } | ||
diff --git a/examples/rp23/src/bin/pio_pwm.rs b/examples/rp23/src/bin/pio_pwm.rs new file mode 100644 index 000000000..587f91ac3 --- /dev/null +++ b/examples/rp23/src/bin/pio_pwm.rs | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | //! This example shows how to create a pwm using the PIO module in the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | use core::time::Duration; | ||
| 6 | |||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::gpio::Level; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::pio::{Common, Config, Direction, Instance, InterruptHandler, Pio, PioPin, StateMachine}; | ||
| 12 | use embassy_rp::{bind_interrupts, clocks}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use pio::InstructionOperands; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | #[link_section = ".start_block"] | ||
| 18 | #[used] | ||
| 19 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 20 | |||
| 21 | // Program metadata for `picotool info` | ||
| 22 | #[link_section = ".bi_entries"] | ||
| 23 | #[used] | ||
| 24 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 25 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 26 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 27 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 28 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 29 | ]; | ||
| 30 | |||
| 31 | const REFRESH_INTERVAL: u64 = 20000; | ||
| 32 | |||
| 33 | bind_interrupts!(struct Irqs { | ||
| 34 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 35 | }); | ||
| 36 | |||
| 37 | pub fn to_pio_cycles(duration: Duration) -> u32 { | ||
| 38 | (clocks::clk_sys_freq() / 1_000_000) / 3 * duration.as_micros() as u32 // parentheses are required to prevent overflow | ||
| 39 | } | ||
| 40 | |||
| 41 | pub struct PwmPio<'d, T: Instance, const SM: usize> { | ||
| 42 | sm: StateMachine<'d, T, SM>, | ||
| 43 | } | ||
| 44 | |||
| 45 | impl<'d, T: Instance, const SM: usize> PwmPio<'d, T, SM> { | ||
| 46 | pub fn new(pio: &mut Common<'d, T>, mut sm: StateMachine<'d, T, SM>, pin: impl PioPin) -> Self { | ||
| 47 | let prg = pio_proc::pio_asm!( | ||
| 48 | ".side_set 1 opt" | ||
| 49 | "pull noblock side 0" | ||
| 50 | "mov x, osr" | ||
| 51 | "mov y, isr" | ||
| 52 | "countloop:" | ||
| 53 | "jmp x!=y noset" | ||
| 54 | "jmp skip side 1" | ||
| 55 | "noset:" | ||
| 56 | "nop" | ||
| 57 | "skip:" | ||
| 58 | "jmp y-- countloop" | ||
| 59 | ); | ||
| 60 | |||
| 61 | pio.load_program(&prg.program); | ||
| 62 | let pin = pio.make_pio_pin(pin); | ||
| 63 | sm.set_pins(Level::High, &[&pin]); | ||
| 64 | sm.set_pin_dirs(Direction::Out, &[&pin]); | ||
| 65 | |||
| 66 | let mut cfg = Config::default(); | ||
| 67 | cfg.use_program(&pio.load_program(&prg.program), &[&pin]); | ||
| 68 | |||
| 69 | sm.set_config(&cfg); | ||
| 70 | |||
| 71 | Self { sm } | ||
| 72 | } | ||
| 73 | |||
| 74 | pub fn start(&mut self) { | ||
| 75 | self.sm.set_enable(true); | ||
| 76 | } | ||
| 77 | |||
| 78 | pub fn stop(&mut self) { | ||
| 79 | self.sm.set_enable(false); | ||
| 80 | } | ||
| 81 | |||
| 82 | pub fn set_period(&mut self, duration: Duration) { | ||
| 83 | let is_enabled = self.sm.is_enabled(); | ||
| 84 | while !self.sm.tx().empty() {} // Make sure that the queue is empty | ||
| 85 | self.sm.set_enable(false); | ||
| 86 | self.sm.tx().push(to_pio_cycles(duration)); | ||
| 87 | unsafe { | ||
| 88 | self.sm.exec_instr( | ||
| 89 | InstructionOperands::PULL { | ||
| 90 | if_empty: false, | ||
| 91 | block: false, | ||
| 92 | } | ||
| 93 | .encode(), | ||
| 94 | ); | ||
| 95 | self.sm.exec_instr( | ||
| 96 | InstructionOperands::OUT { | ||
| 97 | destination: ::pio::OutDestination::ISR, | ||
| 98 | bit_count: 32, | ||
| 99 | } | ||
| 100 | .encode(), | ||
| 101 | ); | ||
| 102 | }; | ||
| 103 | if is_enabled { | ||
| 104 | self.sm.set_enable(true) // Enable if previously enabled | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn set_level(&mut self, level: u32) { | ||
| 109 | self.sm.tx().push(level); | ||
| 110 | } | ||
| 111 | |||
| 112 | pub fn write(&mut self, duration: Duration) { | ||
| 113 | self.set_level(to_pio_cycles(duration)); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | #[embassy_executor::main] | ||
| 118 | async fn main(_spawner: Spawner) { | ||
| 119 | let p = embassy_rp::init(Default::default()); | ||
| 120 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); | ||
| 121 | |||
| 122 | // Note that PIN_25 is the led pin on the Pico | ||
| 123 | let mut pwm_pio = PwmPio::new(&mut common, sm0, p.PIN_25); | ||
| 124 | pwm_pio.set_period(Duration::from_micros(REFRESH_INTERVAL)); | ||
| 125 | pwm_pio.start(); | ||
| 126 | |||
| 127 | let mut duration = 0; | ||
| 128 | loop { | ||
| 129 | duration = (duration + 1) % 1000; | ||
| 130 | pwm_pio.write(Duration::from_micros(duration)); | ||
| 131 | Timer::after_millis(1).await; | ||
| 132 | } | ||
| 133 | } | ||
diff --git a/examples/rp23/src/bin/pio_rotary_encoder.rs b/examples/rp23/src/bin/pio_rotary_encoder.rs new file mode 100644 index 000000000..c147351e8 --- /dev/null +++ b/examples/rp23/src/bin/pio_rotary_encoder.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | //! This example shows how to use the PIO module in the RP2040 to read a quadrature rotary encoder. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::info; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::gpio::Pull; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::{bind_interrupts, pio}; | ||
| 12 | use fixed::traits::ToFixed; | ||
| 13 | use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | pub struct PioEncoder<'d, T: Instance, const SM: usize> { | ||
| 35 | sm: StateMachine<'d, T, SM>, | ||
| 36 | } | ||
| 37 | |||
| 38 | impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> { | ||
| 39 | pub fn new( | ||
| 40 | pio: &mut Common<'d, T>, | ||
| 41 | mut sm: StateMachine<'d, T, SM>, | ||
| 42 | pin_a: impl PioPin, | ||
| 43 | pin_b: impl PioPin, | ||
| 44 | ) -> Self { | ||
| 45 | let mut pin_a = pio.make_pio_pin(pin_a); | ||
| 46 | let mut pin_b = pio.make_pio_pin(pin_b); | ||
| 47 | pin_a.set_pull(Pull::Up); | ||
| 48 | pin_b.set_pull(Pull::Up); | ||
| 49 | sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]); | ||
| 50 | |||
| 51 | let prg = pio_proc::pio_asm!("wait 1 pin 1", "wait 0 pin 1", "in pins, 2", "push",); | ||
| 52 | |||
| 53 | let mut cfg = Config::default(); | ||
| 54 | cfg.set_in_pins(&[&pin_a, &pin_b]); | ||
| 55 | cfg.fifo_join = FifoJoin::RxOnly; | ||
| 56 | cfg.shift_in.direction = ShiftDirection::Left; | ||
| 57 | cfg.clock_divider = 10_000.to_fixed(); | ||
| 58 | cfg.use_program(&pio.load_program(&prg.program), &[]); | ||
| 59 | sm.set_config(&cfg); | ||
| 60 | sm.set_enable(true); | ||
| 61 | Self { sm } | ||
| 62 | } | ||
| 63 | |||
| 64 | pub async fn read(&mut self) -> Direction { | ||
| 65 | loop { | ||
| 66 | match self.sm.rx().wait_pull().await { | ||
| 67 | 0 => return Direction::CounterClockwise, | ||
| 68 | 1 => return Direction::Clockwise, | ||
| 69 | _ => {} | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | pub enum Direction { | ||
| 76 | Clockwise, | ||
| 77 | CounterClockwise, | ||
| 78 | } | ||
| 79 | |||
| 80 | #[embassy_executor::main] | ||
| 81 | async fn main(_spawner: Spawner) { | ||
| 82 | let p = embassy_rp::init(Default::default()); | ||
| 83 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); | ||
| 84 | |||
| 85 | let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5); | ||
| 86 | |||
| 87 | let mut count = 0; | ||
| 88 | loop { | ||
| 89 | info!("Count: {}", count); | ||
| 90 | count += match encoder.read().await { | ||
| 91 | Direction::Clockwise => 1, | ||
| 92 | Direction::CounterClockwise => -1, | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | } | ||
diff --git a/examples/rp23/src/bin/pio_servo.rs b/examples/rp23/src/bin/pio_servo.rs new file mode 100644 index 000000000..5e8714178 --- /dev/null +++ b/examples/rp23/src/bin/pio_servo.rs | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | //! This example shows how to create a pwm using the PIO module in the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | use core::time::Duration; | ||
| 6 | |||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::gpio::Level; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::pio::{Common, Config, Direction, Instance, InterruptHandler, Pio, PioPin, StateMachine}; | ||
| 12 | use embassy_rp::{bind_interrupts, clocks}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use pio::InstructionOperands; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | #[link_section = ".start_block"] | ||
| 18 | #[used] | ||
| 19 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 20 | |||
| 21 | // Program metadata for `picotool info` | ||
| 22 | #[link_section = ".bi_entries"] | ||
| 23 | #[used] | ||
| 24 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 25 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 26 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 27 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 28 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 29 | ]; | ||
| 30 | |||
| 31 | const DEFAULT_MIN_PULSE_WIDTH: u64 = 1000; // uncalibrated default, the shortest duty cycle sent to a servo | ||
| 32 | const DEFAULT_MAX_PULSE_WIDTH: u64 = 2000; // uncalibrated default, the longest duty cycle sent to a servo | ||
| 33 | const DEFAULT_MAX_DEGREE_ROTATION: u64 = 160; // 160 degrees is typical | ||
| 34 | const REFRESH_INTERVAL: u64 = 20000; // The period of each cycle | ||
| 35 | |||
| 36 | bind_interrupts!(struct Irqs { | ||
| 37 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 38 | }); | ||
| 39 | |||
| 40 | pub fn to_pio_cycles(duration: Duration) -> u32 { | ||
| 41 | (clocks::clk_sys_freq() / 1_000_000) / 3 * duration.as_micros() as u32 // parentheses are required to prevent overflow | ||
| 42 | } | ||
| 43 | |||
| 44 | pub struct PwmPio<'d, T: Instance, const SM: usize> { | ||
| 45 | sm: StateMachine<'d, T, SM>, | ||
| 46 | } | ||
| 47 | |||
| 48 | impl<'d, T: Instance, const SM: usize> PwmPio<'d, T, SM> { | ||
| 49 | pub fn new(pio: &mut Common<'d, T>, mut sm: StateMachine<'d, T, SM>, pin: impl PioPin) -> Self { | ||
| 50 | let prg = pio_proc::pio_asm!( | ||
| 51 | ".side_set 1 opt" | ||
| 52 | "pull noblock side 0" | ||
| 53 | "mov x, osr" | ||
| 54 | "mov y, isr" | ||
| 55 | "countloop:" | ||
| 56 | "jmp x!=y noset" | ||
| 57 | "jmp skip side 1" | ||
| 58 | "noset:" | ||
| 59 | "nop" | ||
| 60 | "skip:" | ||
| 61 | "jmp y-- countloop" | ||
| 62 | ); | ||
| 63 | |||
| 64 | pio.load_program(&prg.program); | ||
| 65 | let pin = pio.make_pio_pin(pin); | ||
| 66 | sm.set_pins(Level::High, &[&pin]); | ||
| 67 | sm.set_pin_dirs(Direction::Out, &[&pin]); | ||
| 68 | |||
| 69 | let mut cfg = Config::default(); | ||
| 70 | cfg.use_program(&pio.load_program(&prg.program), &[&pin]); | ||
| 71 | |||
| 72 | sm.set_config(&cfg); | ||
| 73 | |||
| 74 | Self { sm } | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn start(&mut self) { | ||
| 78 | self.sm.set_enable(true); | ||
| 79 | } | ||
| 80 | |||
| 81 | pub fn stop(&mut self) { | ||
| 82 | self.sm.set_enable(false); | ||
| 83 | } | ||
| 84 | |||
| 85 | pub fn set_period(&mut self, duration: Duration) { | ||
| 86 | let is_enabled = self.sm.is_enabled(); | ||
| 87 | while !self.sm.tx().empty() {} // Make sure that the queue is empty | ||
| 88 | self.sm.set_enable(false); | ||
| 89 | self.sm.tx().push(to_pio_cycles(duration)); | ||
| 90 | unsafe { | ||
| 91 | self.sm.exec_instr( | ||
| 92 | InstructionOperands::PULL { | ||
| 93 | if_empty: false, | ||
| 94 | block: false, | ||
| 95 | } | ||
| 96 | .encode(), | ||
| 97 | ); | ||
| 98 | self.sm.exec_instr( | ||
| 99 | InstructionOperands::OUT { | ||
| 100 | destination: ::pio::OutDestination::ISR, | ||
| 101 | bit_count: 32, | ||
| 102 | } | ||
| 103 | .encode(), | ||
| 104 | ); | ||
| 105 | }; | ||
| 106 | if is_enabled { | ||
| 107 | self.sm.set_enable(true) // Enable if previously enabled | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | pub fn set_level(&mut self, level: u32) { | ||
| 112 | self.sm.tx().push(level); | ||
| 113 | } | ||
| 114 | |||
| 115 | pub fn write(&mut self, duration: Duration) { | ||
| 116 | self.set_level(to_pio_cycles(duration)); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | pub struct ServoBuilder<'d, T: Instance, const SM: usize> { | ||
| 121 | pwm: PwmPio<'d, T, SM>, | ||
| 122 | period: Duration, | ||
| 123 | min_pulse_width: Duration, | ||
| 124 | max_pulse_width: Duration, | ||
| 125 | max_degree_rotation: u64, | ||
| 126 | } | ||
| 127 | |||
| 128 | impl<'d, T: Instance, const SM: usize> ServoBuilder<'d, T, SM> { | ||
| 129 | pub fn new(pwm: PwmPio<'d, T, SM>) -> Self { | ||
| 130 | Self { | ||
| 131 | pwm, | ||
| 132 | period: Duration::from_micros(REFRESH_INTERVAL), | ||
| 133 | min_pulse_width: Duration::from_micros(DEFAULT_MIN_PULSE_WIDTH), | ||
| 134 | max_pulse_width: Duration::from_micros(DEFAULT_MAX_PULSE_WIDTH), | ||
| 135 | max_degree_rotation: DEFAULT_MAX_DEGREE_ROTATION, | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | pub fn set_period(mut self, duration: Duration) -> Self { | ||
| 140 | self.period = duration; | ||
| 141 | self | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn set_min_pulse_width(mut self, duration: Duration) -> Self { | ||
| 145 | self.min_pulse_width = duration; | ||
| 146 | self | ||
| 147 | } | ||
| 148 | |||
| 149 | pub fn set_max_pulse_width(mut self, duration: Duration) -> Self { | ||
| 150 | self.max_pulse_width = duration; | ||
| 151 | self | ||
| 152 | } | ||
| 153 | |||
| 154 | pub fn set_max_degree_rotation(mut self, degree: u64) -> Self { | ||
| 155 | self.max_degree_rotation = degree; | ||
| 156 | self | ||
| 157 | } | ||
| 158 | |||
| 159 | pub fn build(mut self) -> Servo<'d, T, SM> { | ||
| 160 | self.pwm.set_period(self.period); | ||
| 161 | Servo { | ||
| 162 | pwm: self.pwm, | ||
| 163 | min_pulse_width: self.min_pulse_width, | ||
| 164 | max_pulse_width: self.max_pulse_width, | ||
| 165 | max_degree_rotation: self.max_degree_rotation, | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | pub struct Servo<'d, T: Instance, const SM: usize> { | ||
| 171 | pwm: PwmPio<'d, T, SM>, | ||
| 172 | min_pulse_width: Duration, | ||
| 173 | max_pulse_width: Duration, | ||
| 174 | max_degree_rotation: u64, | ||
| 175 | } | ||
| 176 | |||
| 177 | impl<'d, T: Instance, const SM: usize> Servo<'d, T, SM> { | ||
| 178 | pub fn start(&mut self) { | ||
| 179 | self.pwm.start(); | ||
| 180 | } | ||
| 181 | |||
| 182 | pub fn stop(&mut self) { | ||
| 183 | self.pwm.stop(); | ||
| 184 | } | ||
| 185 | |||
| 186 | pub fn write_time(&mut self, duration: Duration) { | ||
| 187 | self.pwm.write(duration); | ||
| 188 | } | ||
| 189 | |||
| 190 | pub fn rotate(&mut self, degree: u64) { | ||
| 191 | let degree_per_nano_second = (self.max_pulse_width.as_nanos() as u64 - self.min_pulse_width.as_nanos() as u64) | ||
| 192 | / self.max_degree_rotation; | ||
| 193 | let mut duration = | ||
| 194 | Duration::from_nanos(degree * degree_per_nano_second + self.min_pulse_width.as_nanos() as u64); | ||
| 195 | if self.max_pulse_width < duration { | ||
| 196 | duration = self.max_pulse_width; | ||
| 197 | } | ||
| 198 | |||
| 199 | self.pwm.write(duration); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | #[embassy_executor::main] | ||
| 204 | async fn main(_spawner: Spawner) { | ||
| 205 | let p = embassy_rp::init(Default::default()); | ||
| 206 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); | ||
| 207 | |||
| 208 | let pwm_pio = PwmPio::new(&mut common, sm0, p.PIN_1); | ||
| 209 | let mut servo = ServoBuilder::new(pwm_pio) | ||
| 210 | .set_max_degree_rotation(120) // Example of adjusting values for MG996R servo | ||
| 211 | .set_min_pulse_width(Duration::from_micros(350)) // This value was detemined by a rough experiment. | ||
| 212 | .set_max_pulse_width(Duration::from_micros(2600)) // Along with this value. | ||
| 213 | .build(); | ||
| 214 | |||
| 215 | servo.start(); | ||
| 216 | |||
| 217 | let mut degree = 0; | ||
| 218 | loop { | ||
| 219 | degree = (degree + 1) % 120; | ||
| 220 | servo.rotate(degree); | ||
| 221 | Timer::after_millis(50).await; | ||
| 222 | } | ||
| 223 | } | ||
diff --git a/examples/rp23/src/bin/pio_stepper.rs b/examples/rp23/src/bin/pio_stepper.rs new file mode 100644 index 000000000..24785443b --- /dev/null +++ b/examples/rp23/src/bin/pio_stepper.rs | |||
| @@ -0,0 +1,183 @@ | |||
| 1 | //! This example shows how to use the PIO module in the RP2040 to implement a stepper motor driver | ||
| 2 | //! for a 5-wire stepper such as the 28BYJ-48. You can halt an ongoing rotation by dropping the future. | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | use core::mem::{self, MaybeUninit}; | ||
| 7 | |||
| 8 | use defmt::info; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::peripherals::PIO0; | ||
| 13 | use embassy_rp::pio::{Common, Config, Direction, Instance, InterruptHandler, Irq, Pio, PioPin, StateMachine}; | ||
| 14 | use embassy_time::{with_timeout, Duration, Timer}; | ||
| 15 | use fixed::traits::ToFixed; | ||
| 16 | use fixed::types::extra::U8; | ||
| 17 | use fixed::FixedU32; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | #[link_section = ".start_block"] | ||
| 21 | #[used] | ||
| 22 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 23 | |||
| 24 | // Program metadata for `picotool info` | ||
| 25 | #[link_section = ".bi_entries"] | ||
| 26 | #[used] | ||
| 27 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 28 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 29 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 30 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 31 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 32 | ]; | ||
| 33 | |||
| 34 | bind_interrupts!(struct Irqs { | ||
| 35 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 36 | }); | ||
| 37 | |||
| 38 | pub struct PioStepper<'d, T: Instance, const SM: usize> { | ||
| 39 | irq: Irq<'d, T, SM>, | ||
| 40 | sm: StateMachine<'d, T, SM>, | ||
| 41 | } | ||
| 42 | |||
| 43 | impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> { | ||
| 44 | pub fn new( | ||
| 45 | pio: &mut Common<'d, T>, | ||
| 46 | mut sm: StateMachine<'d, T, SM>, | ||
| 47 | irq: Irq<'d, T, SM>, | ||
| 48 | pin0: impl PioPin, | ||
| 49 | pin1: impl PioPin, | ||
| 50 | pin2: impl PioPin, | ||
| 51 | pin3: impl PioPin, | ||
| 52 | ) -> Self { | ||
| 53 | let prg = pio_proc::pio_asm!( | ||
| 54 | "pull block", | ||
| 55 | "mov x, osr", | ||
| 56 | "pull block", | ||
| 57 | "mov y, osr", | ||
| 58 | "jmp !x end", | ||
| 59 | "loop:", | ||
| 60 | "jmp !osre step", | ||
| 61 | "mov osr, y", | ||
| 62 | "step:", | ||
| 63 | "out pins, 4 [31]" | ||
| 64 | "jmp x-- loop", | ||
| 65 | "end:", | ||
| 66 | "irq 0 rel" | ||
| 67 | ); | ||
| 68 | let pin0 = pio.make_pio_pin(pin0); | ||
| 69 | let pin1 = pio.make_pio_pin(pin1); | ||
| 70 | let pin2 = pio.make_pio_pin(pin2); | ||
| 71 | let pin3 = pio.make_pio_pin(pin3); | ||
| 72 | sm.set_pin_dirs(Direction::Out, &[&pin0, &pin1, &pin2, &pin3]); | ||
| 73 | let mut cfg = Config::default(); | ||
| 74 | cfg.set_out_pins(&[&pin0, &pin1, &pin2, &pin3]); | ||
| 75 | cfg.clock_divider = (125_000_000 / (100 * 136)).to_fixed(); | ||
| 76 | cfg.use_program(&pio.load_program(&prg.program), &[]); | ||
| 77 | sm.set_config(&cfg); | ||
| 78 | sm.set_enable(true); | ||
| 79 | Self { irq, sm } | ||
| 80 | } | ||
| 81 | |||
| 82 | // Set pulse frequency | ||
| 83 | pub fn set_frequency(&mut self, freq: u32) { | ||
| 84 | let clock_divider: FixedU32<U8> = (125_000_000 / (freq * 136)).to_fixed(); | ||
| 85 | assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); | ||
| 86 | assert!(clock_divider >= 1, "clkdiv must be >= 1"); | ||
| 87 | self.sm.set_clock_divider(clock_divider); | ||
| 88 | self.sm.clkdiv_restart(); | ||
| 89 | } | ||
| 90 | |||
| 91 | // Full step, one phase | ||
| 92 | pub async fn step(&mut self, steps: i32) { | ||
| 93 | if steps > 0 { | ||
| 94 | self.run(steps, 0b1000_0100_0010_0001_1000_0100_0010_0001).await | ||
| 95 | } else { | ||
| 96 | self.run(-steps, 0b0001_0010_0100_1000_0001_0010_0100_1000).await | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | // Full step, two phase | ||
| 101 | pub async fn step2(&mut self, steps: i32) { | ||
| 102 | if steps > 0 { | ||
| 103 | self.run(steps, 0b1001_1100_0110_0011_1001_1100_0110_0011).await | ||
| 104 | } else { | ||
| 105 | self.run(-steps, 0b0011_0110_1100_1001_0011_0110_1100_1001).await | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | // Half step | ||
| 110 | pub async fn step_half(&mut self, steps: i32) { | ||
| 111 | if steps > 0 { | ||
| 112 | self.run(steps, 0b1001_1000_1100_0100_0110_0010_0011_0001).await | ||
| 113 | } else { | ||
| 114 | self.run(-steps, 0b0001_0011_0010_0110_0100_1100_1000_1001).await | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | async fn run(&mut self, steps: i32, pattern: u32) { | ||
| 119 | self.sm.tx().wait_push(steps as u32).await; | ||
| 120 | self.sm.tx().wait_push(pattern).await; | ||
| 121 | let drop = OnDrop::new(|| { | ||
| 122 | self.sm.clear_fifos(); | ||
| 123 | unsafe { | ||
| 124 | self.sm.exec_instr( | ||
| 125 | pio::InstructionOperands::JMP { | ||
| 126 | address: 0, | ||
| 127 | condition: pio::JmpCondition::Always, | ||
| 128 | } | ||
| 129 | .encode(), | ||
| 130 | ); | ||
| 131 | } | ||
| 132 | }); | ||
| 133 | self.irq.wait().await; | ||
| 134 | drop.defuse(); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | struct OnDrop<F: FnOnce()> { | ||
| 139 | f: MaybeUninit<F>, | ||
| 140 | } | ||
| 141 | |||
| 142 | impl<F: FnOnce()> OnDrop<F> { | ||
| 143 | pub fn new(f: F) -> Self { | ||
| 144 | Self { f: MaybeUninit::new(f) } | ||
| 145 | } | ||
| 146 | |||
| 147 | pub fn defuse(self) { | ||
| 148 | mem::forget(self) | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | impl<F: FnOnce()> Drop for OnDrop<F> { | ||
| 153 | fn drop(&mut self) { | ||
| 154 | unsafe { self.f.as_ptr().read()() } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | #[embassy_executor::main] | ||
| 159 | async fn main(_spawner: Spawner) { | ||
| 160 | let p = embassy_rp::init(Default::default()); | ||
| 161 | let Pio { | ||
| 162 | mut common, irq0, sm0, .. | ||
| 163 | } = Pio::new(p.PIO0, Irqs); | ||
| 164 | |||
| 165 | let mut stepper = PioStepper::new(&mut common, sm0, irq0, p.PIN_4, p.PIN_5, p.PIN_6, p.PIN_7); | ||
| 166 | stepper.set_frequency(120); | ||
| 167 | loop { | ||
| 168 | info!("CW full steps"); | ||
| 169 | stepper.step(1000).await; | ||
| 170 | |||
| 171 | info!("CCW full steps, drop after 1 sec"); | ||
| 172 | if let Err(_) = with_timeout(Duration::from_secs(1), stepper.step(i32::MIN)).await { | ||
| 173 | info!("Time's up!"); | ||
| 174 | Timer::after(Duration::from_secs(1)).await; | ||
| 175 | } | ||
| 176 | |||
| 177 | info!("CW half steps"); | ||
| 178 | stepper.step_half(1000).await; | ||
| 179 | |||
| 180 | info!("CCW half steps"); | ||
| 181 | stepper.step_half(-1000).await; | ||
| 182 | } | ||
| 183 | } | ||
diff --git a/examples/rp23/src/bin/pio_ws2812.rs b/examples/rp23/src/bin/pio_ws2812.rs new file mode 100644 index 000000000..00fe5e396 --- /dev/null +++ b/examples/rp23/src/bin/pio_ws2812.rs | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip to communicate with WS2812 LED modules. | ||
| 2 | //! See (https://www.sparkfun.com/categories/tags/ws2812) | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::block::ImageDef; | ||
| 10 | use embassy_rp::dma::{AnyChannel, Channel}; | ||
| 11 | use embassy_rp::peripherals::PIO0; | ||
| 12 | use embassy_rp::pio::{ | ||
| 13 | Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 14 | }; | ||
| 15 | use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; | ||
| 16 | use embassy_time::{Duration, Ticker, Timer}; | ||
| 17 | use fixed::types::U24F8; | ||
| 18 | use fixed_macro::fixed; | ||
| 19 | use smart_leds::RGB8; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | #[link_section = ".start_block"] | ||
| 23 | #[used] | ||
| 24 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 25 | |||
| 26 | // Program metadata for `picotool info` | ||
| 27 | #[link_section = ".bi_entries"] | ||
| 28 | #[used] | ||
| 29 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 30 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 31 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 32 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 33 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 34 | ]; | ||
| 35 | |||
| 36 | bind_interrupts!(struct Irqs { | ||
| 37 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 38 | }); | ||
| 39 | |||
| 40 | pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { | ||
| 41 | dma: PeripheralRef<'d, AnyChannel>, | ||
| 42 | sm: StateMachine<'d, P, S>, | ||
| 43 | } | ||
| 44 | |||
| 45 | impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> { | ||
| 46 | pub fn new( | ||
| 47 | pio: &mut Common<'d, P>, | ||
| 48 | mut sm: StateMachine<'d, P, S>, | ||
| 49 | dma: impl Peripheral<P = impl Channel> + 'd, | ||
| 50 | pin: impl PioPin, | ||
| 51 | ) -> Self { | ||
| 52 | into_ref!(dma); | ||
| 53 | |||
| 54 | // Setup sm0 | ||
| 55 | |||
| 56 | // prepare the PIO program | ||
| 57 | let side_set = pio::SideSet::new(false, 1, false); | ||
| 58 | let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set); | ||
| 59 | |||
| 60 | const T1: u8 = 2; // start bit | ||
| 61 | const T2: u8 = 5; // data bit | ||
| 62 | const T3: u8 = 3; // stop bit | ||
| 63 | const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; | ||
| 64 | |||
| 65 | let mut wrap_target = a.label(); | ||
| 66 | let mut wrap_source = a.label(); | ||
| 67 | let mut do_zero = a.label(); | ||
| 68 | a.set_with_side_set(pio::SetDestination::PINDIRS, 1, 0); | ||
| 69 | a.bind(&mut wrap_target); | ||
| 70 | // Do stop bit | ||
| 71 | a.out_with_delay_and_side_set(pio::OutDestination::X, 1, T3 - 1, 0); | ||
| 72 | // Do start bit | ||
| 73 | a.jmp_with_delay_and_side_set(pio::JmpCondition::XIsZero, &mut do_zero, T1 - 1, 1); | ||
| 74 | // Do data bit = 1 | ||
| 75 | a.jmp_with_delay_and_side_set(pio::JmpCondition::Always, &mut wrap_target, T2 - 1, 1); | ||
| 76 | a.bind(&mut do_zero); | ||
| 77 | // Do data bit = 0 | ||
| 78 | a.nop_with_delay_and_side_set(T2 - 1, 0); | ||
| 79 | a.bind(&mut wrap_source); | ||
| 80 | |||
| 81 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); | ||
| 82 | let mut cfg = Config::default(); | ||
| 83 | |||
| 84 | // Pin config | ||
| 85 | let out_pin = pio.make_pio_pin(pin); | ||
| 86 | cfg.set_out_pins(&[&out_pin]); | ||
| 87 | cfg.set_set_pins(&[&out_pin]); | ||
| 88 | |||
| 89 | cfg.use_program(&pio.load_program(&prg), &[&out_pin]); | ||
| 90 | |||
| 91 | // Clock config, measured in kHz to avoid overflows | ||
| 92 | // TODO CLOCK_FREQ should come from embassy_rp | ||
| 93 | let clock_freq = U24F8::from_num(clocks::clk_sys_freq() / 1000); | ||
| 94 | let ws2812_freq = fixed!(800: U24F8); | ||
| 95 | let bit_freq = ws2812_freq * CYCLES_PER_BIT; | ||
| 96 | cfg.clock_divider = clock_freq / bit_freq; | ||
| 97 | |||
| 98 | // FIFO config | ||
| 99 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 100 | cfg.shift_out = ShiftConfig { | ||
| 101 | auto_fill: true, | ||
| 102 | threshold: 24, | ||
| 103 | direction: ShiftDirection::Left, | ||
| 104 | }; | ||
| 105 | |||
| 106 | sm.set_config(&cfg); | ||
| 107 | sm.set_enable(true); | ||
| 108 | |||
| 109 | Self { | ||
| 110 | dma: dma.map_into(), | ||
| 111 | sm, | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | pub async fn write(&mut self, colors: &[RGB8; N]) { | ||
| 116 | // Precompute the word bytes from the colors | ||
| 117 | let mut words = [0u32; N]; | ||
| 118 | for i in 0..N { | ||
| 119 | let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8); | ||
| 120 | words[i] = word; | ||
| 121 | } | ||
| 122 | |||
| 123 | // DMA transfer | ||
| 124 | self.sm.tx().dma_push(self.dma.reborrow(), &words).await; | ||
| 125 | |||
| 126 | Timer::after_micros(55).await; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | /// Input a value 0 to 255 to get a color value | ||
| 131 | /// The colours are a transition r - g - b - back to r. | ||
| 132 | fn wheel(mut wheel_pos: u8) -> RGB8 { | ||
| 133 | wheel_pos = 255 - wheel_pos; | ||
| 134 | if wheel_pos < 85 { | ||
| 135 | return (255 - wheel_pos * 3, 0, wheel_pos * 3).into(); | ||
| 136 | } | ||
| 137 | if wheel_pos < 170 { | ||
| 138 | wheel_pos -= 85; | ||
| 139 | return (0, wheel_pos * 3, 255 - wheel_pos * 3).into(); | ||
| 140 | } | ||
| 141 | wheel_pos -= 170; | ||
| 142 | (wheel_pos * 3, 255 - wheel_pos * 3, 0).into() | ||
| 143 | } | ||
| 144 | |||
| 145 | #[embassy_executor::main] | ||
| 146 | async fn main(_spawner: Spawner) { | ||
| 147 | info!("Start"); | ||
| 148 | let p = embassy_rp::init(Default::default()); | ||
| 149 | |||
| 150 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); | ||
| 151 | |||
| 152 | // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit | ||
| 153 | // feather boards for the 2040 both have one built in. | ||
| 154 | const NUM_LEDS: usize = 1; | ||
| 155 | let mut data = [RGB8::default(); NUM_LEDS]; | ||
| 156 | |||
| 157 | // Common neopixel pins: | ||
| 158 | // Thing plus: 8 | ||
| 159 | // Adafruit Feather: 16; Adafruit Feather+RFM95: 4 | ||
| 160 | let mut ws2812 = Ws2812::new(&mut common, sm0, p.DMA_CH0, p.PIN_16); | ||
| 161 | |||
| 162 | // Loop forever making RGB values and pushing them out to the WS2812. | ||
| 163 | let mut ticker = Ticker::every(Duration::from_millis(10)); | ||
| 164 | loop { | ||
| 165 | for j in 0..(256 * 5) { | ||
| 166 | debug!("New Colors:"); | ||
| 167 | for i in 0..NUM_LEDS { | ||
| 168 | data[i] = wheel((((i * 256) as u16 / NUM_LEDS as u16 + j as u16) & 255) as u8); | ||
| 169 | debug!("R: {} G: {} B: {}", data[i].r, data[i].g, data[i].b); | ||
| 170 | } | ||
| 171 | ws2812.write(&data).await; | ||
| 172 | |||
| 173 | ticker.next().await; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
diff --git a/examples/rp23/src/bin/pwm.rs b/examples/rp23/src/bin/pwm.rs new file mode 100644 index 000000000..bfc2c6f67 --- /dev/null +++ b/examples/rp23/src/bin/pwm.rs | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | //! This example shows how to use PWM (Pulse Width Modulation) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::pwm::{Config, Pwm}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | #[link_section = ".start_block"] | ||
| 16 | #[used] | ||
| 17 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 18 | |||
| 19 | // Program metadata for `picotool info` | ||
| 20 | #[link_section = ".bi_entries"] | ||
| 21 | #[used] | ||
| 22 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 23 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 24 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 25 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 26 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 27 | ]; | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | let p = embassy_rp::init(Default::default()); | ||
| 32 | |||
| 33 | let mut c: Config = Default::default(); | ||
| 34 | c.top = 0x8000; | ||
| 35 | c.compare_b = 8; | ||
| 36 | let mut pwm = Pwm::new_output_b(p.PWM_SLICE4, p.PIN_25, c.clone()); | ||
| 37 | |||
| 38 | loop { | ||
| 39 | info!("current LED duty cycle: {}/32768", c.compare_b); | ||
| 40 | Timer::after_secs(1).await; | ||
| 41 | c.compare_b = c.compare_b.rotate_left(4); | ||
| 42 | pwm.set_config(&c); | ||
| 43 | } | ||
| 44 | } | ||
diff --git a/examples/rp23/src/bin/pwm_input.rs b/examples/rp23/src/bin/pwm_input.rs new file mode 100644 index 000000000..b65f2778b --- /dev/null +++ b/examples/rp23/src/bin/pwm_input.rs | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | //! This example shows how to use the PWM module to measure the frequency of an input signal. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_rp::block::ImageDef; | ||
| 9 | use embassy_rp::gpio::Pull; | ||
| 10 | use embassy_rp::pwm::{Config, InputMode, Pwm}; | ||
| 11 | use embassy_time::{Duration, Ticker}; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | #[embassy_executor::main] | ||
| 29 | async fn main(_spawner: Spawner) { | ||
| 30 | let p = embassy_rp::init(Default::default()); | ||
| 31 | |||
| 32 | let cfg: Config = Default::default(); | ||
| 33 | let pwm = Pwm::new_input(p.PWM_SLICE2, p.PIN_5, Pull::None, InputMode::RisingEdge, cfg); | ||
| 34 | |||
| 35 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 36 | loop { | ||
| 37 | info!("Input frequency: {} Hz", pwm.counter()); | ||
| 38 | pwm.set_counter(0); | ||
| 39 | ticker.next().await; | ||
| 40 | } | ||
| 41 | } | ||
diff --git a/examples/rp23/src/bin/rosc.rs b/examples/rp23/src/bin/rosc.rs new file mode 100644 index 000000000..f65b236b1 --- /dev/null +++ b/examples/rp23/src/bin/rosc.rs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | //! This example test the RP Pico on board LED. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. See wifi_blinky.rs. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::{clocks, gpio}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use gpio::{Level, Output}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(_spawner: Spawner) { | ||
| 32 | let mut config = embassy_rp::config::Config::default(); | ||
| 33 | config.clocks = clocks::ClockConfig::rosc(); | ||
| 34 | let p = embassy_rp::init(config); | ||
| 35 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 36 | |||
| 37 | loop { | ||
| 38 | info!("led on!"); | ||
| 39 | led.set_high(); | ||
| 40 | Timer::after_secs(1).await; | ||
| 41 | |||
| 42 | info!("led off!"); | ||
| 43 | led.set_low(); | ||
| 44 | Timer::after_secs(1).await; | ||
| 45 | } | ||
| 46 | } | ||
diff --git a/examples/rp23/src/bin/shared_bus.rs b/examples/rp23/src/bin/shared_bus.rs new file mode 100644 index 000000000..b3fde13e3 --- /dev/null +++ b/examples/rp23/src/bin/shared_bus.rs | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | //! This example shows how to share (async) I2C and SPI buses between multiple devices. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; | ||
| 8 | use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::gpio::{AnyPin, Level, Output}; | ||
| 13 | use embassy_rp::i2c::{self, I2c, InterruptHandler}; | ||
| 14 | use embassy_rp::peripherals::{I2C1, SPI1}; | ||
| 15 | use embassy_rp::spi::{self, Spi}; | ||
| 16 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 17 | use embassy_sync::mutex::Mutex; | ||
| 18 | use embassy_time::Timer; | ||
| 19 | use static_cell::StaticCell; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | #[link_section = ".start_block"] | ||
| 23 | #[used] | ||
| 24 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 25 | |||
| 26 | // Program metadata for `picotool info` | ||
| 27 | #[link_section = ".bi_entries"] | ||
| 28 | #[used] | ||
| 29 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 30 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 31 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 32 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 33 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 34 | ]; | ||
| 35 | |||
| 36 | type Spi1Bus = Mutex<NoopRawMutex, Spi<'static, SPI1, spi::Async>>; | ||
| 37 | type I2c1Bus = Mutex<NoopRawMutex, I2c<'static, I2C1, i2c::Async>>; | ||
| 38 | |||
| 39 | bind_interrupts!(struct Irqs { | ||
| 40 | I2C1_IRQ => InterruptHandler<I2C1>; | ||
| 41 | }); | ||
| 42 | |||
| 43 | #[embassy_executor::main] | ||
| 44 | async fn main(spawner: Spawner) { | ||
| 45 | let p = embassy_rp::init(Default::default()); | ||
| 46 | info!("Here we go!"); | ||
| 47 | |||
| 48 | // Shared I2C bus | ||
| 49 | let i2c = I2c::new_async(p.I2C1, p.PIN_15, p.PIN_14, Irqs, i2c::Config::default()); | ||
| 50 | static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); | ||
| 51 | let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); | ||
| 52 | |||
| 53 | spawner.must_spawn(i2c_task_a(i2c_bus)); | ||
| 54 | spawner.must_spawn(i2c_task_b(i2c_bus)); | ||
| 55 | |||
| 56 | // Shared SPI bus | ||
| 57 | let spi_cfg = spi::Config::default(); | ||
| 58 | let spi = Spi::new(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, spi_cfg); | ||
| 59 | static SPI_BUS: StaticCell<Spi1Bus> = StaticCell::new(); | ||
| 60 | let spi_bus = SPI_BUS.init(Mutex::new(spi)); | ||
| 61 | |||
| 62 | // Chip select pins for the SPI devices | ||
| 63 | let cs_a = Output::new(AnyPin::from(p.PIN_0), Level::High); | ||
| 64 | let cs_b = Output::new(AnyPin::from(p.PIN_1), Level::High); | ||
| 65 | |||
| 66 | spawner.must_spawn(spi_task_a(spi_bus, cs_a)); | ||
| 67 | spawner.must_spawn(spi_task_b(spi_bus, cs_b)); | ||
| 68 | } | ||
| 69 | |||
| 70 | #[embassy_executor::task] | ||
| 71 | async fn i2c_task_a(i2c_bus: &'static I2c1Bus) { | ||
| 72 | let i2c_dev = I2cDevice::new(i2c_bus); | ||
| 73 | let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xC0); | ||
| 74 | loop { | ||
| 75 | info!("i2c task A"); | ||
| 76 | Timer::after_secs(1).await; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | #[embassy_executor::task] | ||
| 81 | async fn i2c_task_b(i2c_bus: &'static I2c1Bus) { | ||
| 82 | let i2c_dev = I2cDevice::new(i2c_bus); | ||
| 83 | let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xDE); | ||
| 84 | loop { | ||
| 85 | info!("i2c task B"); | ||
| 86 | Timer::after_secs(1).await; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | #[embassy_executor::task] | ||
| 91 | async fn spi_task_a(spi_bus: &'static Spi1Bus, cs: Output<'static>) { | ||
| 92 | let spi_dev = SpiDevice::new(spi_bus, cs); | ||
| 93 | let _sensor = DummySpiDeviceDriver::new(spi_dev); | ||
| 94 | loop { | ||
| 95 | info!("spi task A"); | ||
| 96 | Timer::after_secs(1).await; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | #[embassy_executor::task] | ||
| 101 | async fn spi_task_b(spi_bus: &'static Spi1Bus, cs: Output<'static>) { | ||
| 102 | let spi_dev = SpiDevice::new(spi_bus, cs); | ||
| 103 | let _sensor = DummySpiDeviceDriver::new(spi_dev); | ||
| 104 | loop { | ||
| 105 | info!("spi task B"); | ||
| 106 | Timer::after_secs(1).await; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | // Dummy I2C device driver, using `embedded-hal-async` | ||
| 111 | struct DummyI2cDeviceDriver<I2C: embedded_hal_async::i2c::I2c> { | ||
| 112 | _i2c: I2C, | ||
| 113 | } | ||
| 114 | |||
| 115 | impl<I2C: embedded_hal_async::i2c::I2c> DummyI2cDeviceDriver<I2C> { | ||
| 116 | fn new(i2c_dev: I2C, _address: u8) -> Self { | ||
| 117 | Self { _i2c: i2c_dev } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | // Dummy SPI device driver, using `embedded-hal-async` | ||
| 122 | struct DummySpiDeviceDriver<SPI: embedded_hal_async::spi::SpiDevice> { | ||
| 123 | _spi: SPI, | ||
| 124 | } | ||
| 125 | |||
| 126 | impl<SPI: embedded_hal_async::spi::SpiDevice> DummySpiDeviceDriver<SPI> { | ||
| 127 | fn new(spi_dev: SPI) -> Self { | ||
| 128 | Self { _spi: spi_dev } | ||
| 129 | } | ||
| 130 | } | ||
diff --git a/examples/rp23/src/bin/sharing.rs b/examples/rp23/src/bin/sharing.rs new file mode 100644 index 000000000..4a3301cfd --- /dev/null +++ b/examples/rp23/src/bin/sharing.rs | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | //! This example shows some common strategies for sharing resources between tasks. | ||
| 2 | //! | ||
| 3 | //! We demonstrate five different ways of sharing, covering different use cases: | ||
| 4 | //! - Atomics: This method is used for simple values, such as bool and u8..u32 | ||
| 5 | //! - Blocking Mutex: This is used for sharing non-async things, using Cell/RefCell for interior mutability. | ||
| 6 | //! - Async Mutex: This is used for sharing async resources, where you need to hold the lock across await points. | ||
| 7 | //! The async Mutex has interior mutability built-in, so no RefCell is needed. | ||
| 8 | //! - Cell: For sharing Copy types between tasks running on the same executor. | ||
| 9 | //! - RefCell: When you want &mut access to a value shared between tasks running on the same executor. | ||
| 10 | //! | ||
| 11 | //! More information: https://embassy.dev/book/#_sharing_peripherals_between_tasks | ||
| 12 | |||
| 13 | #![no_std] | ||
| 14 | #![no_main] | ||
| 15 | |||
| 16 | use core::cell::{Cell, RefCell}; | ||
| 17 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 18 | |||
| 19 | use cortex_m_rt::entry; | ||
| 20 | use defmt::info; | ||
| 21 | use embassy_executor::{Executor, InterruptExecutor}; | ||
| 22 | use embassy_rp::block::ImageDef; | ||
| 23 | use embassy_rp::clocks::RoscRng; | ||
| 24 | use embassy_rp::interrupt::{InterruptExt, Priority}; | ||
| 25 | use embassy_rp::peripherals::UART0; | ||
| 26 | use embassy_rp::uart::{self, InterruptHandler, UartTx}; | ||
| 27 | use embassy_rp::{bind_interrupts, interrupt}; | ||
| 28 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 29 | use embassy_sync::{blocking_mutex, mutex}; | ||
| 30 | use embassy_time::{Duration, Ticker}; | ||
| 31 | use rand::RngCore; | ||
| 32 | use static_cell::{ConstStaticCell, StaticCell}; | ||
| 33 | use {defmt_rtt as _, panic_probe as _}; | ||
| 34 | |||
| 35 | #[link_section = ".start_block"] | ||
| 36 | #[used] | ||
| 37 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 38 | |||
| 39 | // Program metadata for `picotool info` | ||
| 40 | #[link_section = ".bi_entries"] | ||
| 41 | #[used] | ||
| 42 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 43 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 44 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 45 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 46 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 47 | ]; | ||
| 48 | |||
| 49 | type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>; | ||
| 50 | |||
| 51 | struct MyType { | ||
| 52 | inner: u32, | ||
| 53 | } | ||
| 54 | |||
| 55 | static EXECUTOR_HI: InterruptExecutor = InterruptExecutor::new(); | ||
| 56 | static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | ||
| 57 | |||
| 58 | // Use Atomics for simple values | ||
| 59 | static ATOMIC: AtomicU32 = AtomicU32::new(0); | ||
| 60 | |||
| 61 | // Use blocking Mutex with Cell/RefCell for sharing non-async things | ||
| 62 | static MUTEX_BLOCKING: blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<MyType>> = | ||
| 63 | blocking_mutex::Mutex::new(RefCell::new(MyType { inner: 0 })); | ||
| 64 | |||
| 65 | bind_interrupts!(struct Irqs { | ||
| 66 | UART0_IRQ => InterruptHandler<UART0>; | ||
| 67 | }); | ||
| 68 | |||
| 69 | #[interrupt] | ||
| 70 | unsafe fn SWI_IRQ_0() { | ||
| 71 | EXECUTOR_HI.on_interrupt() | ||
| 72 | } | ||
| 73 | |||
| 74 | #[entry] | ||
| 75 | fn main() -> ! { | ||
| 76 | let p = embassy_rp::init(Default::default()); | ||
| 77 | info!("Here we go!"); | ||
| 78 | |||
| 79 | let uart = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, uart::Config::default()); | ||
| 80 | // Use the async Mutex for sharing async things (built-in interior mutability) | ||
| 81 | static UART: StaticCell<UartAsyncMutex> = StaticCell::new(); | ||
| 82 | let uart = UART.init(mutex::Mutex::new(uart)); | ||
| 83 | |||
| 84 | // High-priority executor: runs in interrupt mode | ||
| 85 | interrupt::SWI_IRQ_0.set_priority(Priority::P3); | ||
| 86 | let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); | ||
| 87 | spawner.must_spawn(task_a(uart)); | ||
| 88 | |||
| 89 | // Low priority executor: runs in thread mode | ||
| 90 | let executor = EXECUTOR_LOW.init(Executor::new()); | ||
| 91 | executor.run(|spawner| { | ||
| 92 | // No Mutex needed when sharing between tasks running on the same executor | ||
| 93 | |||
| 94 | // Use Cell for Copy-types | ||
| 95 | static CELL: ConstStaticCell<Cell<[u8; 4]>> = ConstStaticCell::new(Cell::new([0; 4])); | ||
| 96 | let cell = CELL.take(); | ||
| 97 | |||
| 98 | // Use RefCell for &mut access | ||
| 99 | static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); | ||
| 100 | let ref_cell = REF_CELL.take(); | ||
| 101 | |||
| 102 | spawner.must_spawn(task_b(uart, cell, ref_cell)); | ||
| 103 | spawner.must_spawn(task_c(cell, ref_cell)); | ||
| 104 | }); | ||
| 105 | } | ||
| 106 | |||
| 107 | #[embassy_executor::task] | ||
| 108 | async fn task_a(uart: &'static UartAsyncMutex) { | ||
| 109 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 110 | loop { | ||
| 111 | let random = RoscRng.next_u32(); | ||
| 112 | |||
| 113 | { | ||
| 114 | let mut uart = uart.lock().await; | ||
| 115 | uart.write(b"task a").await.unwrap(); | ||
| 116 | // The uart lock is released when it goes out of scope | ||
| 117 | } | ||
| 118 | |||
| 119 | ATOMIC.store(random, Ordering::Relaxed); | ||
| 120 | |||
| 121 | MUTEX_BLOCKING.lock(|x| x.borrow_mut().inner = random); | ||
| 122 | |||
| 123 | ticker.next().await; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | #[embassy_executor::task] | ||
| 128 | async fn task_b(uart: &'static UartAsyncMutex, cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell<MyType>) { | ||
| 129 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 130 | loop { | ||
| 131 | let random = RoscRng.next_u32(); | ||
| 132 | |||
| 133 | uart.lock().await.write(b"task b").await.unwrap(); | ||
| 134 | |||
| 135 | cell.set(random.to_be_bytes()); | ||
| 136 | |||
| 137 | ref_cell.borrow_mut().inner = random; | ||
| 138 | |||
| 139 | ticker.next().await; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | #[embassy_executor::task] | ||
| 144 | async fn task_c(cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell<MyType>) { | ||
| 145 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 146 | loop { | ||
| 147 | info!("======================="); | ||
| 148 | |||
| 149 | let atomic_val = ATOMIC.load(Ordering::Relaxed); | ||
| 150 | info!("atomic: {}", atomic_val); | ||
| 151 | |||
| 152 | MUTEX_BLOCKING.lock(|x| { | ||
| 153 | let val = x.borrow().inner; | ||
| 154 | info!("blocking mutex: {}", val); | ||
| 155 | }); | ||
| 156 | |||
| 157 | let cell_val = cell.get(); | ||
| 158 | info!("cell: {:?}", cell_val); | ||
| 159 | |||
| 160 | let ref_cell_val = ref_cell.borrow().inner; | ||
| 161 | info!("ref_cell: {:?}", ref_cell_val); | ||
| 162 | |||
| 163 | ticker.next().await; | ||
| 164 | } | ||
| 165 | } | ||
diff --git a/examples/rp23/src/bin/spi.rs b/examples/rp23/src/bin/spi.rs new file mode 100644 index 000000000..924873e60 --- /dev/null +++ b/examples/rp23/src/bin/spi.rs | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! Example for resistive touch sensor in Waveshare Pico-ResTouch | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::spi::Spi; | ||
| 12 | use embassy_rp::{gpio, spi}; | ||
| 13 | use gpio::{Level, Output}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | #[link_section = ".start_block"] | ||
| 17 | #[used] | ||
| 18 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 19 | |||
| 20 | // Program metadata for `picotool info` | ||
| 21 | #[link_section = ".bi_entries"] | ||
| 22 | #[used] | ||
| 23 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 24 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 25 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 26 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 27 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 28 | ]; | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(_spawner: Spawner) { | ||
| 32 | let p = embassy_rp::init(Default::default()); | ||
| 33 | info!("Hello World!"); | ||
| 34 | |||
| 35 | // Example for resistive touch sensor in Waveshare Pico-ResTouch | ||
| 36 | |||
| 37 | let miso = p.PIN_12; | ||
| 38 | let mosi = p.PIN_11; | ||
| 39 | let clk = p.PIN_10; | ||
| 40 | let touch_cs = p.PIN_16; | ||
| 41 | |||
| 42 | // create SPI | ||
| 43 | let mut config = spi::Config::default(); | ||
| 44 | config.frequency = 2_000_000; | ||
| 45 | let mut spi = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); | ||
| 46 | |||
| 47 | // Configure CS | ||
| 48 | let mut cs = Output::new(touch_cs, Level::Low); | ||
| 49 | |||
| 50 | loop { | ||
| 51 | cs.set_low(); | ||
| 52 | let mut buf = [0x90, 0x00, 0x00, 0xd0, 0x00, 0x00]; | ||
| 53 | spi.blocking_transfer_in_place(&mut buf).unwrap(); | ||
| 54 | cs.set_high(); | ||
| 55 | |||
| 56 | let x = (buf[1] as u32) << 5 | (buf[2] as u32) >> 3; | ||
| 57 | let y = (buf[4] as u32) << 5 | (buf[5] as u32) >> 3; | ||
| 58 | |||
| 59 | info!("touch: {=u32} {=u32}", x, y); | ||
| 60 | } | ||
| 61 | } | ||
diff --git a/examples/rp23/src/bin/spi_async.rs b/examples/rp23/src/bin/spi_async.rs new file mode 100644 index 000000000..4a74f991c --- /dev/null +++ b/examples/rp23/src/bin/spi_async.rs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! No specific hardware is specified in this example. If you connect pin 11 and 12 you should get the same data back. | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::block::ImageDef; | ||
| 10 | use embassy_rp::spi::{Config, Spi}; | ||
| 11 | use embassy_time::Timer; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | #[embassy_executor::main] | ||
| 29 | async fn main(_spawner: Spawner) { | ||
| 30 | let p = embassy_rp::init(Default::default()); | ||
| 31 | info!("Hello World!"); | ||
| 32 | |||
| 33 | let miso = p.PIN_12; | ||
| 34 | let mosi = p.PIN_11; | ||
| 35 | let clk = p.PIN_10; | ||
| 36 | |||
| 37 | let mut spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, 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 | spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); | ||
| 43 | info!("{:?}", rx_buf); | ||
| 44 | Timer::after_secs(1).await; | ||
| 45 | } | ||
| 46 | } | ||
diff --git a/examples/rp23/src/bin/spi_display.rs b/examples/rp23/src/bin/spi_display.rs new file mode 100644 index 000000000..71dd84658 --- /dev/null +++ b/examples/rp23/src/bin/spi_display.rs | |||
| @@ -0,0 +1,327 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch | ||
| 4 | //! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8) | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use core::cell::RefCell; | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig; | ||
| 13 | use embassy_executor::Spawner; | ||
| 14 | use embassy_rp::block::ImageDef; | ||
| 15 | use embassy_rp::gpio::{Level, Output}; | ||
| 16 | use embassy_rp::spi; | ||
| 17 | use embassy_rp::spi::{Blocking, Spi}; | ||
| 18 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 19 | use embassy_sync::blocking_mutex::Mutex; | ||
| 20 | use embassy_time::Delay; | ||
| 21 | use embedded_graphics::image::{Image, ImageRawLE}; | ||
| 22 | use embedded_graphics::mono_font::ascii::FONT_10X20; | ||
| 23 | use embedded_graphics::mono_font::MonoTextStyle; | ||
| 24 | use embedded_graphics::pixelcolor::Rgb565; | ||
| 25 | use embedded_graphics::prelude::*; | ||
| 26 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | ||
| 27 | use embedded_graphics::text::Text; | ||
| 28 | use st7789::{Orientation, ST7789}; | ||
| 29 | use {defmt_rtt as _, panic_probe as _}; | ||
| 30 | |||
| 31 | #[link_section = ".start_block"] | ||
| 32 | #[used] | ||
| 33 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 34 | |||
| 35 | // Program metadata for `picotool info` | ||
| 36 | #[link_section = ".bi_entries"] | ||
| 37 | #[used] | ||
| 38 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 39 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 40 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 41 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 42 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 43 | ]; | ||
| 44 | |||
| 45 | use crate::my_display_interface::SPIDeviceInterface; | ||
| 46 | use crate::touch::Touch; | ||
| 47 | |||
| 48 | const DISPLAY_FREQ: u32 = 64_000_000; | ||
| 49 | const TOUCH_FREQ: u32 = 200_000; | ||
| 50 | |||
| 51 | #[embassy_executor::main] | ||
| 52 | async fn main(_spawner: Spawner) { | ||
| 53 | let p = embassy_rp::init(Default::default()); | ||
| 54 | info!("Hello World!"); | ||
| 55 | |||
| 56 | let bl = p.PIN_13; | ||
| 57 | let rst = p.PIN_15; | ||
| 58 | let display_cs = p.PIN_9; | ||
| 59 | let dcx = p.PIN_8; | ||
| 60 | let miso = p.PIN_12; | ||
| 61 | let mosi = p.PIN_11; | ||
| 62 | let clk = p.PIN_10; | ||
| 63 | let touch_cs = p.PIN_16; | ||
| 64 | //let touch_irq = p.PIN_17; | ||
| 65 | |||
| 66 | // create SPI | ||
| 67 | let mut display_config = spi::Config::default(); | ||
| 68 | display_config.frequency = DISPLAY_FREQ; | ||
| 69 | display_config.phase = spi::Phase::CaptureOnSecondTransition; | ||
| 70 | display_config.polarity = spi::Polarity::IdleHigh; | ||
| 71 | let mut touch_config = spi::Config::default(); | ||
| 72 | touch_config.frequency = TOUCH_FREQ; | ||
| 73 | touch_config.phase = spi::Phase::CaptureOnSecondTransition; | ||
| 74 | touch_config.polarity = spi::Polarity::IdleHigh; | ||
| 75 | |||
| 76 | let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, touch_config.clone()); | ||
| 77 | let spi_bus: Mutex<NoopRawMutex, _> = Mutex::new(RefCell::new(spi)); | ||
| 78 | |||
| 79 | let display_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(display_cs, Level::High), display_config); | ||
| 80 | let touch_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(touch_cs, Level::High), touch_config); | ||
| 81 | |||
| 82 | let mut touch = Touch::new(touch_spi); | ||
| 83 | |||
| 84 | let dcx = Output::new(dcx, Level::Low); | ||
| 85 | let rst = Output::new(rst, Level::Low); | ||
| 86 | // dcx: 0 = command, 1 = data | ||
| 87 | |||
| 88 | // Enable LCD backlight | ||
| 89 | let _bl = Output::new(bl, Level::High); | ||
| 90 | |||
| 91 | // display interface abstraction from SPI and DC | ||
| 92 | let di = SPIDeviceInterface::new(display_spi, dcx); | ||
| 93 | |||
| 94 | // create driver | ||
| 95 | let mut display = ST7789::new(di, rst, 240, 320); | ||
| 96 | |||
| 97 | // initialize | ||
| 98 | display.init(&mut Delay).unwrap(); | ||
| 99 | |||
| 100 | // set default orientation | ||
| 101 | display.set_orientation(Orientation::Landscape).unwrap(); | ||
| 102 | |||
| 103 | display.clear(Rgb565::BLACK).unwrap(); | ||
| 104 | |||
| 105 | let raw_image_data = ImageRawLE::new(include_bytes!("../../assets/ferris.raw"), 86); | ||
| 106 | let ferris = Image::new(&raw_image_data, Point::new(34, 68)); | ||
| 107 | |||
| 108 | // Display the image | ||
| 109 | ferris.draw(&mut display).unwrap(); | ||
| 110 | |||
| 111 | let style = MonoTextStyle::new(&FONT_10X20, Rgb565::GREEN); | ||
| 112 | Text::new( | ||
| 113 | "Hello embedded_graphics \n + embassy + RP2040!", | ||
| 114 | Point::new(20, 200), | ||
| 115 | style, | ||
| 116 | ) | ||
| 117 | .draw(&mut display) | ||
| 118 | .unwrap(); | ||
| 119 | |||
| 120 | loop { | ||
| 121 | if let Some((x, y)) = touch.read() { | ||
| 122 | let style = PrimitiveStyleBuilder::new().fill_color(Rgb565::BLUE).build(); | ||
| 123 | |||
| 124 | Rectangle::new(Point::new(x - 1, y - 1), Size::new(3, 3)) | ||
| 125 | .into_styled(style) | ||
| 126 | .draw(&mut display) | ||
| 127 | .unwrap(); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | /// Driver for the XPT2046 resistive touchscreen sensor | ||
| 133 | mod touch { | ||
| 134 | use embedded_hal_1::spi::{Operation, SpiDevice}; | ||
| 135 | |||
| 136 | struct Calibration { | ||
| 137 | x1: i32, | ||
| 138 | x2: i32, | ||
| 139 | y1: i32, | ||
| 140 | y2: i32, | ||
| 141 | sx: i32, | ||
| 142 | sy: i32, | ||
| 143 | } | ||
| 144 | |||
| 145 | const CALIBRATION: Calibration = Calibration { | ||
| 146 | x1: 3880, | ||
| 147 | x2: 340, | ||
| 148 | y1: 262, | ||
| 149 | y2: 3850, | ||
| 150 | sx: 320, | ||
| 151 | sy: 240, | ||
| 152 | }; | ||
| 153 | |||
| 154 | pub struct Touch<SPI: SpiDevice> { | ||
| 155 | spi: SPI, | ||
| 156 | } | ||
| 157 | |||
| 158 | impl<SPI> Touch<SPI> | ||
| 159 | where | ||
| 160 | SPI: SpiDevice, | ||
| 161 | { | ||
| 162 | pub fn new(spi: SPI) -> Self { | ||
| 163 | Self { spi } | ||
| 164 | } | ||
| 165 | |||
| 166 | pub fn read(&mut self) -> Option<(i32, i32)> { | ||
| 167 | let mut x = [0; 2]; | ||
| 168 | let mut y = [0; 2]; | ||
| 169 | self.spi | ||
| 170 | .transaction(&mut [ | ||
| 171 | Operation::Write(&[0x90]), | ||
| 172 | Operation::Read(&mut x), | ||
| 173 | Operation::Write(&[0xd0]), | ||
| 174 | Operation::Read(&mut y), | ||
| 175 | ]) | ||
| 176 | .unwrap(); | ||
| 177 | |||
| 178 | let x = (u16::from_be_bytes(x) >> 3) as i32; | ||
| 179 | let y = (u16::from_be_bytes(y) >> 3) as i32; | ||
| 180 | |||
| 181 | let cal = &CALIBRATION; | ||
| 182 | |||
| 183 | let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); | ||
| 184 | let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); | ||
| 185 | if x == 0 && y == 0 { | ||
| 186 | None | ||
| 187 | } else { | ||
| 188 | Some((x, y)) | ||
| 189 | } | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | mod my_display_interface { | ||
| 195 | use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; | ||
| 196 | use embedded_hal_1::digital::OutputPin; | ||
| 197 | use embedded_hal_1::spi::SpiDevice; | ||
| 198 | |||
| 199 | /// SPI display interface. | ||
| 200 | /// | ||
| 201 | /// This combines the SPI peripheral and a data/command pin | ||
| 202 | pub struct SPIDeviceInterface<SPI, DC> { | ||
| 203 | spi: SPI, | ||
| 204 | dc: DC, | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<SPI, DC> SPIDeviceInterface<SPI, DC> | ||
| 208 | where | ||
| 209 | SPI: SpiDevice, | ||
| 210 | DC: OutputPin, | ||
| 211 | { | ||
| 212 | /// Create new SPI interface for communciation with a display driver | ||
| 213 | pub fn new(spi: SPI, dc: DC) -> Self { | ||
| 214 | Self { spi, dc } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | impl<SPI, DC> WriteOnlyDataCommand for SPIDeviceInterface<SPI, DC> | ||
| 219 | where | ||
| 220 | SPI: SpiDevice, | ||
| 221 | DC: OutputPin, | ||
| 222 | { | ||
| 223 | fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { | ||
| 224 | // 1 = data, 0 = command | ||
| 225 | self.dc.set_low().map_err(|_| DisplayError::DCError)?; | ||
| 226 | |||
| 227 | send_u8(&mut self.spi, cmds).map_err(|_| DisplayError::BusWriteError)?; | ||
| 228 | Ok(()) | ||
| 229 | } | ||
| 230 | |||
| 231 | fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> { | ||
| 232 | // 1 = data, 0 = command | ||
| 233 | self.dc.set_high().map_err(|_| DisplayError::DCError)?; | ||
| 234 | |||
| 235 | send_u8(&mut self.spi, buf).map_err(|_| DisplayError::BusWriteError)?; | ||
| 236 | Ok(()) | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | fn send_u8<T: SpiDevice>(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { | ||
| 241 | match words { | ||
| 242 | DataFormat::U8(slice) => spi.write(slice), | ||
| 243 | DataFormat::U16(slice) => { | ||
| 244 | use byte_slice_cast::*; | ||
| 245 | spi.write(slice.as_byte_slice()) | ||
| 246 | } | ||
| 247 | DataFormat::U16LE(slice) => { | ||
| 248 | use byte_slice_cast::*; | ||
| 249 | for v in slice.as_mut() { | ||
| 250 | *v = v.to_le(); | ||
| 251 | } | ||
| 252 | spi.write(slice.as_byte_slice()) | ||
| 253 | } | ||
| 254 | DataFormat::U16BE(slice) => { | ||
| 255 | use byte_slice_cast::*; | ||
| 256 | for v in slice.as_mut() { | ||
| 257 | *v = v.to_be(); | ||
| 258 | } | ||
| 259 | spi.write(slice.as_byte_slice()) | ||
| 260 | } | ||
| 261 | DataFormat::U8Iter(iter) => { | ||
| 262 | let mut buf = [0; 32]; | ||
| 263 | let mut i = 0; | ||
| 264 | |||
| 265 | for v in iter.into_iter() { | ||
| 266 | buf[i] = v; | ||
| 267 | i += 1; | ||
| 268 | |||
| 269 | if i == buf.len() { | ||
| 270 | spi.write(&buf)?; | ||
| 271 | i = 0; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | if i > 0 { | ||
| 276 | spi.write(&buf[..i])?; | ||
| 277 | } | ||
| 278 | |||
| 279 | Ok(()) | ||
| 280 | } | ||
| 281 | DataFormat::U16LEIter(iter) => { | ||
| 282 | use byte_slice_cast::*; | ||
| 283 | let mut buf = [0; 32]; | ||
| 284 | let mut i = 0; | ||
| 285 | |||
| 286 | for v in iter.map(u16::to_le) { | ||
| 287 | buf[i] = v; | ||
| 288 | i += 1; | ||
| 289 | |||
| 290 | if i == buf.len() { | ||
| 291 | spi.write(&buf.as_byte_slice())?; | ||
| 292 | i = 0; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | if i > 0 { | ||
| 297 | spi.write(&buf[..i].as_byte_slice())?; | ||
| 298 | } | ||
| 299 | |||
| 300 | Ok(()) | ||
| 301 | } | ||
| 302 | DataFormat::U16BEIter(iter) => { | ||
| 303 | use byte_slice_cast::*; | ||
| 304 | let mut buf = [0; 64]; | ||
| 305 | let mut i = 0; | ||
| 306 | let len = buf.len(); | ||
| 307 | |||
| 308 | for v in iter.map(u16::to_be) { | ||
| 309 | buf[i] = v; | ||
| 310 | i += 1; | ||
| 311 | |||
| 312 | if i == len { | ||
| 313 | spi.write(&buf.as_byte_slice())?; | ||
| 314 | i = 0; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | if i > 0 { | ||
| 319 | spi.write(&buf[..i].as_byte_slice())?; | ||
| 320 | } | ||
| 321 | |||
| 322 | Ok(()) | ||
| 323 | } | ||
| 324 | _ => unimplemented!(), | ||
| 325 | } | ||
| 326 | } | ||
| 327 | } | ||
diff --git a/examples/rp23/src/bin/spi_sdmmc.rs b/examples/rp23/src/bin/spi_sdmmc.rs new file mode 100644 index 000000000..dabf41ab8 --- /dev/null +++ b/examples/rp23/src/bin/spi_sdmmc.rs | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | //! This example shows how to use `embedded-sdmmc` with the RP2040 chip, over SPI. | ||
| 2 | //! | ||
| 3 | //! The example will attempt to read a file `MY_FILE.TXT` from the root directory | ||
| 4 | //! of the SD card and print its contents. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_embedded_hal::SetConfig; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_rp::block::ImageDef; | ||
| 13 | use embassy_rp::spi::Spi; | ||
| 14 | use embassy_rp::{gpio, spi}; | ||
| 15 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 16 | use embedded_sdmmc::sdcard::{DummyCsPin, SdCard}; | ||
| 17 | use gpio::{Level, Output}; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | #[link_section = ".start_block"] | ||
| 21 | #[used] | ||
| 22 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 23 | |||
| 24 | // Program metadata for `picotool info` | ||
| 25 | #[link_section = ".bi_entries"] | ||
| 26 | #[used] | ||
| 27 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 28 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 29 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 30 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 31 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 32 | ]; | ||
| 33 | |||
| 34 | struct DummyTimesource(); | ||
| 35 | |||
| 36 | impl embedded_sdmmc::TimeSource for DummyTimesource { | ||
| 37 | fn get_timestamp(&self) -> embedded_sdmmc::Timestamp { | ||
| 38 | embedded_sdmmc::Timestamp { | ||
| 39 | year_since_1970: 0, | ||
| 40 | zero_indexed_month: 0, | ||
| 41 | zero_indexed_day: 0, | ||
| 42 | hours: 0, | ||
| 43 | minutes: 0, | ||
| 44 | seconds: 0, | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | #[embassy_executor::main] | ||
| 50 | async fn main(_spawner: Spawner) { | ||
| 51 | embassy_rp::pac::SIO.spinlock(31).write_value(1); | ||
| 52 | let p = embassy_rp::init(Default::default()); | ||
| 53 | |||
| 54 | // SPI clock needs to be running at <= 400kHz during initialization | ||
| 55 | let mut config = spi::Config::default(); | ||
| 56 | config.frequency = 400_000; | ||
| 57 | let spi = Spi::new_blocking(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, config); | ||
| 58 | // Use a dummy cs pin here, for embedded-hal SpiDevice compatibility reasons | ||
| 59 | let spi_dev = ExclusiveDevice::new_no_delay(spi, DummyCsPin); | ||
| 60 | // Real cs pin | ||
| 61 | let cs = Output::new(p.PIN_16, Level::High); | ||
| 62 | |||
| 63 | let sdcard = SdCard::new(spi_dev, cs, embassy_time::Delay); | ||
| 64 | info!("Card size is {} bytes", sdcard.num_bytes().unwrap()); | ||
| 65 | |||
| 66 | // Now that the card is initialized, the SPI clock can go faster | ||
| 67 | let mut config = spi::Config::default(); | ||
| 68 | config.frequency = 16_000_000; | ||
| 69 | sdcard.spi(|dev| dev.bus_mut().set_config(&config)).ok(); | ||
| 70 | |||
| 71 | // Now let's look for volumes (also known as partitions) on our block device. | ||
| 72 | // To do this we need a Volume Manager. It will take ownership of the block device. | ||
| 73 | let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, DummyTimesource()); | ||
| 74 | |||
| 75 | // Try and access Volume 0 (i.e. the first partition). | ||
| 76 | // The volume object holds information about the filesystem on that volume. | ||
| 77 | let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0)).unwrap(); | ||
| 78 | info!("Volume 0: {:?}", defmt::Debug2Format(&volume0)); | ||
| 79 | |||
| 80 | // Open the root directory (mutably borrows from the volume). | ||
| 81 | let mut root_dir = volume0.open_root_dir().unwrap(); | ||
| 82 | |||
| 83 | // Open a file called "MY_FILE.TXT" in the root directory | ||
| 84 | // This mutably borrows the directory. | ||
| 85 | let mut my_file = root_dir | ||
| 86 | .open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly) | ||
| 87 | .unwrap(); | ||
| 88 | |||
| 89 | // Print the contents of the file | ||
| 90 | while !my_file.is_eof() { | ||
| 91 | let mut buf = [0u8; 32]; | ||
| 92 | if let Ok(n) = my_file.read(&mut buf) { | ||
| 93 | info!("{:a}", buf[..n]); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | loop {} | ||
| 98 | } | ||
diff --git a/examples/rp23/src/bin/uart.rs b/examples/rp23/src/bin/uart.rs new file mode 100644 index 000000000..0ffe0b293 --- /dev/null +++ b/examples/rp23/src/bin/uart.rs | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! No specific hardware is specified in this example. Only output on pin 0 is tested. | ||
| 4 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 5 | //! with its UART port. | ||
| 6 | |||
| 7 | #![no_std] | ||
| 8 | #![no_main] | ||
| 9 | |||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_rp::block::ImageDef; | ||
| 12 | use embassy_rp::uart; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | #[link_section = ".start_block"] | ||
| 16 | #[used] | ||
| 17 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 18 | |||
| 19 | // Program metadata for `picotool info` | ||
| 20 | #[link_section = ".bi_entries"] | ||
| 21 | #[used] | ||
| 22 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 23 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 24 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 25 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 26 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 27 | ]; | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | let p = embassy_rp::init(Default::default()); | ||
| 32 | let config = uart::Config::default(); | ||
| 33 | let mut uart = uart::Uart::new_blocking(p.UART1, p.PIN_4, p.PIN_5, config); | ||
| 34 | uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap(); | ||
| 35 | |||
| 36 | loop { | ||
| 37 | uart.blocking_write("hello there!\r\n".as_bytes()).unwrap(); | ||
| 38 | cortex_m::asm::delay(1_000_000); | ||
| 39 | } | ||
| 40 | } | ||
diff --git a/examples/rp23/src/bin/uart_buffered_split.rs b/examples/rp23/src/bin/uart_buffered_split.rs new file mode 100644 index 000000000..4e69a20c4 --- /dev/null +++ b/examples/rp23/src/bin/uart_buffered_split.rs | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! No specific hardware is specified in this example. If you connect pin 0 and 1 you should get the same data back. | ||
| 4 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 5 | //! with its UART port. | ||
| 6 | |||
| 7 | #![no_std] | ||
| 8 | #![no_main] | ||
| 9 | |||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_rp::bind_interrupts; | ||
| 13 | use embassy_rp::block::ImageDef; | ||
| 14 | use embassy_rp::peripherals::UART0; | ||
| 15 | use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; | ||
| 16 | use embassy_time::Timer; | ||
| 17 | use embedded_io_async::{Read, Write}; | ||
| 18 | use static_cell::StaticCell; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | #[link_section = ".start_block"] | ||
| 22 | #[used] | ||
| 23 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 24 | |||
| 25 | // Program metadata for `picotool info` | ||
| 26 | #[link_section = ".bi_entries"] | ||
| 27 | #[used] | ||
| 28 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 29 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 30 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 31 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 32 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 33 | ]; | ||
| 34 | |||
| 35 | bind_interrupts!(struct Irqs { | ||
| 36 | UART0_IRQ => BufferedInterruptHandler<UART0>; | ||
| 37 | }); | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(spawner: Spawner) { | ||
| 41 | let p = embassy_rp::init(Default::default()); | ||
| 42 | let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); | ||
| 43 | |||
| 44 | static TX_BUF: StaticCell<[u8; 16]> = StaticCell::new(); | ||
| 45 | let tx_buf = &mut TX_BUF.init([0; 16])[..]; | ||
| 46 | static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new(); | ||
| 47 | let rx_buf = &mut RX_BUF.init([0; 16])[..]; | ||
| 48 | let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); | ||
| 49 | let (mut tx, rx) = uart.split(); | ||
| 50 | |||
| 51 | unwrap!(spawner.spawn(reader(rx))); | ||
| 52 | |||
| 53 | info!("Writing..."); | ||
| 54 | loop { | ||
| 55 | let data = [ | ||
| 56 | 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, | ||
| 57 | 29, 30, 31, | ||
| 58 | ]; | ||
| 59 | info!("TX {:?}", data); | ||
| 60 | tx.write_all(&data).await.unwrap(); | ||
| 61 | Timer::after_secs(1).await; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | #[embassy_executor::task] | ||
| 66 | async fn reader(mut rx: BufferedUartRx<'static, UART0>) { | ||
| 67 | info!("Reading..."); | ||
| 68 | loop { | ||
| 69 | let mut buf = [0; 31]; | ||
| 70 | rx.read_exact(&mut buf).await.unwrap(); | ||
| 71 | info!("RX {:?}", buf); | ||
| 72 | } | ||
| 73 | } | ||
diff --git a/examples/rp23/src/bin/uart_r503.rs b/examples/rp23/src/bin/uart_r503.rs new file mode 100644 index 000000000..5ac8839e3 --- /dev/null +++ b/examples/rp23/src/bin/uart_r503.rs | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{debug, error, info}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_rp::bind_interrupts; | ||
| 7 | use embassy_rp::block::ImageDef; | ||
| 8 | use embassy_rp::peripherals::UART0; | ||
| 9 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; | ||
| 10 | use embassy_time::{with_timeout, Duration, Timer}; | ||
| 11 | use heapless::Vec; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[link_section = ".start_block"] | ||
| 15 | #[used] | ||
| 16 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 17 | |||
| 18 | // Program metadata for `picotool info` | ||
| 19 | #[link_section = ".bi_entries"] | ||
| 20 | #[used] | ||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 26 | ]; | ||
| 27 | |||
| 28 | bind_interrupts!(pub struct Irqs { | ||
| 29 | UART0_IRQ => UARTInterruptHandler<UART0>; | ||
| 30 | }); | ||
| 31 | |||
| 32 | const START: u16 = 0xEF01; | ||
| 33 | const ADDRESS: u32 = 0xFFFFFFFF; | ||
| 34 | |||
| 35 | // ================================================================================ | ||
| 36 | |||
| 37 | // Data package format | ||
| 38 | // Name Length Description | ||
| 39 | // ========================================================================================================== | ||
| 40 | // Start 2 bytes Fixed value of 0xEF01; High byte transferred first. | ||
| 41 | // Address 4 bytes Default value is 0xFFFFFFFF, which can be modified by command. | ||
| 42 | // High byte transferred first and at wrong adder value, module | ||
| 43 | // will reject to transfer. | ||
| 44 | // PID 1 byte 01H Command packet; | ||
| 45 | // 02H Data packet; Data packet shall not appear alone in executing | ||
| 46 | // processs, must follow command packet or acknowledge packet. | ||
| 47 | // 07H Acknowledge packet; | ||
| 48 | // 08H End of Data packet. | ||
| 49 | // LENGTH 2 bytes Refers to the length of package content (command packets and data packets) | ||
| 50 | // plus the length of Checksum (2 bytes). Unit is byte. Max length is 256 bytes. | ||
| 51 | // And high byte is transferred first. | ||
| 52 | // DATA - It can be commands, data, command’s parameters, acknowledge result, etc. | ||
| 53 | // (fingerprint character value, template are all deemed as data); | ||
| 54 | // SUM 2 bytes The arithmetic sum of package identifier, package length and all package | ||
| 55 | // contens. Overflowing bits are omitted. high byte is transferred first. | ||
| 56 | |||
| 57 | // ================================================================================ | ||
| 58 | |||
| 59 | // Checksum is calculated on 'length (2 bytes) + data (??)'. | ||
| 60 | fn compute_checksum(buf: Vec<u8, 32>) -> u16 { | ||
| 61 | let mut checksum = 0u16; | ||
| 62 | |||
| 63 | let check_end = buf.len(); | ||
| 64 | let checked_bytes = &buf[6..check_end]; | ||
| 65 | for byte in checked_bytes { | ||
| 66 | checksum += (*byte) as u16; | ||
| 67 | } | ||
| 68 | return checksum; | ||
| 69 | } | ||
| 70 | |||
| 71 | #[embassy_executor::main] | ||
| 72 | async fn main(_spawner: Spawner) { | ||
| 73 | info!("Start"); | ||
| 74 | |||
| 75 | let p = embassy_rp::init(Default::default()); | ||
| 76 | |||
| 77 | // Initialize the fingerprint scanner. | ||
| 78 | let mut config = Config::default(); | ||
| 79 | config.baudrate = 57600; | ||
| 80 | config.stop_bits = StopBits::STOP1; | ||
| 81 | config.data_bits = DataBits::DataBits8; | ||
| 82 | config.parity = Parity::ParityNone; | ||
| 83 | |||
| 84 | let (uart, tx_pin, tx_dma, rx_pin, rx_dma) = (p.UART0, p.PIN_16, p.DMA_CH0, p.PIN_17, p.DMA_CH1); | ||
| 85 | let uart = Uart::new(uart, tx_pin, rx_pin, Irqs, tx_dma, rx_dma, config); | ||
| 86 | let (mut tx, mut rx) = uart.split(); | ||
| 87 | |||
| 88 | let mut vec_buf: Vec<u8, 32> = heapless::Vec::new(); | ||
| 89 | let mut data: Vec<u8, 32> = heapless::Vec::new(); | ||
| 90 | |||
| 91 | let mut speeds: Vec<u8, 3> = heapless::Vec::new(); | ||
| 92 | let _ = speeds.push(0xC8); // Slow | ||
| 93 | let _ = speeds.push(0x20); // Medium | ||
| 94 | let _ = speeds.push(0x02); // Fast | ||
| 95 | |||
| 96 | // Cycle through the three colours Red, Blue and Purple forever. | ||
| 97 | loop { | ||
| 98 | for colour in 1..=3 { | ||
| 99 | for speed in &speeds { | ||
| 100 | // Set the data first, because the length is dependent on that. | ||
| 101 | // However, we write the length bits before we do the data. | ||
| 102 | data.clear(); | ||
| 103 | let _ = data.push(0x01); // ctrl=Breathing light | ||
| 104 | let _ = data.push(*speed); | ||
| 105 | let _ = data.push(colour as u8); // colour=Red, Blue, Purple | ||
| 106 | let _ = data.push(0x00); // times=Infinite | ||
| 107 | |||
| 108 | // Clear buffers | ||
| 109 | vec_buf.clear(); | ||
| 110 | |||
| 111 | // START | ||
| 112 | let _ = vec_buf.extend_from_slice(&START.to_be_bytes()[..]); | ||
| 113 | |||
| 114 | // ADDRESS | ||
| 115 | let _ = vec_buf.extend_from_slice(&ADDRESS.to_be_bytes()[..]); | ||
| 116 | |||
| 117 | // PID | ||
| 118 | let _ = vec_buf.extend_from_slice(&[0x01]); | ||
| 119 | |||
| 120 | // LENGTH | ||
| 121 | let len: u16 = (1 + data.len() + 2).try_into().unwrap(); | ||
| 122 | let _ = vec_buf.extend_from_slice(&len.to_be_bytes()[..]); | ||
| 123 | |||
| 124 | // COMMAND | ||
| 125 | let _ = vec_buf.push(0x35); // Command: AuraLedConfig | ||
| 126 | |||
| 127 | // DATA | ||
| 128 | let _ = vec_buf.extend_from_slice(&data); | ||
| 129 | |||
| 130 | // SUM | ||
| 131 | let chk = compute_checksum(vec_buf.clone()); | ||
| 132 | let _ = vec_buf.extend_from_slice(&chk.to_be_bytes()[..]); | ||
| 133 | |||
| 134 | // ===== | ||
| 135 | |||
| 136 | // Send command buffer. | ||
| 137 | let data_write: [u8; 16] = vec_buf.clone().into_array().unwrap(); | ||
| 138 | debug!(" write='{:?}'", data_write[..]); | ||
| 139 | match tx.write(&data_write).await { | ||
| 140 | Ok(..) => info!("Write successful."), | ||
| 141 | Err(e) => error!("Write error: {:?}", e), | ||
| 142 | } | ||
| 143 | |||
| 144 | // ===== | ||
| 145 | |||
| 146 | // Read command buffer. | ||
| 147 | let mut read_buf: [u8; 1] = [0; 1]; // Can only read one byte at a time! | ||
| 148 | let mut data_read: Vec<u8, 32> = heapless::Vec::new(); // Save buffer. | ||
| 149 | |||
| 150 | info!("Attempting read."); | ||
| 151 | loop { | ||
| 152 | // Some commands, like `Img2Tz()` needs longer, but we hard-code this to 200ms | ||
| 153 | // for this command. | ||
| 154 | match with_timeout(Duration::from_millis(200), rx.read(&mut read_buf)).await { | ||
| 155 | Ok(..) => { | ||
| 156 | // Extract and save read byte. | ||
| 157 | debug!(" r='{=u8:#04x}H' ({:03}D)", read_buf[0], read_buf[0]); | ||
| 158 | let _ = data_read.push(read_buf[0]).unwrap(); | ||
| 159 | } | ||
| 160 | Err(..) => break, // TimeoutError -> Ignore. | ||
| 161 | } | ||
| 162 | } | ||
| 163 | info!("Read successful"); | ||
| 164 | debug!(" read='{:?}'", data_read[..]); | ||
| 165 | |||
| 166 | Timer::after_secs(3).await; | ||
| 167 | info!("Changing speed."); | ||
| 168 | } | ||
| 169 | |||
| 170 | info!("Changing colour."); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | } | ||
diff --git a/examples/rp23/src/bin/uart_unidir.rs b/examples/rp23/src/bin/uart_unidir.rs new file mode 100644 index 000000000..988e44a79 --- /dev/null +++ b/examples/rp23/src/bin/uart_unidir.rs | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! Test TX-only and RX-only on two different UARTs. You need to connect GPIO0 to GPIO5 for | ||
| 4 | //! this to work | ||
| 5 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 6 | //! with its UART port. | ||
| 7 | |||
| 8 | #![no_std] | ||
| 9 | #![no_main] | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use embassy_executor::Spawner; | ||
| 13 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::block::ImageDef; | ||
| 15 | use embassy_rp::peripherals::UART1; | ||
| 16 | use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx}; | ||
| 17 | use embassy_time::Timer; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | #[link_section = ".start_block"] | ||
| 21 | #[used] | ||
| 22 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 23 | |||
| 24 | // Program metadata for `picotool info` | ||
| 25 | #[link_section = ".bi_entries"] | ||
| 26 | #[used] | ||
| 27 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 28 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 29 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 30 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 31 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 32 | ]; | ||
| 33 | |||
| 34 | bind_interrupts!(struct Irqs { | ||
| 35 | UART1_IRQ => InterruptHandler<UART1>; | ||
| 36 | }); | ||
| 37 | |||
| 38 | #[embassy_executor::main] | ||
| 39 | async fn main(spawner: Spawner) { | ||
| 40 | let p = embassy_rp::init(Default::default()); | ||
| 41 | |||
| 42 | let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); | ||
| 43 | let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); | ||
| 44 | |||
| 45 | unwrap!(spawner.spawn(reader(uart_rx))); | ||
| 46 | |||
| 47 | info!("Writing..."); | ||
| 48 | loop { | ||
| 49 | let data = [1u8, 2, 3, 4, 5, 6, 7, 8]; | ||
| 50 | info!("TX {:?}", data); | ||
| 51 | uart_tx.write(&data).await.unwrap(); | ||
| 52 | Timer::after_secs(1).await; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | #[embassy_executor::task] | ||
| 57 | async fn reader(mut rx: UartRx<'static, UART1, Async>) { | ||
| 58 | info!("Reading..."); | ||
| 59 | loop { | ||
| 60 | // read a total of 4 transmissions (32 / 8) and then print the result | ||
| 61 | let mut buf = [0; 32]; | ||
| 62 | rx.read(&mut buf).await.unwrap(); | ||
| 63 | info!("RX {:?}", buf); | ||
| 64 | } | ||
| 65 | } | ||
diff --git a/examples/rp23/src/bin/usb_webusb.rs b/examples/rp23/src/bin/usb_webusb.rs new file mode 100644 index 000000000..3ade2226b --- /dev/null +++ b/examples/rp23/src/bin/usb_webusb.rs | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | //! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! This creates a WebUSB capable device that echoes data back to the host. | ||
| 4 | //! | ||
| 5 | //! To test this in the browser (ideally host this on localhost:8080, to test the landing page | ||
| 6 | //! feature): | ||
| 7 | //! ```js | ||
| 8 | //! (async () => { | ||
| 9 | //! const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0xf569 }] }); | ||
| 10 | //! await device.open(); | ||
| 11 | //! await device.claimInterface(1); | ||
| 12 | //! device.transferIn(1, 64).then(data => console.log(data)); | ||
| 13 | //! await device.transferOut(1, new Uint8Array([1,2,3])); | ||
| 14 | //! })(); | ||
| 15 | //! ``` | ||
| 16 | |||
| 17 | #![no_std] | ||
| 18 | #![no_main] | ||
| 19 | |||
| 20 | use defmt::info; | ||
| 21 | use embassy_executor::Spawner; | ||
| 22 | use embassy_futures::join::join; | ||
| 23 | use embassy_rp::bind_interrupts; | ||
| 24 | use embassy_rp::block::ImageDef; | ||
| 25 | use embassy_rp::peripherals::USB; | ||
| 26 | use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; | ||
| 27 | use embassy_usb::class::web_usb::{Config as WebUsbConfig, State, Url, WebUsb}; | ||
| 28 | use embassy_usb::driver::{Driver, Endpoint, EndpointIn, EndpointOut}; | ||
| 29 | use embassy_usb::msos::{self, windows_version}; | ||
| 30 | use embassy_usb::{Builder, Config}; | ||
| 31 | use {defmt_rtt as _, panic_probe as _}; | ||
| 32 | |||
| 33 | #[link_section = ".start_block"] | ||
| 34 | #[used] | ||
| 35 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 36 | |||
| 37 | // Program metadata for `picotool info` | ||
| 38 | #[link_section = ".bi_entries"] | ||
| 39 | #[used] | ||
| 40 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 41 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 42 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 43 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 44 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 45 | ]; | ||
| 46 | |||
| 47 | bind_interrupts!(struct Irqs { | ||
| 48 | USBCTRL_IRQ => InterruptHandler<USB>; | ||
| 49 | }); | ||
| 50 | |||
| 51 | // This is a randomly generated GUID to allow clients on Windows to find our device | ||
| 52 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{AFB9A6FB-30BA-44BC-9232-806CFC875321}"]; | ||
| 53 | |||
| 54 | #[embassy_executor::main] | ||
| 55 | async fn main(_spawner: Spawner) { | ||
| 56 | let p = embassy_rp::init(Default::default()); | ||
| 57 | |||
| 58 | // Create the driver, from the HAL. | ||
| 59 | let driver = UsbDriver::new(p.USB, Irqs); | ||
| 60 | |||
| 61 | // Create embassy-usb Config | ||
| 62 | let mut config = Config::new(0xf569, 0x0001); | ||
| 63 | config.manufacturer = Some("Embassy"); | ||
| 64 | config.product = Some("WebUSB example"); | ||
| 65 | config.serial_number = Some("12345678"); | ||
| 66 | config.max_power = 100; | ||
| 67 | config.max_packet_size_0 = 64; | ||
| 68 | |||
| 69 | // Required for windows compatibility. | ||
| 70 | // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help | ||
| 71 | config.device_class = 0xff; | ||
| 72 | config.device_sub_class = 0x00; | ||
| 73 | config.device_protocol = 0x00; | ||
| 74 | |||
| 75 | // Create embassy-usb DeviceBuilder using the driver and config. | ||
| 76 | // It needs some buffers for building the descriptors. | ||
| 77 | let mut config_descriptor = [0; 256]; | ||
| 78 | let mut bos_descriptor = [0; 256]; | ||
| 79 | let mut control_buf = [0; 64]; | ||
| 80 | let mut msos_descriptor = [0; 256]; | ||
| 81 | |||
| 82 | let webusb_config = WebUsbConfig { | ||
| 83 | max_packet_size: 64, | ||
| 84 | vendor_code: 1, | ||
| 85 | // If defined, shows a landing page which the device manufacturer would like the user to visit in order to control their device. Suggest the user to navigate to this URL when the device is connected. | ||
| 86 | landing_url: Some(Url::new("http://localhost:8080")), | ||
| 87 | }; | ||
| 88 | |||
| 89 | let mut state = State::new(); | ||
| 90 | |||
| 91 | let mut builder = Builder::new( | ||
| 92 | driver, | ||
| 93 | config, | ||
| 94 | &mut config_descriptor, | ||
| 95 | &mut bos_descriptor, | ||
| 96 | &mut msos_descriptor, | ||
| 97 | &mut control_buf, | ||
| 98 | ); | ||
| 99 | |||
| 100 | // Add the Microsoft OS Descriptor (MSOS/MOD) descriptor. | ||
| 101 | // We tell Windows that this entire device is compatible with the "WINUSB" feature, | ||
| 102 | // which causes it to use the built-in WinUSB driver automatically, which in turn | ||
| 103 | // can be used by libusb/rusb software without needing a custom driver or INF file. | ||
| 104 | // In principle you might want to call msos_feature() just on a specific function, | ||
| 105 | // if your device also has other functions that still use standard class drivers. | ||
| 106 | builder.msos_descriptor(windows_version::WIN8_1, 0); | ||
| 107 | builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
| 108 | builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
| 109 | "DeviceInterfaceGUIDs", | ||
| 110 | msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
| 111 | )); | ||
| 112 | |||
| 113 | // Create classes on the builder (WebUSB just needs some setup, but doesn't return anything) | ||
| 114 | WebUsb::configure(&mut builder, &mut state, &webusb_config); | ||
| 115 | // Create some USB bulk endpoints for testing. | ||
| 116 | let mut endpoints = WebEndpoints::new(&mut builder, &webusb_config); | ||
| 117 | |||
| 118 | // Build the builder. | ||
| 119 | let mut usb = builder.build(); | ||
| 120 | |||
| 121 | // Run the USB device. | ||
| 122 | let usb_fut = usb.run(); | ||
| 123 | |||
| 124 | // Do some WebUSB transfers. | ||
| 125 | let webusb_fut = async { | ||
| 126 | loop { | ||
| 127 | endpoints.wait_connected().await; | ||
| 128 | info!("Connected"); | ||
| 129 | endpoints.echo().await; | ||
| 130 | } | ||
| 131 | }; | ||
| 132 | |||
| 133 | // Run everything concurrently. | ||
| 134 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. | ||
| 135 | join(usb_fut, webusb_fut).await; | ||
| 136 | } | ||
| 137 | |||
| 138 | struct WebEndpoints<'d, D: Driver<'d>> { | ||
| 139 | write_ep: D::EndpointIn, | ||
| 140 | read_ep: D::EndpointOut, | ||
| 141 | } | ||
| 142 | |||
| 143 | impl<'d, D: Driver<'d>> WebEndpoints<'d, D> { | ||
| 144 | fn new(builder: &mut Builder<'d, D>, config: &'d WebUsbConfig<'d>) -> Self { | ||
| 145 | let mut func = builder.function(0xff, 0x00, 0x00); | ||
| 146 | let mut iface = func.interface(); | ||
| 147 | let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); | ||
| 148 | |||
| 149 | let write_ep = alt.endpoint_bulk_in(config.max_packet_size); | ||
| 150 | let read_ep = alt.endpoint_bulk_out(config.max_packet_size); | ||
| 151 | |||
| 152 | WebEndpoints { write_ep, read_ep } | ||
| 153 | } | ||
| 154 | |||
| 155 | // Wait until the device's endpoints are enabled. | ||
| 156 | async fn wait_connected(&mut self) { | ||
| 157 | self.read_ep.wait_enabled().await | ||
| 158 | } | ||
| 159 | |||
| 160 | // Echo data back to the host. | ||
| 161 | async fn echo(&mut self) { | ||
| 162 | let mut buf = [0; 64]; | ||
| 163 | loop { | ||
| 164 | let n = self.read_ep.read(&mut buf).await.unwrap(); | ||
| 165 | let data = &buf[..n]; | ||
| 166 | info!("Data read: {:x}", data); | ||
| 167 | self.write_ep.write(data).await.unwrap(); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
diff --git a/examples/rp23/src/bin/watchdog.rs b/examples/rp23/src/bin/watchdog.rs new file mode 100644 index 000000000..a901c1164 --- /dev/null +++ b/examples/rp23/src/bin/watchdog.rs | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | //! This example shows how to use Watchdog in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. See wifi_blinky.rs or connect external LED and resistor. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::info; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_rp::block::ImageDef; | ||
| 11 | use embassy_rp::gpio; | ||
| 12 | use embassy_rp::watchdog::*; | ||
| 13 | use embassy_time::{Duration, Timer}; | ||
| 14 | use gpio::{Level, Output}; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | #[link_section = ".start_block"] | ||
| 18 | #[used] | ||
| 19 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 20 | |||
| 21 | // Program metadata for `picotool info` | ||
| 22 | #[link_section = ".bi_entries"] | ||
| 23 | #[used] | ||
| 24 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 25 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 26 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 27 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 28 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 29 | ]; | ||
| 30 | |||
| 31 | #[embassy_executor::main] | ||
| 32 | async fn main(_spawner: Spawner) { | ||
| 33 | let p = embassy_rp::init(Default::default()); | ||
| 34 | info!("Hello world!"); | ||
| 35 | |||
| 36 | let mut watchdog = Watchdog::new(p.WATCHDOG); | ||
| 37 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 38 | |||
| 39 | // Set the LED high for 2 seconds so we know when we're about to start the watchdog | ||
| 40 | led.set_high(); | ||
| 41 | Timer::after_secs(2).await; | ||
| 42 | |||
| 43 | // Set to watchdog to reset if it's not fed within 1.05 seconds, and start it | ||
| 44 | watchdog.start(Duration::from_millis(1_050)); | ||
| 45 | info!("Started the watchdog timer"); | ||
| 46 | |||
| 47 | // Blink once a second for 5 seconds, feed the watchdog timer once a second to avoid a reset | ||
| 48 | for _ in 1..=5 { | ||
| 49 | led.set_low(); | ||
| 50 | Timer::after_millis(500).await; | ||
| 51 | led.set_high(); | ||
| 52 | Timer::after_millis(500).await; | ||
| 53 | info!("Feeding watchdog"); | ||
| 54 | watchdog.feed(); | ||
| 55 | } | ||
| 56 | |||
| 57 | info!("Stopped feeding, device will reset in 1.05 seconds"); | ||
| 58 | // Blink 10 times per second, not feeding the watchdog. | ||
| 59 | // The processor should reset in 1.05 seconds. | ||
| 60 | loop { | ||
| 61 | led.set_low(); | ||
| 62 | Timer::after_millis(100).await; | ||
| 63 | led.set_high(); | ||
| 64 | Timer::after_millis(100).await; | ||
| 65 | } | ||
| 66 | } | ||
diff --git a/examples/rp23/src/bin/zerocopy.rs b/examples/rp23/src/bin/zerocopy.rs new file mode 100644 index 000000000..86fca6f12 --- /dev/null +++ b/examples/rp23/src/bin/zerocopy.rs | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | //! This example shows how to use `zerocopy_channel` from `embassy_sync` for | ||
| 2 | //! sending large values between two tasks without copying. | ||
| 3 | //! The example also shows how to use the RP2040 ADC with DMA. | ||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use core::sync::atomic::{AtomicU16, Ordering}; | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; | ||
| 12 | use embassy_rp::bind_interrupts; | ||
| 13 | use embassy_rp::block::ImageDef; | ||
| 14 | use embassy_rp::gpio::Pull; | ||
| 15 | use embassy_rp::peripherals::DMA_CH0; | ||
| 16 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 17 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; | ||
| 18 | use embassy_time::{Duration, Ticker, Timer}; | ||
| 19 | use static_cell::StaticCell; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | #[link_section = ".start_block"] | ||
| 23 | #[used] | ||
| 24 | pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | ||
| 25 | |||
| 26 | // Program metadata for `picotool info` | ||
| 27 | #[link_section = ".bi_entries"] | ||
| 28 | #[used] | ||
| 29 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | ||
| 30 | embassy_rp::binary_info::rp_program_name!(c"example"), | ||
| 31 | embassy_rp::binary_info::rp_cargo_version!(), | ||
| 32 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | ||
| 33 | embassy_rp::binary_info::rp_program_build_attribute!(), | ||
| 34 | ]; | ||
| 35 | |||
| 36 | type SampleBuffer = [u16; 512]; | ||
| 37 | |||
| 38 | bind_interrupts!(struct Irqs { | ||
| 39 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 40 | }); | ||
| 41 | |||
| 42 | const BLOCK_SIZE: usize = 512; | ||
| 43 | const NUM_BLOCKS: usize = 2; | ||
| 44 | static MAX: AtomicU16 = AtomicU16::new(0); | ||
| 45 | |||
| 46 | struct AdcParts { | ||
| 47 | adc: Adc<'static, Async>, | ||
| 48 | pin: adc::Channel<'static>, | ||
| 49 | dma: DMA_CH0, | ||
| 50 | } | ||
| 51 | |||
| 52 | #[embassy_executor::main] | ||
| 53 | async fn main(spawner: Spawner) { | ||
| 54 | let p = embassy_rp::init(Default::default()); | ||
| 55 | info!("Here we go!"); | ||
| 56 | |||
| 57 | let adc_parts = AdcParts { | ||
| 58 | adc: Adc::new(p.ADC, Irqs, Config::default()), | ||
| 59 | pin: adc::Channel::new_pin(p.PIN_29, Pull::None), | ||
| 60 | dma: p.DMA_CH0, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static BUF: StaticCell<[SampleBuffer; NUM_BLOCKS]> = StaticCell::new(); | ||
| 64 | let buf = BUF.init([[0; BLOCK_SIZE]; NUM_BLOCKS]); | ||
| 65 | |||
| 66 | static CHANNEL: StaticCell<Channel<'_, NoopRawMutex, SampleBuffer>> = StaticCell::new(); | ||
| 67 | let channel = CHANNEL.init(Channel::new(buf)); | ||
| 68 | let (sender, receiver) = channel.split(); | ||
| 69 | |||
| 70 | spawner.must_spawn(consumer(receiver)); | ||
| 71 | spawner.must_spawn(producer(sender, adc_parts)); | ||
| 72 | |||
| 73 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 74 | loop { | ||
| 75 | ticker.next().await; | ||
| 76 | let max = MAX.load(Ordering::Relaxed); | ||
| 77 | info!("latest block's max value: {:?}", max); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | #[embassy_executor::task] | ||
| 82 | async fn producer(mut sender: Sender<'static, NoopRawMutex, SampleBuffer>, mut adc: AdcParts) { | ||
| 83 | loop { | ||
| 84 | // Obtain a free buffer from the channel | ||
| 85 | let buf = sender.send().await; | ||
| 86 | |||
| 87 | // Fill it with data | ||
| 88 | adc.adc.read_many(&mut adc.pin, buf, 1, &mut adc.dma).await.unwrap(); | ||
| 89 | |||
| 90 | // Notify the channel that the buffer is now ready to be received | ||
| 91 | sender.send_done(); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | #[embassy_executor::task] | ||
| 96 | async fn consumer(mut receiver: Receiver<'static, NoopRawMutex, SampleBuffer>) { | ||
| 97 | loop { | ||
| 98 | // Receive a buffer from the channel | ||
| 99 | let buf = receiver.receive().await; | ||
| 100 | |||
| 101 | // Simulate using the data, while the producer is filling up the next buffer | ||
| 102 | Timer::after_micros(1000).await; | ||
| 103 | let max = buf.iter().max().unwrap(); | ||
| 104 | MAX.store(*max, Ordering::Relaxed); | ||
| 105 | |||
| 106 | // Notify the channel that the buffer is now ready to be reused | ||
| 107 | receiver.receive_done(); | ||
| 108 | } | ||
| 109 | } | ||
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 58ea894f3..87491b1d2 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -6,8 +6,8 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } | 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["log", "std", ] } | 10 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["log", "std", ] } |
| 11 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } | 11 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } |
| 12 | embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } | 12 | embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } |
| 13 | embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} | 13 | embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} |
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 59813d8cb..310e7264d 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs | |||
| @@ -52,12 +52,7 @@ async fn main_task(spawner: Spawner) { | |||
| 52 | // Init network stack | 52 | // Init network stack |
| 53 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | 53 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); |
| 54 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 54 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 55 | let stack = &*STACK.init(Stack::new( | 55 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 56 | device, | ||
| 57 | config, | ||
| 58 | RESOURCES.init(StackResources::<3>::new()), | ||
| 59 | seed, | ||
| 60 | )); | ||
| 61 | 56 | ||
| 62 | // Launch network task | 57 | // Launch network task |
| 63 | spawner.spawn(net_task(stack)).unwrap(); | 58 | spawner.spawn(net_task(stack)).unwrap(); |
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index 3b6a3de37..c9615ef35 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs | |||
| @@ -51,12 +51,7 @@ async fn main_task(spawner: Spawner) { | |||
| 51 | // Init network stack | 51 | // Init network stack |
| 52 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | 52 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); |
| 53 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 53 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 54 | let stack: &Stack<_> = &*STACK.init(Stack::new( | 54 | let stack: &Stack<_> = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 55 | device, | ||
| 56 | config, | ||
| 57 | RESOURCES.init(StackResources::<3>::new()), | ||
| 58 | seed, | ||
| 59 | )); | ||
| 60 | 55 | ||
| 61 | // Launch network task | 56 | // Launch network task |
| 62 | spawner.spawn(net_task(stack)).unwrap(); | 57 | spawner.spawn(net_task(stack)).unwrap(); |
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index 9ec0ea91f..c5c27c4a3 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs | |||
| @@ -102,7 +102,7 @@ async fn main_task(spawner: Spawner) { | |||
| 102 | let stack = &*STACK.init(Stack::new( | 102 | let stack = &*STACK.init(Stack::new( |
| 103 | device, | 103 | device, |
| 104 | Config::default(), // don't configure IP yet | 104 | Config::default(), // don't configure IP yet |
| 105 | RESOURCES.init(StackResources::<3>::new()), | 105 | RESOURCES.init(StackResources::new()), |
| 106 | seed, | 106 | seed, |
| 107 | )); | 107 | )); |
| 108 | 108 | ||
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index bee91990d..b2ba4915a 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs | |||
| @@ -50,12 +50,7 @@ async fn main_task(spawner: Spawner) { | |||
| 50 | // Init network stack | 50 | // Init network stack |
| 51 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | 51 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); |
| 52 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 52 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 53 | let stack = &*STACK.init(Stack::new( | 53 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 54 | device, | ||
| 55 | config, | ||
| 56 | RESOURCES.init(StackResources::<3>::new()), | ||
| 57 | seed, | ||
| 58 | )); | ||
| 59 | 54 | ||
| 60 | // Launch network task | 55 | // Launch network task |
| 61 | spawner.spawn(net_task(stack)).unwrap(); | 56 | spawner.spawn(net_task(stack)).unwrap(); |
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index e8b6eaa6c..39b29a449 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs | |||
| @@ -64,12 +64,7 @@ async fn main_task(spawner: Spawner) { | |||
| 64 | // Init network stack | 64 | // Init network stack |
| 65 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); | 65 | static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new(); |
| 66 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 66 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 67 | let stack = &*STACK.init(Stack::new( | 67 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 68 | device, | ||
| 69 | config, | ||
| 70 | RESOURCES.init(StackResources::<3>::new()), | ||
| 71 | seed, | ||
| 72 | )); | ||
| 73 | 68 | ||
| 74 | // Launch network task | 69 | // Launch network task |
| 75 | spawner.spawn(net_task(stack)).unwrap(); | 70 | spawner.spawn(net_task(stack)).unwrap(); |
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 331046a80..9102467eb 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml | |||
| @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32c031c6 to your chip name, if necessary. | 8 | # Change stm32c031c6 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
| 15 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 15fb55ca7..724efdaff 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml | |||
| @@ -13,8 +13,8 @@ defmt = "0.3" | |||
| 13 | defmt-rtt = "0.4" | 13 | defmt-rtt = "0.4" |
| 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 15 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 15 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 16 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 16 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 17 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 17 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 18 | static_cell = "2" | 18 | static_cell = "2" |
| 19 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | 19 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } |
| 20 | 20 | ||
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 38b615795..0084651a3 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32f103c8 to your chip name, if necessary. | 8 | # Change stm32f103c8 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index ec9b54920..60eb0eb93 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml | |||
| @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32f207zg to your chip name, if necessary. | 8 | # Change stm32f207zg to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
| 15 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 62c0fed16..7fda410d9 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32f303ze to your chip name, if necessary. | 8 | # Change stm32f303ze to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32f3/src/bin/blocking-tsc.rs b/examples/stm32f3/src/bin/blocking-tsc.rs new file mode 100644 index 000000000..5c8dac94f --- /dev/null +++ b/examples/stm32f3/src/bin/blocking-tsc.rs | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | // Example of polling TSC (Touch Sensing Controller) that lights an LED when touch is detected. | ||
| 2 | // | ||
| 3 | // Suggested physical setup on STM32F303ZE Nucleo board: | ||
| 4 | // - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. | ||
| 5 | // - Connect one end of a 1K resistor to pin A1 and leave the other end loose. | ||
| 6 | // The loose end will act as touch sensor which will register your touch. | ||
| 7 | // | ||
| 8 | // Troubleshooting the setup: | ||
| 9 | // - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, | ||
| 10 | // now the led should light up. Next try using a different value for the sampling capacitor. | ||
| 11 | // Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. | ||
| 12 | // | ||
| 13 | // All configuration values and sampling capacitor value have been determined experimentally. | ||
| 14 | // Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. | ||
| 15 | // | ||
| 16 | #![no_std] | ||
| 17 | #![no_main] | ||
| 18 | |||
| 19 | use defmt::*; | ||
| 20 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 21 | use embassy_stm32::tsc::{self, *}; | ||
| 22 | use embassy_time::Timer; | ||
| 23 | use {defmt_rtt as _, panic_probe as _}; | ||
| 24 | |||
| 25 | /// This example is written for the nucleo-stm32f303ze, with a stm32f303ze chip. | ||
| 26 | /// | ||
| 27 | /// Make sure you check/update the following (whether you use the F303ZE or another board): | ||
| 28 | /// | ||
| 29 | /// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32F303ZETx`chip name. | ||
| 30 | /// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for F303ZE it should be `stm32f303ze`. | ||
| 31 | /// * [ ] If your board has a special clock or power configuration, make sure that it is | ||
| 32 | /// set up appropriately. | ||
| 33 | /// * [ ] If your board has different pin mapping, update any pin numbers or peripherals | ||
| 34 | /// to match your schematic | ||
| 35 | /// | ||
| 36 | /// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 37 | /// | ||
| 38 | /// * Which example you are trying to run | ||
| 39 | /// * Which chip and board you are using | ||
| 40 | /// | ||
| 41 | /// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
| 42 | #[embassy_executor::main] | ||
| 43 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 44 | let device_config = embassy_stm32::Config::default(); | ||
| 45 | let context = embassy_stm32::init(device_config); | ||
| 46 | |||
| 47 | let tsc_conf = Config { | ||
| 48 | ct_pulse_high_length: ChargeTransferPulseCycle::_8, | ||
| 49 | ct_pulse_low_length: ChargeTransferPulseCycle::_8, | ||
| 50 | spread_spectrum: false, | ||
| 51 | spread_spectrum_deviation: SSDeviation::new(2).unwrap(), | ||
| 52 | spread_spectrum_prescaler: false, | ||
| 53 | pulse_generator_prescaler: PGPrescalerDivider::_32, | ||
| 54 | max_count_value: MaxCount::_255, | ||
| 55 | io_default_mode: false, | ||
| 56 | synchro_pin_polarity: false, | ||
| 57 | acquisition_mode: false, | ||
| 58 | max_count_interrupt: false, | ||
| 59 | channel_ios: TscIOPin::Group1Io1.into(), | ||
| 60 | shield_ios: 0, // no shield | ||
| 61 | sampling_ios: TscIOPin::Group1Io2.into(), | ||
| 62 | }; | ||
| 63 | |||
| 64 | let mut g1: PinGroup<embassy_stm32::peripherals::TSC, G1> = PinGroup::new(); | ||
| 65 | g1.set_io1(context.PA0, PinType::Sample); | ||
| 66 | g1.set_io2(context.PA1, PinType::Channel); | ||
| 67 | |||
| 68 | let mut touch_controller = tsc::Tsc::new_blocking(context.TSC, Some(g1), None, None, None, None, None, tsc_conf); | ||
| 69 | |||
| 70 | // LED2 on the STM32F303ZE nucleo-board | ||
| 71 | let mut led = Output::new(context.PB7, Level::High, Speed::Low); | ||
| 72 | |||
| 73 | // smaller sample capacitor discharge faster and can be used with shorter delay. | ||
| 74 | let discharge_delay = 5; // ms | ||
| 75 | |||
| 76 | // the interval at which the loop polls for new touch sensor values | ||
| 77 | let polling_interval = 100; // ms | ||
| 78 | |||
| 79 | info!("polling for touch"); | ||
| 80 | loop { | ||
| 81 | touch_controller.start(); | ||
| 82 | touch_controller.poll_for_acquisition(); | ||
| 83 | touch_controller.discharge_io(true); | ||
| 84 | Timer::after_millis(discharge_delay).await; | ||
| 85 | |||
| 86 | let grp1_status = touch_controller.group_get_status(Group::One); | ||
| 87 | match grp1_status { | ||
| 88 | GroupStatus::Complete => { | ||
| 89 | let group_one_val = touch_controller.group_get_value(Group::One); | ||
| 90 | info!("{}", group_one_val); | ||
| 91 | led.set_high(); | ||
| 92 | } | ||
| 93 | GroupStatus::Ongoing => led.set_low(), | ||
| 94 | } | ||
| 95 | |||
| 96 | Timer::after_millis(polling_interval).await; | ||
| 97 | } | ||
| 98 | } | ||
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 84c44a7b7..1cc0a97da 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml | |||
| @@ -6,10 +6,10 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 12 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index d909c7e68..b85361596 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32f429zi to your chip name, if necessary. | 8 | # Change stm32f429zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt" ] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt" ] } |
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } | 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } |
| 15 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | 15 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| @@ -30,7 +30,7 @@ heapless = { version = "0.8", default-features = false } | |||
| 30 | nb = "1.0.0" | 30 | nb = "1.0.0" |
| 31 | embedded-storage = "0.3.1" | 31 | embedded-storage = "0.3.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | usbd-hid = "0.7.0" | 33 | usbd-hid = "0.8.1" |
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | chrono = { version = "^0.4", default-features = false} | 35 | chrono = { version = "^0.4", default-features = false} |
| 36 | 36 | ||
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 648c45bbd..9388c64bf 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -89,13 +89,8 @@ async fn main(spawner: Spawner) -> ! { | |||
| 89 | 89 | ||
| 90 | // Init network stack | 90 | // Init network stack |
| 91 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 91 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 92 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 92 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 93 | let stack = &*STACK.init(Stack::new( | 93 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 94 | device, | ||
| 95 | config, | ||
| 96 | RESOURCES.init(StackResources::<2>::new()), | ||
| 97 | seed, | ||
| 98 | )); | ||
| 99 | 94 | ||
| 100 | // Launch network task | 95 | // Launch network task |
| 101 | unwrap!(spawner.spawn(net_task(stack))); | 96 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index 3c770a873..5c3c6c3ba 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -93,13 +93,8 @@ async fn main(spawner: Spawner) -> ! { | |||
| 93 | //}); | 93 | //}); |
| 94 | 94 | ||
| 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 96 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 97 | let stack = &*STACK.init(Stack::new( | 97 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 98 | device, | ||
| 99 | config, | ||
| 100 | RESOURCES.init(StackResources::<2>::new()), | ||
| 101 | seed, | ||
| 102 | )); | ||
| 103 | 98 | ||
| 104 | // Launch network task | 99 | // Launch network task |
| 105 | unwrap!(spawner.spawn(net_task(stack))); | 100 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index b398c35da..94e51c338 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs | |||
| @@ -145,13 +145,8 @@ async fn main(spawner: Spawner) { | |||
| 145 | 145 | ||
| 146 | // Init network stack | 146 | // Init network stack |
| 147 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | 147 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); |
| 148 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 148 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 149 | let stack = &*STACK.init(Stack::new( | 149 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 150 | device, | ||
| 151 | config, | ||
| 152 | RESOURCES.init(StackResources::<2>::new()), | ||
| 153 | seed, | ||
| 154 | )); | ||
| 155 | 150 | ||
| 156 | unwrap!(spawner.spawn(net_task(stack))); | 151 | unwrap!(spawner.spawn(net_task(stack))); |
| 157 | 152 | ||
diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 634f13f4e..6a5bd0b29 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml | |||
| @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | # Specific examples only for stm32f469 | 8 | # Specific examples only for stm32f469 |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } |
| 10 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "0.3" |
| 14 | defmt-rtt = "0.4" | 14 | defmt-rtt = "0.4" |
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 7fc7d6f42..8c591ebd2 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32f777zi to your chip name, if necessary. | 8 | # Change stm32f777zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 14 | embedded-io-async = { version = "0.6.1" } | 14 | embedded-io-async = { version = "0.6.1" } |
| 15 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 17 | 17 | ||
| 18 | defmt = "0.3" | 18 | defmt = "0.3" |
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 41e2a6061..2fd10c8fb 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -90,13 +90,8 @@ async fn main(spawner: Spawner) -> ! { | |||
| 90 | 90 | ||
| 91 | // Init network stack | 91 | // Init network stack |
| 92 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 92 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 93 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 93 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 94 | let stack = &*STACK.init(Stack::new( | 94 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 95 | device, | ||
| 96 | config, | ||
| 97 | RESOURCES.init(StackResources::<2>::new()), | ||
| 98 | seed, | ||
| 99 | )); | ||
| 100 | 95 | ||
| 101 | // Launch network task | 96 | // Launch network task |
| 102 | unwrap!(spawner.spawn(net_task(stack))); | 97 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index b9d710ca7..a50074ce0 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32g0b1re to your chip name, if necessary. | 8 | # Change stm32g0b1re to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index ac6010f5f..2768147a1 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml | |||
| @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32g491re to your chip name, if necessary. | 8 | # Change stm32g491re to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | usbd-hid = "0.7.0" | 15 | usbd-hid = "0.8.1" |
| 16 | 16 | ||
| 17 | defmt = "0.3" | 17 | defmt = "0.3" |
| 18 | defmt-rtt = "0.4" | 18 | defmt-rtt = "0.4" |
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs new file mode 100644 index 000000000..78d071d45 --- /dev/null +++ b/examples/stm32g4/src/bin/adc_differential.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | //! adc differential mode example | ||
| 2 | //! | ||
| 3 | //! This example uses adc1 in differential mode | ||
| 4 | //! p:pa0 n:pa1 | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 12 | use embassy_stm32::Config; | ||
| 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 mut config = Config::default(); | ||
| 19 | { | ||
| 20 | use embassy_stm32::rcc::*; | ||
| 21 | config.rcc.pll = Some(Pll { | ||
| 22 | source: PllSource::HSI, | ||
| 23 | prediv: PllPreDiv::DIV4, | ||
| 24 | mul: PllMul::MUL85, | ||
| 25 | divp: None, | ||
| 26 | divq: None, | ||
| 27 | // Main system clock at 170 MHz | ||
| 28 | divr: Some(PllRDiv::DIV2), | ||
| 29 | }); | ||
| 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; | ||
| 31 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 32 | } | ||
| 33 | let mut p = embassy_stm32::init(config); | ||
| 34 | |||
| 35 | let mut adc = Adc::new(p.ADC1); | ||
| 36 | adc.set_sample_time(SampleTime::CYCLES247_5); | ||
| 37 | adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 | ||
| 38 | |||
| 39 | // can also use | ||
| 40 | // adc.set_differential_channel(1, true); | ||
| 41 | info!("adc initialized"); | ||
| 42 | loop { | ||
| 43 | let measured = adc.blocking_read(&mut p.PA0); | ||
| 44 | info!("data: {}", measured); | ||
| 45 | Timer::after_millis(500).await; | ||
| 46 | } | ||
| 47 | } | ||
diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs new file mode 100644 index 000000000..d31eb20f8 --- /dev/null +++ b/examples/stm32g4/src/bin/adc_oversampling.rs | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | //! adc oversampling example | ||
| 2 | //! | ||
| 3 | //! This example uses adc oversampling to achieve 16bit data | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_stm32::adc::vals::{Rovsm, Trovs}; | ||
| 11 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 12 | use embassy_stm32::Config; | ||
| 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 mut config = Config::default(); | ||
| 19 | { | ||
| 20 | use embassy_stm32::rcc::*; | ||
| 21 | config.rcc.pll = Some(Pll { | ||
| 22 | source: PllSource::HSI, | ||
| 23 | prediv: PllPreDiv::DIV4, | ||
| 24 | mul: PllMul::MUL85, | ||
| 25 | divp: None, | ||
| 26 | divq: None, | ||
| 27 | // Main system clock at 170 MHz | ||
| 28 | divr: Some(PllRDiv::DIV2), | ||
| 29 | }); | ||
| 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; | ||
| 31 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 32 | } | ||
| 33 | let mut p = embassy_stm32::init(config); | ||
| 34 | |||
| 35 | let mut adc = Adc::new(p.ADC1); | ||
| 36 | adc.set_sample_time(SampleTime::CYCLES6_5); | ||
| 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf | ||
| 38 | // page652 Oversampler | ||
| 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation | ||
| 40 | // 0x00 oversampling ratio X2 | ||
| 41 | // 0x01 oversampling ratio X4 | ||
| 42 | // 0x02 oversampling ratio X8 | ||
| 43 | // 0x03 oversampling ratio X16 | ||
| 44 | // 0x04 oversampling ratio X32 | ||
| 45 | // 0x05 oversampling ratio X64 | ||
| 46 | // 0x06 oversampling ratio X128 | ||
| 47 | // 0x07 oversampling ratio X256 | ||
| 48 | adc.set_oversampling_ratio(0x03); // ratio X3 | ||
| 49 | adc.set_oversampling_shift(0b0000); // no shift | ||
| 50 | adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); | ||
| 51 | |||
| 52 | loop { | ||
| 53 | let measured = adc.blocking_read(&mut p.PA0); | ||
| 54 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 | ||
| 55 | Timer::after_millis(500).await; | ||
| 56 | } | ||
| 57 | } | ||
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs index 7caea634f..2e87d3931 100644 --- a/examples/stm32g4/src/bin/usb_c_pd.rs +++ b/examples/stm32g4/src/bin/usb_c_pd.rs | |||
| @@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) { | |||
| 55 | 55 | ||
| 56 | info!("Hello World!"); | 56 | info!("Hello World!"); |
| 57 | 57 | ||
| 58 | let mut ucpd = Ucpd::new(p.UCPD1, Irqs {}, p.PB6, p.PB4); | 58 | let mut ucpd = Ucpd::new(p.UCPD1, Irqs {}, p.PB6, p.PB4, Default::default()); |
| 59 | ucpd.cc_phy().set_pull(CcPull::Sink); | 59 | ucpd.cc_phy().set_pull(CcPull::Sink); |
| 60 | 60 | ||
| 61 | info!("Waiting for USB connection..."); | 61 | info!("Waiting for USB connection..."); |
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 59d3a9759..30b1d2be9 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml | |||
| @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32h563zi to your chip name, if necessary. | 8 | # Change stm32h563zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } | 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 16 | 16 | ||
| 17 | defmt = "0.3" | 17 | defmt = "0.3" |
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 2370656e6..65cfad8c9 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -93,13 +93,8 @@ async fn main(spawner: Spawner) -> ! { | |||
| 93 | 93 | ||
| 94 | // Init network stack | 94 | // Init network stack |
| 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 95 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 96 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 96 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 97 | let stack = &*STACK.init(Stack::new( | 97 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 98 | device, | ||
| 99 | config, | ||
| 100 | RESOURCES.init(StackResources::<2>::new()), | ||
| 101 | seed, | ||
| 102 | )); | ||
| 103 | 98 | ||
| 104 | // Launch network task | 99 | // Launch network task |
| 105 | unwrap!(spawner.spawn(net_task(&stack))); | 100 | unwrap!(spawner.spawn(net_task(&stack))); |
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 0584f3916..13fce7dc7 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml | |||
| @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32h743bi to your chip name, if necessary. | 8 | # Change stm32h743bi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 11 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } |
| 12 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 12 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 13 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 15 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 17 | 17 | ||
| 18 | defmt = "0.3" | 18 | defmt = "0.3" |
| @@ -34,6 +34,7 @@ stm32-fmc = "0.3.0" | |||
| 34 | embedded-storage = "0.3.1" | 34 | embedded-storage = "0.3.1" |
| 35 | static_cell = "2" | 35 | 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 | 38 | ||
| 38 | # cargo build/run | 39 | # cargo build/run |
| 39 | [profile.dev] | 40 | [profile.dev] |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 7c7964ecd..b2f8ed91e 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -93,12 +93,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 93 | // Init network stack | 93 | // Init network stack |
| 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 96 | let stack = &*STACK.init(Stack::new( | 96 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 97 | device, | ||
| 98 | config, | ||
| 99 | RESOURCES.init(StackResources::<3>::new()), | ||
| 100 | seed, | ||
| 101 | )); | ||
| 102 | 97 | ||
| 103 | // Launch network task | 98 | // Launch network task |
| 104 | unwrap!(spawner.spawn(net_task(&stack))); | 99 | unwrap!(spawner.spawn(net_task(&stack))); |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 0639fb99f..274c24ab1 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -93,12 +93,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 93 | // Init network stack | 93 | // Init network stack |
| 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 95 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 96 | let stack = &*STACK.init(Stack::new( | 96 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 97 | device, | ||
| 98 | config, | ||
| 99 | RESOURCES.init(StackResources::<3>::new()), | ||
| 100 | seed, | ||
| 101 | )); | ||
| 102 | 97 | ||
| 103 | // Launch network task | 98 | // Launch network task |
| 104 | unwrap!(spawner.spawn(net_task(stack))); | 99 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index 9a52e8d3b..aa6544f41 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs | |||
| @@ -99,12 +99,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 99 | // Init network stack | 99 | // Init network stack |
| 100 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | 100 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 101 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | 101 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 102 | let stack = &*STACK.init(Stack::new( | 102 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 103 | device, | ||
| 104 | config, | ||
| 105 | RESOURCES.init(StackResources::<3>::new()), | ||
| 106 | seed, | ||
| 107 | )); | ||
| 108 | 103 | ||
| 109 | // Launch network task | 104 | // Launch network task |
| 110 | unwrap!(spawner.spawn(net_task(stack))); | 105 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs new file mode 100644 index 000000000..f6735e235 --- /dev/null +++ b/examples/stm32h7/src/bin/sai.rs | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | //! Daisy Seed rev.7(with PCM3060 codec) | ||
| 2 | //! https://electro-smith.com/products/daisy-seed | ||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use grounded::uninit::GroundedArrayCell; | ||
| 8 | use hal::rcc::*; | ||
| 9 | use hal::sai::*; | ||
| 10 | use hal::time::Hertz; | ||
| 11 | use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; | ||
| 12 | |||
| 13 | const BLOCK_LENGTH: usize = 32; // 32 samples | ||
| 14 | const HALF_DMA_BUFFER_LENGTH: usize = BLOCK_LENGTH * 2; // 2 channels | ||
| 15 | const DMA_BUFFER_LENGTH: usize = HALF_DMA_BUFFER_LENGTH * 2; // 2 half-blocks | ||
| 16 | const SAMPLE_RATE: u32 = 48000; | ||
| 17 | |||
| 18 | //DMA buffer must be in special region. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions | ||
| 19 | #[link_section = ".sram1_bss"] | ||
| 20 | static mut TX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); | ||
| 21 | #[link_section = ".sram1_bss"] | ||
| 22 | static mut RX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); | ||
| 23 | |||
| 24 | #[embassy_executor::main] | ||
| 25 | async fn main(_spawner: Spawner) { | ||
| 26 | let mut config = hal::Config::default(); | ||
| 27 | config.rcc.pll1 = Some(Pll { | ||
| 28 | source: PllSource::HSE, | ||
| 29 | prediv: PllPreDiv::DIV4, | ||
| 30 | mul: PllMul::MUL200, | ||
| 31 | divp: Some(PllDiv::DIV2), | ||
| 32 | divq: Some(PllDiv::DIV5), | ||
| 33 | divr: Some(PllDiv::DIV2), | ||
| 34 | }); | ||
| 35 | config.rcc.pll3 = Some(Pll { | ||
| 36 | source: PllSource::HSE, | ||
| 37 | prediv: PllPreDiv::DIV6, | ||
| 38 | mul: PllMul::MUL295, | ||
| 39 | divp: Some(PllDiv::DIV16), | ||
| 40 | divq: Some(PllDiv::DIV4), | ||
| 41 | divr: Some(PllDiv::DIV32), | ||
| 42 | }); | ||
| 43 | config.rcc.sys = Sysclk::PLL1_P; | ||
| 44 | config.rcc.mux.sai1sel = hal::pac::rcc::vals::Saisel::PLL3_P; | ||
| 45 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz | ||
| 46 | config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 47 | config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 48 | config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 49 | config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 50 | config.rcc.hse = Some(Hse { | ||
| 51 | freq: Hertz::mhz(16), | ||
| 52 | mode: HseMode::Oscillator, | ||
| 53 | }); | ||
| 54 | |||
| 55 | let p = hal::init(config); | ||
| 56 | |||
| 57 | let (sub_block_tx, sub_block_rx) = hal::sai::split_subblocks(p.SAI1); | ||
| 58 | let kernel_clock = hal::rcc::frequency::<hal::peripherals::SAI1>().0; | ||
| 59 | let mclk_div = mclk_div_from_u8((kernel_clock / (SAMPLE_RATE * 256)) as u8); | ||
| 60 | |||
| 61 | let mut tx_config = hal::sai::Config::default(); | ||
| 62 | tx_config.mode = Mode::Master; | ||
| 63 | tx_config.tx_rx = TxRx::Transmitter; | ||
| 64 | tx_config.sync_output = true; | ||
| 65 | tx_config.clock_strobe = ClockStrobe::Falling; | ||
| 66 | tx_config.master_clock_divider = mclk_div; | ||
| 67 | tx_config.stereo_mono = StereoMono::Stereo; | ||
| 68 | tx_config.data_size = DataSize::Data24; | ||
| 69 | tx_config.bit_order = BitOrder::MsbFirst; | ||
| 70 | tx_config.frame_sync_polarity = FrameSyncPolarity::ActiveHigh; | ||
| 71 | tx_config.frame_sync_offset = FrameSyncOffset::OnFirstBit; | ||
| 72 | tx_config.frame_length = 64; | ||
| 73 | tx_config.frame_sync_active_level_length = embassy_stm32::sai::word::U7(32); | ||
| 74 | tx_config.fifo_threshold = FifoThreshold::Quarter; | ||
| 75 | |||
| 76 | let mut rx_config = tx_config.clone(); | ||
| 77 | rx_config.mode = Mode::Slave; | ||
| 78 | rx_config.tx_rx = TxRx::Receiver; | ||
| 79 | rx_config.sync_input = SyncInput::Internal; | ||
| 80 | rx_config.clock_strobe = ClockStrobe::Rising; | ||
| 81 | rx_config.sync_output = false; | ||
| 82 | |||
| 83 | let tx_buffer: &mut [u32] = unsafe { | ||
| 84 | TX_BUFFER.initialize_all_copied(0); | ||
| 85 | let (ptr, len) = TX_BUFFER.get_ptr_len(); | ||
| 86 | core::slice::from_raw_parts_mut(ptr, len) | ||
| 87 | }; | ||
| 88 | |||
| 89 | let mut sai_transmitter = Sai::new_asynchronous_with_mclk( | ||
| 90 | sub_block_tx, | ||
| 91 | p.PE5, | ||
| 92 | p.PE6, | ||
| 93 | p.PE4, | ||
| 94 | p.PE2, | ||
| 95 | p.DMA1_CH0, | ||
| 96 | tx_buffer, | ||
| 97 | tx_config, | ||
| 98 | ); | ||
| 99 | |||
| 100 | let rx_buffer: &mut [u32] = unsafe { | ||
| 101 | RX_BUFFER.initialize_all_copied(0); | ||
| 102 | let (ptr, len) = RX_BUFFER.get_ptr_len(); | ||
| 103 | core::slice::from_raw_parts_mut(ptr, len) | ||
| 104 | }; | ||
| 105 | |||
| 106 | let mut sai_receiver = Sai::new_synchronous(sub_block_rx, p.PE3, p.DMA1_CH1, rx_buffer, rx_config); | ||
| 107 | |||
| 108 | sai_receiver.start(); | ||
| 109 | sai_transmitter.start(); | ||
| 110 | |||
| 111 | let mut buf = [0u32; HALF_DMA_BUFFER_LENGTH]; | ||
| 112 | |||
| 113 | loop { | ||
| 114 | sai_receiver.read(&mut buf).await.unwrap(); | ||
| 115 | sai_transmitter.write(&buf).await.unwrap(); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | const fn mclk_div_from_u8(v: u8) -> MasterClockDivider { | ||
| 120 | match v { | ||
| 121 | 1 => MasterClockDivider::Div1, | ||
| 122 | 2 => MasterClockDivider::Div2, | ||
| 123 | 3 => MasterClockDivider::Div3, | ||
| 124 | 4 => MasterClockDivider::Div4, | ||
| 125 | 5 => MasterClockDivider::Div5, | ||
| 126 | 6 => MasterClockDivider::Div6, | ||
| 127 | 7 => MasterClockDivider::Div7, | ||
| 128 | 8 => MasterClockDivider::Div8, | ||
| 129 | 9 => MasterClockDivider::Div9, | ||
| 130 | 10 => MasterClockDivider::Div10, | ||
| 131 | 11 => MasterClockDivider::Div11, | ||
| 132 | 12 => MasterClockDivider::Div12, | ||
| 133 | 13 => MasterClockDivider::Div13, | ||
| 134 | 14 => MasterClockDivider::Div14, | ||
| 135 | 15 => MasterClockDivider::Div15, | ||
| 136 | 16 => MasterClockDivider::Div16, | ||
| 137 | 17 => MasterClockDivider::Div17, | ||
| 138 | 18 => MasterClockDivider::Div18, | ||
| 139 | 19 => MasterClockDivider::Div19, | ||
| 140 | 20 => MasterClockDivider::Div20, | ||
| 141 | 21 => MasterClockDivider::Div21, | ||
| 142 | 22 => MasterClockDivider::Div22, | ||
| 143 | 23 => MasterClockDivider::Div23, | ||
| 144 | 24 => MasterClockDivider::Div24, | ||
| 145 | 25 => MasterClockDivider::Div25, | ||
| 146 | 26 => MasterClockDivider::Div26, | ||
| 147 | 27 => MasterClockDivider::Div27, | ||
| 148 | 28 => MasterClockDivider::Div28, | ||
| 149 | 29 => MasterClockDivider::Div29, | ||
| 150 | 30 => MasterClockDivider::Div30, | ||
| 151 | 31 => MasterClockDivider::Div31, | ||
| 152 | 32 => MasterClockDivider::Div32, | ||
| 153 | 33 => MasterClockDivider::Div33, | ||
| 154 | 34 => MasterClockDivider::Div34, | ||
| 155 | 35 => MasterClockDivider::Div35, | ||
| 156 | 36 => MasterClockDivider::Div36, | ||
| 157 | 37 => MasterClockDivider::Div37, | ||
| 158 | 38 => MasterClockDivider::Div38, | ||
| 159 | 39 => MasterClockDivider::Div39, | ||
| 160 | 40 => MasterClockDivider::Div40, | ||
| 161 | 41 => MasterClockDivider::Div41, | ||
| 162 | 42 => MasterClockDivider::Div42, | ||
| 163 | 43 => MasterClockDivider::Div43, | ||
| 164 | 44 => MasterClockDivider::Div44, | ||
| 165 | 45 => MasterClockDivider::Div45, | ||
| 166 | 46 => MasterClockDivider::Div46, | ||
| 167 | 47 => MasterClockDivider::Div47, | ||
| 168 | 48 => MasterClockDivider::Div48, | ||
| 169 | 49 => MasterClockDivider::Div49, | ||
| 170 | 50 => MasterClockDivider::Div50, | ||
| 171 | 51 => MasterClockDivider::Div51, | ||
| 172 | 52 => MasterClockDivider::Div52, | ||
| 173 | 53 => MasterClockDivider::Div53, | ||
| 174 | 54 => MasterClockDivider::Div54, | ||
| 175 | 55 => MasterClockDivider::Div55, | ||
| 176 | 56 => MasterClockDivider::Div56, | ||
| 177 | 57 => MasterClockDivider::Div57, | ||
| 178 | 58 => MasterClockDivider::Div58, | ||
| 179 | 59 => MasterClockDivider::Div59, | ||
| 180 | 60 => MasterClockDivider::Div60, | ||
| 181 | 61 => MasterClockDivider::Div61, | ||
| 182 | 62 => MasterClockDivider::Div62, | ||
| 183 | 63 => MasterClockDivider::Div63, | ||
| 184 | _ => panic!(), | ||
| 185 | } | ||
| 186 | } | ||
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs index b2e941078..43fb6b41c 100644 --- a/examples/stm32h7/src/bin/spi_bdma.rs +++ b/examples/stm32h7/src/bin/spi_bdma.rs | |||
| @@ -10,18 +10,24 @@ use embassy_executor::Executor; | |||
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::time::mhz; | 11 | use embassy_stm32::time::mhz; |
| 12 | use embassy_stm32::{spi, Config}; | 12 | use embassy_stm32::{spi, Config}; |
| 13 | use grounded::uninit::GroundedArrayCell; | ||
| 13 | use heapless::String; | 14 | use heapless::String; |
| 14 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 17 | ||
| 17 | // Defined in memory.x | 18 | // Defined in memory.x |
| 18 | #[link_section = ".ram_d3"] | 19 | #[link_section = ".ram_d3"] |
| 19 | static mut RAM_D3: [u8; 64 * 1024] = [0u8; 64 * 1024]; | 20 | static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); |
| 20 | 21 | ||
| 21 | #[embassy_executor::task] | 22 | #[embassy_executor::task] |
| 22 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 23 | async fn main_task(mut spi: spi::Spi<'static, Async>) { |
| 23 | let read_buffer = unsafe { &mut RAM_D3[0..128] }; | 24 | let (read_buffer, write_buffer) = unsafe { |
| 24 | let write_buffer = unsafe { &mut RAM_D3[128..256] }; | 25 | RAM_D3.initialize_all_copied(0); |
| 26 | ( | ||
| 27 | RAM_D3.get_subslice_mut_unchecked(0, 128), | ||
| 28 | RAM_D3.get_subslice_mut_unchecked(128, 128), | ||
| 29 | ) | ||
| 30 | }; | ||
| 25 | 31 | ||
| 26 | for n in 0u32.. { | 32 | for n in 0u32.. { |
| 27 | let mut write: String<128> = String::new(); | 33 | let mut write: String<128> = String::new(); |
diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index fc21cc894..93e9575b6 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml | |||
| @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 8 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 10 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
diff --git a/examples/stm32h755cm4/.cargo/config.toml b/examples/stm32h755cm4/.cargo/config.toml new file mode 100644 index 000000000..193e6bbc3 --- /dev/null +++ b/examples/stm32h755cm4/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv7em-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip STM32H755ZITx --catch-hardfault --always-print-stacktrace' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml new file mode 100644 index 000000000..7a42fbdaa --- /dev/null +++ b/examples/stm32h755cm4/Cargo.toml | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32h755cm4-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | # Change stm32h755zi-cm4 to your chip name, if necessary. | ||
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | ||
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | ||
| 11 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } | ||
| 12 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||
| 13 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | ||
| 15 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } | ||
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 17 | |||
| 18 | defmt = "0.3" | ||
| 19 | defmt-rtt = "0.4" | ||
| 20 | |||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 22 | cortex-m-rt = "0.7.0" | ||
| 23 | embedded-hal = "0.2.6" | ||
| 24 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 25 | embedded-hal-async = { version = "1.0" } | ||
| 26 | embedded-nal-async = { version = "0.7.1" } | ||
| 27 | embedded-io-async = { version = "0.6.1" } | ||
| 28 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 29 | heapless = { version = "0.8", default-features = false } | ||
| 30 | rand_core = "0.6.3" | ||
| 31 | critical-section = "1.1" | ||
| 32 | micromath = "2.0.0" | ||
| 33 | stm32-fmc = "0.3.0" | ||
| 34 | embedded-storage = "0.3.1" | ||
| 35 | static_cell = "2" | ||
| 36 | chrono = { version = "^0.4", default-features = false } | ||
| 37 | grounded = "0.2.0" | ||
| 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 | ||
| 49 | [profile.test] | ||
| 50 | codegen-units = 1 | ||
| 51 | debug = 2 | ||
| 52 | debug-assertions = true # <- | ||
| 53 | incremental = false | ||
| 54 | opt-level = 3 # <- | ||
| 55 | overflow-checks = true # <- | ||
| 56 | |||
| 57 | # cargo build/run --release | ||
| 58 | [profile.release] | ||
| 59 | codegen-units = 1 | ||
| 60 | debug = 2 | ||
| 61 | debug-assertions = false # <- | ||
| 62 | incremental = false | ||
| 63 | lto = 'fat' | ||
| 64 | opt-level = 3 # <- | ||
| 65 | overflow-checks = false # <- | ||
| 66 | |||
| 67 | # cargo test --release | ||
| 68 | [profile.bench] | ||
| 69 | codegen-units = 1 | ||
| 70 | debug = 2 | ||
| 71 | debug-assertions = false # <- | ||
| 72 | incremental = false | ||
| 73 | lto = 'fat' | ||
| 74 | opt-level = 3 # <- | ||
| 75 | overflow-checks = false # <- | ||
diff --git a/examples/stm32h755cm4/build.rs b/examples/stm32h755cm4/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/stm32h755cm4/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/stm32h755cm4/memory.x b/examples/stm32h755cm4/memory.x new file mode 100644 index 000000000..7d60354e3 --- /dev/null +++ b/examples/stm32h755cm4/memory.x | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x08100000, LENGTH = 1024K /* BANK_2 */ | ||
| 4 | RAM : ORIGIN = 0x10000000, LENGTH = 128K /* SRAM1 */ | ||
| 5 | RAM_D3 : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 */ | ||
| 6 | } | ||
| 7 | |||
| 8 | SECTIONS | ||
| 9 | { | ||
| 10 | .ram_d3 : | ||
| 11 | { | ||
| 12 | *(.ram_d3.shared_data) | ||
| 13 | *(.ram_d3) | ||
| 14 | } > RAM_D3 | ||
| 15 | } \ No newline at end of file | ||
diff --git a/examples/stm32h755cm4/src/bin/blinky.rs b/examples/stm32h755cm4/src/bin/blinky.rs new file mode 100644 index 000000000..b5c547839 --- /dev/null +++ b/examples/stm32h755cm4/src/bin/blinky.rs | |||
| @@ -0,0 +1,32 @@ | |||
| 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::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[link_section = ".ram_d3.shared_data"] | ||
| 14 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let p = embassy_stm32::init_secondary(&SHARED_DATA); | ||
| 19 | info!("Hello World!"); | ||
| 20 | |||
| 21 | let mut led = Output::new(p.PE1, Level::High, Speed::Low); | ||
| 22 | |||
| 23 | loop { | ||
| 24 | info!("high"); | ||
| 25 | led.set_high(); | ||
| 26 | Timer::after_millis(250).await; | ||
| 27 | |||
| 28 | info!("low"); | ||
| 29 | led.set_low(); | ||
| 30 | Timer::after_millis(250).await; | ||
| 31 | } | ||
| 32 | } | ||
diff --git a/examples/stm32h755cm7/.cargo/config.toml b/examples/stm32h755cm7/.cargo/config.toml new file mode 100644 index 000000000..193e6bbc3 --- /dev/null +++ b/examples/stm32h755cm7/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv7em-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip STM32H755ZITx --catch-hardfault --always-print-stacktrace' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml new file mode 100644 index 000000000..4f0f69c3f --- /dev/null +++ b/examples/stm32h755cm7/Cargo.toml | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32h755cm7-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | # Change stm32h743bi to your chip name, if necessary. | ||
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } | ||
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | ||
| 11 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } | ||
| 12 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||
| 13 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | ||
| 15 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } | ||
| 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 17 | |||
| 18 | defmt = "0.3" | ||
| 19 | defmt-rtt = "0.4" | ||
| 20 | |||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 22 | cortex-m-rt = "0.7.0" | ||
| 23 | embedded-hal = "0.2.6" | ||
| 24 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 25 | embedded-hal-async = { version = "1.0" } | ||
| 26 | embedded-nal-async = { version = "0.7.1" } | ||
| 27 | embedded-io-async = { version = "0.6.1" } | ||
| 28 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 29 | heapless = { version = "0.8", default-features = false } | ||
| 30 | rand_core = "0.6.3" | ||
| 31 | critical-section = "1.1" | ||
| 32 | micromath = "2.0.0" | ||
| 33 | stm32-fmc = "0.3.0" | ||
| 34 | embedded-storage = "0.3.1" | ||
| 35 | static_cell = "2" | ||
| 36 | chrono = { version = "^0.4", default-features = false } | ||
| 37 | grounded = "0.2.0" | ||
| 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 | ||
| 49 | [profile.test] | ||
| 50 | codegen-units = 1 | ||
| 51 | debug = 2 | ||
| 52 | debug-assertions = true # <- | ||
| 53 | incremental = false | ||
| 54 | opt-level = 3 # <- | ||
| 55 | overflow-checks = true # <- | ||
| 56 | |||
| 57 | # cargo build/run --release | ||
| 58 | [profile.release] | ||
| 59 | codegen-units = 1 | ||
| 60 | debug = 2 | ||
| 61 | debug-assertions = false # <- | ||
| 62 | incremental = false | ||
| 63 | lto = 'fat' | ||
| 64 | opt-level = 3 # <- | ||
| 65 | overflow-checks = false # <- | ||
| 66 | |||
| 67 | # cargo test --release | ||
| 68 | [profile.bench] | ||
| 69 | codegen-units = 1 | ||
| 70 | debug = 2 | ||
| 71 | debug-assertions = false # <- | ||
| 72 | incremental = false | ||
| 73 | lto = 'fat' | ||
| 74 | opt-level = 3 # <- | ||
| 75 | overflow-checks = false # <- | ||
diff --git a/examples/stm32h755cm7/build.rs b/examples/stm32h755cm7/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/stm32h755cm7/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/stm32h755cm7/memory.x b/examples/stm32h755cm7/memory.x new file mode 100644 index 000000000..ef884796a --- /dev/null +++ b/examples/stm32h755cm7/memory.x | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x08000000, LENGTH = 1024K /* BANK_1 */ | ||
| 4 | RAM : ORIGIN = 0x24000000, LENGTH = 512K /* AXIRAM */ | ||
| 5 | RAM_D3 : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 */ | ||
| 6 | } | ||
| 7 | |||
| 8 | SECTIONS | ||
| 9 | { | ||
| 10 | .ram_d3 : | ||
| 11 | { | ||
| 12 | *(.ram_d3.shared_data) | ||
| 13 | *(.ram_d3) | ||
| 14 | } > RAM_D3 | ||
| 15 | } \ No newline at end of file | ||
diff --git a/examples/stm32h755cm7/src/bin/blinky.rs b/examples/stm32h755cm7/src/bin/blinky.rs new file mode 100644 index 000000000..94d2226c0 --- /dev/null +++ b/examples/stm32h755cm7/src/bin/blinky.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 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::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[link_section = ".ram_d3.shared_data"] | ||
| 14 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let mut config = embassy_stm32::Config::default(); | ||
| 19 | { | ||
| 20 | use embassy_stm32::rcc::*; | ||
| 21 | config.rcc.hsi = Some(HSIPrescaler::DIV1); | ||
| 22 | config.rcc.csi = true; | ||
| 23 | config.rcc.pll1 = Some(Pll { | ||
| 24 | source: PllSource::HSI, | ||
| 25 | prediv: PllPreDiv::DIV4, | ||
| 26 | mul: PllMul::MUL50, | ||
| 27 | divp: Some(PllDiv::DIV2), | ||
| 28 | divq: Some(PllDiv::DIV8), // 100mhz | ||
| 29 | divr: None, | ||
| 30 | }); | ||
| 31 | config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz | ||
| 32 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz | ||
| 33 | config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 34 | config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 35 | config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 36 | config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 37 | config.rcc.voltage_scale = VoltageScale::Scale1; | ||
| 38 | config.rcc.supply_config = SupplyConfig::DirectSMPS; | ||
| 39 | } | ||
| 40 | let p = embassy_stm32::init_primary(config, &SHARED_DATA); | ||
| 41 | info!("Hello World!"); | ||
| 42 | |||
| 43 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | ||
| 44 | |||
| 45 | loop { | ||
| 46 | info!("high"); | ||
| 47 | led.set_high(); | ||
| 48 | Timer::after_millis(500).await; | ||
| 49 | |||
| 50 | info!("low"); | ||
| 51 | led.set_low(); | ||
| 52 | Timer::after_millis(500).await; | ||
| 53 | } | ||
| 54 | } | ||
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 13d33320f..f97dfd722 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml | |||
| @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32h743bi to your chip name, if necessary. | 8 | # Change stm32h743bi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } | 13 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 16 | 16 | ||
| 17 | defmt = "0.3" | 17 | defmt = "0.3" |
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 5b0519ac4..2577f19e0 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32l072cz to your chip name, if necessary. | 8 | # Change stm32l072cz to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
| 15 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
diff --git a/examples/stm32l0/src/bin/async-tsc.rs b/examples/stm32l0/src/bin/async-tsc.rs new file mode 100644 index 000000000..c40b86af9 --- /dev/null +++ b/examples/stm32l0/src/bin/async-tsc.rs | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | // Example of async TSC (Touch Sensing Controller) that lights an LED when touch is detected. | ||
| 2 | // | ||
| 3 | // Suggested physical setup on STM32L073RZ Nucleo board: | ||
| 4 | // - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. | ||
| 5 | // - Connect one end of a 1K resistor to pin A1 and leave the other end loose. | ||
| 6 | // The loose end will act as touch sensor which will register your touch. | ||
| 7 | // | ||
| 8 | // Troubleshooting the setup: | ||
| 9 | // - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, | ||
| 10 | // now the led should light up. Next try using a different value for the sampling capacitor. | ||
| 11 | // Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. | ||
| 12 | // | ||
| 13 | // All configuration values and sampling capacitor value have been determined experimentally. | ||
| 14 | // Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. | ||
| 15 | // | ||
| 16 | #![no_std] | ||
| 17 | #![no_main] | ||
| 18 | |||
| 19 | use defmt::*; | ||
| 20 | use embassy_stm32::bind_interrupts; | ||
| 21 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 22 | use embassy_stm32::tsc::{self, *}; | ||
| 23 | use embassy_time::Timer; | ||
| 24 | use {defmt_rtt as _, panic_probe as _}; | ||
| 25 | |||
| 26 | bind_interrupts!(struct Irqs { | ||
| 27 | TSC => InterruptHandler<embassy_stm32::peripherals::TSC>; | ||
| 28 | }); | ||
| 29 | |||
| 30 | #[cortex_m_rt::exception] | ||
| 31 | unsafe fn HardFault(_: &cortex_m_rt::ExceptionFrame) -> ! { | ||
| 32 | cortex_m::peripheral::SCB::sys_reset(); | ||
| 33 | } | ||
| 34 | |||
| 35 | /// This example is written for the nucleo-stm32l073rz, with a stm32l073rz chip. | ||
| 36 | /// | ||
| 37 | /// Make sure you check/update the following (whether you use the L073RZ or another board): | ||
| 38 | /// | ||
| 39 | /// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32L073RZTx`chip name. | ||
| 40 | /// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for L073RZ it should be `stm32l073rz`. | ||
| 41 | /// * [ ] If your board has a special clock or power configuration, make sure that it is | ||
| 42 | /// set up appropriately. | ||
| 43 | /// * [ ] If your board has different pin mapping, update any pin numbers or peripherals | ||
| 44 | /// to match your schematic | ||
| 45 | /// | ||
| 46 | /// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 47 | /// | ||
| 48 | /// * Which example you are trying to run | ||
| 49 | /// * Which chip and board you are using | ||
| 50 | /// | ||
| 51 | /// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
| 52 | #[embassy_executor::main] | ||
| 53 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 54 | let device_config = embassy_stm32::Config::default(); | ||
| 55 | let context = embassy_stm32::init(device_config); | ||
| 56 | |||
| 57 | let config = tsc::Config { | ||
| 58 | ct_pulse_high_length: ChargeTransferPulseCycle::_4, | ||
| 59 | ct_pulse_low_length: ChargeTransferPulseCycle::_4, | ||
| 60 | spread_spectrum: false, | ||
| 61 | spread_spectrum_deviation: SSDeviation::new(2).unwrap(), | ||
| 62 | spread_spectrum_prescaler: false, | ||
| 63 | pulse_generator_prescaler: PGPrescalerDivider::_16, | ||
| 64 | max_count_value: MaxCount::_255, | ||
| 65 | io_default_mode: false, | ||
| 66 | synchro_pin_polarity: false, | ||
| 67 | acquisition_mode: false, | ||
| 68 | max_count_interrupt: false, | ||
| 69 | channel_ios: TscIOPin::Group1Io1.into(), | ||
| 70 | shield_ios: 0, // no shield | ||
| 71 | sampling_ios: TscIOPin::Group1Io2.into(), | ||
| 72 | }; | ||
| 73 | |||
| 74 | let mut g1: PinGroup<embassy_stm32::peripherals::TSC, G1> = PinGroup::new(); | ||
| 75 | g1.set_io1(context.PA0, PinType::Sample); | ||
| 76 | g1.set_io2(context.PA1, PinType::Channel); | ||
| 77 | |||
| 78 | let mut touch_controller = tsc::Tsc::new_async( | ||
| 79 | context.TSC, | ||
| 80 | Some(g1), | ||
| 81 | None, | ||
| 82 | None, | ||
| 83 | None, | ||
| 84 | None, | ||
| 85 | None, | ||
| 86 | None, | ||
| 87 | None, | ||
| 88 | config, | ||
| 89 | Irqs, | ||
| 90 | ); | ||
| 91 | |||
| 92 | // Check if TSC is ready | ||
| 93 | if touch_controller.get_state() != State::Ready { | ||
| 94 | info!("TSC not ready!"); | ||
| 95 | loop {} // Halt execution | ||
| 96 | } | ||
| 97 | info!("TSC initialized successfully"); | ||
| 98 | |||
| 99 | // LED2 on the STM32L073RZ nucleo-board (PA5) | ||
| 100 | let mut led = Output::new(context.PA5, Level::High, Speed::Low); | ||
| 101 | |||
| 102 | // smaller sample capacitor discharge faster and can be used with shorter delay. | ||
| 103 | let discharge_delay = 5; // ms | ||
| 104 | |||
| 105 | info!("Starting touch_controller interface"); | ||
| 106 | loop { | ||
| 107 | touch_controller.start(); | ||
| 108 | touch_controller.pend_for_acquisition().await; | ||
| 109 | touch_controller.discharge_io(true); | ||
| 110 | Timer::after_millis(discharge_delay).await; | ||
| 111 | |||
| 112 | let grp1_status = touch_controller.group_get_status(Group::One); | ||
| 113 | match grp1_status { | ||
| 114 | GroupStatus::Complete => { | ||
| 115 | let group_one_val = touch_controller.group_get_value(Group::One); | ||
| 116 | info!("{}", group_one_val); | ||
| 117 | led.set_high(); | ||
| 118 | } | ||
| 119 | GroupStatus::Ongoing => led.set_low(), | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
diff --git a/examples/stm32l0/src/bin/blocking-tsc.rs b/examples/stm32l0/src/bin/blocking-tsc.rs new file mode 100644 index 000000000..7e4f40946 --- /dev/null +++ b/examples/stm32l0/src/bin/blocking-tsc.rs | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | // Example of polling TSC (Touch Sensing Controller) that lights an LED when touch is detected. | ||
| 2 | // | ||
| 3 | // Suggested physical setup on STM32L073RZ Nucleo board: | ||
| 4 | // - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. | ||
| 5 | // - Connect one end of a 1K resistor to pin A1 and leave the other end loose. | ||
| 6 | // The loose end will act as touch sensor which will register your touch. | ||
| 7 | // | ||
| 8 | // Troubleshooting the setup: | ||
| 9 | // - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, | ||
| 10 | // now the led should light up. Next try using a different value for the sampling capacitor. | ||
| 11 | // Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. | ||
| 12 | // | ||
| 13 | // All configuration values and sampling capacitor value have been determined experimentally. | ||
| 14 | // Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. | ||
| 15 | // | ||
| 16 | #![no_std] | ||
| 17 | #![no_main] | ||
| 18 | |||
| 19 | use defmt::*; | ||
| 20 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 21 | use embassy_stm32::tsc::{self, *}; | ||
| 22 | use embassy_time::Timer; | ||
| 23 | use {defmt_rtt as _, panic_probe as _}; | ||
| 24 | |||
| 25 | /// This example is written for the nucleo-stm32l073rz, with a stm32l073rz chip. | ||
| 26 | /// | ||
| 27 | /// Make sure you check/update the following (whether you use the L073RZ or another board): | ||
| 28 | /// | ||
| 29 | /// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32L073RZTx`chip name. | ||
| 30 | /// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for L073RZ it should be `stm32l073rz`. | ||
| 31 | /// * [ ] If your board has a special clock or power configuration, make sure that it is | ||
| 32 | /// set up appropriately. | ||
| 33 | /// * [ ] If your board has different pin mapping, update any pin numbers or peripherals | ||
| 34 | /// to match your schematic | ||
| 35 | /// | ||
| 36 | /// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 37 | /// | ||
| 38 | /// * Which example you are trying to run | ||
| 39 | /// * Which chip and board you are using | ||
| 40 | /// | ||
| 41 | /// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
| 42 | #[embassy_executor::main] | ||
| 43 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 44 | let device_config = embassy_stm32::Config::default(); | ||
| 45 | let context = embassy_stm32::init(device_config); | ||
| 46 | |||
| 47 | let tsc_conf = Config { | ||
| 48 | ct_pulse_high_length: ChargeTransferPulseCycle::_4, | ||
| 49 | ct_pulse_low_length: ChargeTransferPulseCycle::_4, | ||
| 50 | spread_spectrum: false, | ||
| 51 | spread_spectrum_deviation: SSDeviation::new(2).unwrap(), | ||
| 52 | spread_spectrum_prescaler: false, | ||
| 53 | pulse_generator_prescaler: PGPrescalerDivider::_16, | ||
| 54 | max_count_value: MaxCount::_255, | ||
| 55 | io_default_mode: false, | ||
| 56 | synchro_pin_polarity: false, | ||
| 57 | acquisition_mode: false, | ||
| 58 | max_count_interrupt: false, | ||
| 59 | channel_ios: TscIOPin::Group1Io1.into(), | ||
| 60 | shield_ios: 0, // no shield | ||
| 61 | sampling_ios: TscIOPin::Group1Io2.into(), | ||
| 62 | }; | ||
| 63 | |||
| 64 | let mut g1: PinGroup<embassy_stm32::peripherals::TSC, G1> = PinGroup::new(); | ||
| 65 | g1.set_io1(context.PA0, PinType::Sample); | ||
| 66 | g1.set_io2(context.PA1, PinType::Channel); | ||
| 67 | |||
| 68 | let mut touch_controller = tsc::Tsc::new_blocking( | ||
| 69 | context.TSC, | ||
| 70 | Some(g1), | ||
| 71 | None, | ||
| 72 | None, | ||
| 73 | None, | ||
| 74 | None, | ||
| 75 | None, | ||
| 76 | None, | ||
| 77 | None, | ||
| 78 | tsc_conf, | ||
| 79 | ); | ||
| 80 | |||
| 81 | // Check if TSC is ready | ||
| 82 | if touch_controller.get_state() != State::Ready { | ||
| 83 | info!("TSC not ready!"); | ||
| 84 | loop {} // Halt execution | ||
| 85 | } | ||
| 86 | info!("TSC initialized successfully"); | ||
| 87 | |||
| 88 | // LED2 on the STM32L073RZ nucleo-board (PA5) | ||
| 89 | let mut led = Output::new(context.PA5, Level::High, Speed::Low); | ||
| 90 | |||
| 91 | // smaller sample capacitor discharge faster and can be used with shorter delay. | ||
| 92 | let discharge_delay = 5; // ms | ||
| 93 | |||
| 94 | // the interval at which the loop polls for new touch sensor values | ||
| 95 | let polling_interval = 100; // ms | ||
| 96 | |||
| 97 | info!("polling for touch"); | ||
| 98 | loop { | ||
| 99 | touch_controller.start(); | ||
| 100 | touch_controller.poll_for_acquisition(); | ||
| 101 | touch_controller.discharge_io(true); | ||
| 102 | Timer::after_millis(discharge_delay).await; | ||
| 103 | |||
| 104 | let grp1_status = touch_controller.group_get_status(Group::One); | ||
| 105 | match grp1_status { | ||
| 106 | GroupStatus::Complete => { | ||
| 107 | let group_one_val = touch_controller.group_get_value(Group::One); | ||
| 108 | info!("{}", group_one_val); | ||
| 109 | led.set_high(); | ||
| 110 | } | ||
| 111 | GroupStatus::Ongoing => led.set_low(), | ||
| 112 | } | ||
| 113 | |||
| 114 | Timer::after_millis(polling_interval).await; | ||
| 115 | } | ||
| 116 | } | ||
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 9e4ceac6a..062044f32 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml | |||
| @@ -6,10 +6,10 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } |
| 12 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index de2b2bd4d..c5478b17b 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml | |||
| @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32l4s5vi to your chip name, if necessary. | 8 | # Change stm32l4s5vi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } |
| 14 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" } | 15 | embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" } |
| 16 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } | 16 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } |
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 33149144c..bd633cecb 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -207,13 +207,8 @@ async fn main(spawner: Spawner) { | |||
| 207 | 207 | ||
| 208 | // Init network stack | 208 | // Init network stack |
| 209 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); | 209 | static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new(); |
| 210 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 210 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 211 | let stack = &*STACK.init(Stack::new( | 211 | let stack = &*STACK.init(Stack::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed)); |
| 212 | device, | ||
| 213 | ip_cfg, | ||
| 214 | RESOURCES.init(StackResources::<2>::new()), | ||
| 215 | seed, | ||
| 216 | )); | ||
| 217 | 212 | ||
| 218 | // Launch network task | 213 | // Launch network task |
| 219 | unwrap!(spawner.spawn(net_task(stack))); | 214 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index e4a3c8e9c..16c184de2 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml | |||
| @@ -8,12 +8,12 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32l552ze to your chip name, if necessary. | 8 | # Change stm32l552ze to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 16 | usbd-hid = "0.7.0" | 16 | usbd-hid = "0.8.1" |
| 17 | 17 | ||
| 18 | defmt = "0.3" | 18 | defmt = "0.3" |
| 19 | defmt-rtt = "0.4" | 19 | defmt-rtt = "0.4" |
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 7f73fd677..d02bac91d 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -122,13 +122,8 @@ async fn main(spawner: Spawner) { | |||
| 122 | 122 | ||
| 123 | // Init network stack | 123 | // Init network stack |
| 124 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); | 124 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); |
| 125 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | 125 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 126 | let stack = &*STACK.init(Stack::new( | 126 | let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed)); |
| 127 | device, | ||
| 128 | config, | ||
| 129 | RESOURCES.init(StackResources::<2>::new()), | ||
| 130 | seed, | ||
| 131 | )); | ||
| 132 | 127 | ||
| 133 | unwrap!(spawner.spawn(net_task(stack))); | 128 | unwrap!(spawner.spawn(net_task(stack))); |
| 134 | 129 | ||
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index afeb4dc34..2e890cdb5 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32u083rc to your chip name, if necessary. | 8 | # Change stm32u083rc to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index d0134b972..20d64c6f7 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32u585ai to your chip name, if necessary. | 8 | # Change stm32u585ai to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index c3a11b14b..1e1a0efe2 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0" | |||
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 9 | embassy-stm32 = { version = "0.1.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"] } | 10 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } |
| 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 12 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 13 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } | 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } |
| 15 | 15 | ||
| 16 | defmt = "0.3" | 16 | defmt = "0.3" |
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index dc788e15b..401281c0b 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml | |||
| @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } | 8 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } |
| 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 12 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } | 12 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 3ea7d0cbe..46af5218c 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml | |||
| @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" | |||
| 8 | # Change stm32wl55jc-cm4 to your chip name, if necessary. | 8 | # Change stm32wl55jc-cm4 to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
| 16 | defmt-rtt = "0.4" | 16 | defmt-rtt = "0.4" |
diff --git a/examples/stm32wl/memory.x b/examples/stm32wl/memory.x new file mode 100644 index 000000000..4590867a8 --- /dev/null +++ b/examples/stm32wl/memory.x | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 256K | ||
| 5 | SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128 | ||
| 6 | RAM (rwx) : ORIGIN = 0x20000080, LENGTH = 64K - 128 | ||
| 7 | } | ||
| 8 | |||
| 9 | SECTIONS | ||
| 10 | { | ||
| 11 | .shared_data : | ||
| 12 | { | ||
| 13 | *(.shared_data) | ||
| 14 | } > SHARED_RAM | ||
| 15 | } | ||
diff --git a/examples/stm32wl/src/bin/blinky.rs b/examples/stm32wl/src/bin/blinky.rs index 347bd093f..ce7d0ec58 100644 --- a/examples/stm32wl/src/bin/blinky.rs +++ b/examples/stm32wl/src/bin/blinky.rs | |||
| @@ -1,15 +1,21 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 9 | use embassy_stm32::SharedData; | ||
| 7 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 12 | ||
| 13 | #[link_section = ".shared_data"] | ||
| 14 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut led = Output::new(p.PB15, Level::High, Speed::Low); | 21 | let mut led = Output::new(p.PB15, Level::High, Speed::Low); |
diff --git a/examples/stm32wl/src/bin/button.rs b/examples/stm32wl/src/bin/button.rs index eccd211e2..8b5204479 100644 --- a/examples/stm32wl/src/bin/button.rs +++ b/examples/stm32wl/src/bin/button.rs | |||
| @@ -1,16 +1,22 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 7 | use defmt::*; |
| 6 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | 8 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; |
| 9 | use embassy_stm32::SharedData; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 11 | ||
| 12 | #[link_section = ".shared_data"] | ||
| 13 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 14 | |||
| 9 | #[entry] | 15 | #[entry] |
| 10 | fn main() -> ! { | 16 | fn main() -> ! { |
| 11 | info!("Hello World!"); | 17 | info!("Hello World!"); |
| 12 | 18 | ||
| 13 | let p = embassy_stm32::init(Default::default()); | 19 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 14 | 20 | ||
| 15 | let button = Input::new(p.PA0, Pull::Up); | 21 | let button = Input::new(p.PA0, Pull::Up); |
| 16 | let mut led1 = Output::new(p.PB15, Level::High, Speed::Low); | 22 | let mut led1 = Output::new(p.PB15, Level::High, Speed::Low); |
diff --git a/examples/stm32wl/src/bin/button_exti.rs b/examples/stm32wl/src/bin/button_exti.rs index 27d5330bd..8dd1a6a5e 100644 --- a/examples/stm32wl/src/bin/button_exti.rs +++ b/examples/stm32wl/src/bin/button_exti.rs | |||
| @@ -1,15 +1,21 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 8 | use embassy_stm32::exti::ExtiInput; |
| 7 | use embassy_stm32::gpio::Pull; | 9 | use embassy_stm32::gpio::Pull; |
| 10 | use embassy_stm32::SharedData; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 12 | ||
| 13 | #[link_section = ".shared_data"] | ||
| 14 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); |
diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index 0b7417c01..147f5d293 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs | |||
| @@ -1,14 +1,20 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use defmt::{info, unwrap}; | 6 | use defmt::{info, unwrap}; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::flash::Flash; | 8 | use embassy_stm32::flash::Flash; |
| 9 | use embassy_stm32::SharedData; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 11 | ||
| 12 | #[link_section = ".shared_data"] | ||
| 13 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 14 | |||
| 9 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 10 | async fn main(_spawner: Spawner) { | 16 | async fn main(_spawner: Spawner) { |
| 11 | let p = embassy_stm32::init(Default::default()); | 17 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 12 | info!("Hello Flash!"); | 18 | info!("Hello Flash!"); |
| 13 | 19 | ||
| 14 | const ADDR: u32 = 0x36000; | 20 | const ADDR: u32 = 0x36000; |
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 8e9fe02b2..df2ed0054 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs | |||
| @@ -1,17 +1,22 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rng::{self, Rng}; | 8 | use embassy_stm32::rng::{self, Rng}; |
| 7 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, SharedData}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 12 | ||
| 11 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
| 12 | RNG => rng::InterruptHandler<peripherals::RNG>; | 14 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 13 | }); | 15 | }); |
| 14 | 16 | ||
| 17 | #[link_section = ".shared_data"] | ||
| 18 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 19 | |||
| 15 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 21 | async fn main(_spawner: Spawner) { |
| 17 | let mut config = embassy_stm32::Config::default(); | 22 | let mut config = embassy_stm32::Config::default(); |
| @@ -32,7 +37,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2) | 37 | divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2) |
| 33 | }); | 38 | }); |
| 34 | } | 39 | } |
| 35 | let p = embassy_stm32::init(config); | 40 | let p = embassy_stm32::init_primary(config, &SHARED_DATA); |
| 36 | 41 | ||
| 37 | info!("Hello World!"); | 42 | info!("Hello World!"); |
| 38 | 43 | ||
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index cf7d6d220..69a9ddc4c 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs | |||
| @@ -1,15 +1,20 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 6 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 7 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 8 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::Config; | 11 | use embassy_stm32::{Config, SharedData}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 14 | ||
| 15 | #[link_section = ".shared_data"] | ||
| 16 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 17 | |||
| 13 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 19 | async fn main(_spawner: Spawner) { |
| 15 | let mut config = Config::default(); | 20 | let mut config = Config::default(); |
| @@ -31,7 +36,7 @@ async fn main(_spawner: Spawner) { | |||
| 31 | divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2) | 36 | divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2) |
| 32 | }); | 37 | }); |
| 33 | } | 38 | } |
| 34 | let p = embassy_stm32::init(config); | 39 | let p = embassy_stm32::init_primary(config, &SHARED_DATA); |
| 35 | info!("Hello World!"); | 40 | info!("Hello World!"); |
| 36 | 41 | ||
| 37 | let now = NaiveDate::from_ymd_opt(2020, 5, 15) | 42 | let now = NaiveDate::from_ymd_opt(2020, 5, 15) |
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs index 3637243a0..ece9b9201 100644 --- a/examples/stm32wl/src/bin/uart_async.rs +++ b/examples/stm32wl/src/bin/uart_async.rs | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::mem::MaybeUninit; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::usart::{Config, InterruptHandler, Uart}; | 8 | use embassy_stm32::usart::{Config, InterruptHandler, Uart}; |
| 7 | use embassy_stm32::{bind_interrupts, peripherals}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, SharedData}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 11 | ||
| 10 | bind_interrupts!(struct Irqs{ | 12 | bind_interrupts!(struct Irqs{ |
| @@ -12,6 +14,9 @@ bind_interrupts!(struct Irqs{ | |||
| 12 | LPUART1 => InterruptHandler<peripherals::LPUART1>; | 14 | LPUART1 => InterruptHandler<peripherals::LPUART1>; |
| 13 | }); | 15 | }); |
| 14 | 16 | ||
| 17 | #[link_section = ".shared_data"] | ||
| 18 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 19 | |||
| 15 | /* | 20 | /* |
| 16 | Pass Incoming data from LPUART1 to USART1 | 21 | Pass Incoming data from LPUART1 to USART1 |
| 17 | Example is written for the LoRa-E5 mini v1.0, | 22 | Example is written for the LoRa-E5 mini v1.0, |
| @@ -21,7 +26,7 @@ but can be surely changed for your needs. | |||
| 21 | async fn main(_spawner: Spawner) { | 26 | async fn main(_spawner: Spawner) { |
| 22 | let mut config = embassy_stm32::Config::default(); | 27 | let mut config = embassy_stm32::Config::default(); |
| 23 | config.rcc.sys = embassy_stm32::rcc::Sysclk::HSE; | 28 | config.rcc.sys = embassy_stm32::rcc::Sysclk::HSE; |
| 24 | let p = embassy_stm32::init(config); | 29 | let p = embassy_stm32::init_primary(config, &SHARED_DATA); |
| 25 | 30 | ||
| 26 | defmt::info!("Starting system"); | 31 | defmt::info!("Starting system"); |
| 27 | 32 | ||
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 9d7acc175..75de079b7 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml | |||
| @@ -9,14 +9,13 @@ crate-type = ["cdylib"] | |||
| 9 | 9 | ||
| 10 | [dependencies] | 10 | [dependencies] |
| 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } | 11 | embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } |
| 12 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "integrated-timers"] } | 12 | embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "integrated-timers"] } |
| 13 | embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["log", "wasm", ] } | 13 | embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["log", "wasm", ] } |
| 14 | 14 | ||
| 15 | wasm-logger = "0.2.0" | 15 | wasm-logger = "0.2.0" |
| 16 | wasm-bindgen = "0.2" | 16 | wasm-bindgen = "0.2" |
| 17 | web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } | 17 | web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } |
| 18 | log = "0.4.11" | 18 | log = "0.4.11" |
| 19 | critical-section = { version = "1.1", features = ["std"] } | ||
| 20 | 19 | ||
| 21 | [profile.release] | 20 | [profile.release] |
| 22 | debug = 2 | 21 | debug = 2 |
