diff --git a/Cargo.toml b/Cargo.toml index a28e17d..4773a5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,4 +17,5 @@ members = [ exclude = [ "examples/stm32f3-disco-rtic", "examples/stm32h7-nucleo-rtic", + "examples/stm32h7-nucleo-embassy", ] diff --git a/README.md b/README.md index 2ac1b36..40b8a98 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ All examples and their helper crates are located inside the Simple example using sat-rs components on a bare-metal system with constrained resources. This example uses the [RTIC](https://github.com/rtic-rs/rtic) framework on the NUCLEO-H753ZI board. +* [`stm32h7-nucleo-embassy`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/stm32h7-nucleo-embassy): + Same as `stm32h7-nucleo-rtic`, but using the [embassy](https://embassy.dev/) executor instead + of RTIC. * [`embedded-client`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/embedded-client) and [`embedded-types`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/embedded-types): Client and shared telecommand and telemetry definitions for the embedded examples. diff --git a/examples/stm32f3-disco-rtic/src/main.rs b/examples/stm32f3-disco-rtic/src/main.rs index bae2527..0654e80 100644 --- a/examples/stm32f3-disco-rtic/src/main.rs +++ b/examples/stm32f3-disco-rtic/src/main.rs @@ -281,7 +281,7 @@ async fn send_tm( response: stm32f3::Response, current_seq_count: u14, ) -> Result<(), TmSendError> { - let sp_header = SpHeader::new_for_unseg_tc(stm32f3::PUS_APID, current_seq_count, 0); + let sp_header = SpHeader::new_for_unseg_tm(stm32f3::PUS_APID, current_seq_count, 0); let tm_header = TmHeader { tc_packet_id: Some(tc_packet_id), uptime_millis: embassy_time::Instant::now().as_millis(), diff --git a/examples/stm32h7-nucleo-embassy/.cargo/config.toml.template b/examples/stm32h7-nucleo-embassy/.cargo/config.toml.template new file mode 100644 index 0000000..f01cbee --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/.cargo/config.toml.template @@ -0,0 +1,29 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs run --chip STM32H753ZITx" +# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"] + +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", + # Can be useful for debugging. + # "-Clink-args=-Map=app.map" +] + +[build] +# (`thumbv6m-*` is compatible with all ARM Cortex-M chips but using the right +# target improves performance) +# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ +# target = "thumbv7m-none-eabi" # Cortex-M3 +# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) +target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) + +[alias] +rb = "run --bin" +rrb = "run --release --bin" + +[env] +DEFMT_LOG = "info" diff --git a/examples/stm32h7-nucleo-embassy/.gitignore b/examples/stm32h7-nucleo-embassy/.gitignore new file mode 100644 index 0000000..54f6671 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/.gitignore @@ -0,0 +1,4 @@ +/target +/.cargo/config.toml +/.vscode +/app.map diff --git a/examples/stm32h7-nucleo-embassy/Cargo.lock b/examples/stm32h7-nucleo-embassy/Cargo.lock new file mode 100644 index 0000000..ef8b69f --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/Cargo.lock @@ -0,0 +1,1547 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "arbitrary-int" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993a810118f8f37e9c4411c86f1c4c940a09a7ab34b7bf2d88d06f50c553fab7" +dependencies = [ + "defmt 1.1.0", + "serde", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitbybit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d2a3353d70ac1091a33cbf31fc7e77b19091538a7e306e3740712af19807ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block-device-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e" +dependencies = [ + "aligned", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "cordyceps" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9ab7e0ca1d179628fa0172b2b97203c7fa0cd81be2448bd446fb9559ca9261" +dependencies = [ + "loom", + "tracing", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.1.0", +] + +[[package]] +name = "defmt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0a27770e9c8f719a79d8b638281f4d828f77d8fd61e0bd94451b9b85e576a0b" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f73a4a4a91609e977ae3b7bd831ffa292edfd42ad140a3244a61d805b0e05e" +dependencies = [ + "critical-section", + "defmt 1.1.0", +] + +[[package]] +name = "defmt-test" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d326e211b94939affafdf96f5c1baf8745b960037dcf763f813597d32b03d51" +dependencies = [ + "defmt 1.1.0", + "defmt-test-macros", + "semihosting", +] + +[[package]] +name = "defmt-test-macros" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7563a5468e1a1bd97f44cb75b658c2feec75af2b1389e70f4c0677b8402edd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "delegate" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0641612053b2f34fc250bb63f6630ae75de46e02ade7f457268447081d709ce" +dependencies = [ + "defmt 1.1.0", + "embassy-futures", + "embassy-hal-internal 0.4.0", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0d3b15c9d7dc4fec1d8cb77112472fb008b3b28c51ad23838d83587a6d2f1e" +dependencies = [ + "cordyceps", + "cortex-m", + "critical-section", + "defmt 1.1.0", + "document-features", + "embassy-executor-macros", + "embassy-executor-timer-queue", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11a246f53de5f97a387f40ac24726817cd0b6f833e7603baac784f29d6ff276" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "embassy-executor-timer-queue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-hal-internal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f10ce10a4dfdf6402d8e9bd63128986b96a736b1a0a6680547ed2ac55d55dba" +dependencies = [ + "num-traits", +] + +[[package]] +name = "embassy-hal-internal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568659fc53866d3d85c60fa33723fb751aa69e71507634fc2c19e7649432fb75" +dependencies = [ + "cortex-m", + "critical-section", + "defmt 1.1.0", + "num-traits", +] + +[[package]] +name = "embassy-net" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347bc855bdbdf50ed9c5a1d80e8204badb0ba149b8732dde38e1e9708ed9d313" +dependencies = [ + "defmt 1.1.0", + "document-features", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embedded-io-async 0.7.0", + "embedded-nal-async", + "heapless 0.9.3", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" +dependencies = [ + "defmt 0.3.100", +] + +[[package]] +name = "embassy-stm32" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486c0622deb5a519fc4d2cb8e3ef324f7568fcdfff201ff8fcab46557d663ceb" +dependencies = [ + "aligned", + "bit_field", + "bitflags 2.11.1", + "block-device-driver", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt 1.1.0", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal 0.5.0", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-time-queue-utils", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io 0.7.1", + "embedded-io-async 0.7.0", + "embedded-storage", + "embedded-storage-async", + "futures-util", + "heapless 0.9.3", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core 0.6.4", + "rand_core 0.9.5", + "regex", + "sdio-host", + "static_assertions", + "stm32-fmc", + "stm32-metapac", + "trait-set", + "vcell", + "volatile-register", +] + +[[package]] +name = "embassy-sync" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bbd85cf5a5ae56bdf26f618364af642d1d0a4e245cdd75cd9aabda382f65a81" +dependencies = [ + "cfg-if", + "critical-section", + "defmt 1.1.0", + "embedded-io-async 0.7.0", + "futures-core", + "futures-sink", + "heapless 0.9.3", +] + +[[package]] +name = "embassy-time" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b0c143ec626e821d4d90da51a2bd91d559d6c442b7c74a47d368c9e23d97a" +dependencies = [ + "cfg-if", + "critical-section", + "defmt 1.1.0", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee71af1b3a0deaa53eaf2d39252f83504c853646e472400b763060389b9fcc9" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-utils" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168297bf80aaf114b3c9ad589bf38b01b3009b9af7f97cd18086c5bbf96f5693" +dependencies = [ + "embassy-executor-timer-queue", + "heapless 0.9.3", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa675c5f4349b6aa0fcffc4bf9b241f18cd11b97c1f8323273fb9a5449937fbd" +dependencies = [ + "defmt 1.1.0", + "embedded-io-async 0.6.1", + "embedded-io-async 0.7.0", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb205e26d59e483e8c48f91f637ec217ec7e2cfb0b61d50482301b991b4ff431" +dependencies = [ + "critical-section", + "defmt 1.1.0", + "embassy-sync", + "embassy-time", + "embassy-usb-driver", + "portable-atomic", +] + +[[package]] +name = "embedded-alloc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2db634e07f552215f7a3572dc0a4d29760c637fcea5a8c18d2cc291f782c216c" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" +dependencies = [ + "defmt 1.1.0", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-io-async" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564b9f813c544241430e147d8bc454815ef9ac998878d30cc3055449f7fd4c0" +dependencies = [ + "defmt 1.1.0", + "embedded-io 0.7.1", +] + +[[package]] +name = "embedded-nal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-nal-async" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5a1bd585135d302f8f6d7de329310938093da6271b37a6c94b8798795c0c6d" +dependencies = [ + "embedded-io-async 0.7.0", + "embedded-nal", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "embedded-types" +version = "0.1.0" +dependencies = [ + "arbitrary-int", + "defmt 1.1.0", + "postcard", + "serde", + "spacepackets", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", +] + +[[package]] +name = "generator" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ade96dc9003043bce7c035c85a9df5a858bfb2039c5a2e6fdf00f324f6c551" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows-link", + "windows-result", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.1", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" +dependencies = [ + "defmt 1.1.0", + "hash32 0.3.1", + "stable_deref_trait", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "panic-probe" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" +dependencies = [ + "cortex-m", + "defmt 1.1.0", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "defmt 1.1.0", + "heapless 0.7.17", + "serde", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.28", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b328e2cb950eeccd55b7f55c3a963691455dcd044cfb5354f0c5e68d2c2d6ee2" + +[[package]] +name = "semihosting" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8e4abf97879f4e80db69a9fba7bd64998e9bdad25f58ef045a778e191172fd4" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "smallvec" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" + +[[package]] +name = "smoltcp" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f73d40463bba65efc9adc6370b56df76d563cc46e2482bba58351b4afb7535e" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "defmt 0.3.100", + "heapless 0.9.3", + "managed", +] + +[[package]] +name = "spacepackets" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93b9cf1b8372119e7c79383f1578f3e845b2ca2e6d07073e96f475ba354f44e3" +dependencies = [ + "arbitrary-int", + "bitbybit", + "chrono", + "crc", + "defmt 1.1.0", + "delegate", + "num-traits", + "num_enum", + "paste", + "serde", + "thiserror", + "zerocopy", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stm32-fmc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72692594faa67f052e5e06dd34460951c21e83bc55de4feb8d2666e2f15480a2" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "stm32-metapac" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74b78632cea498cfb28386a29f8bfae7476d6570a78733eb5fecbee66c2f4ce" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 0.3.100", +] + +[[package]] +name = "stm32h7-nucleo-embassy" +version = "0.1.0" +dependencies = [ + "arbitrary-int", + "cortex-m", + "cortex-m-rt", + "defmt 1.1.0", + "defmt-rtt", + "defmt-test", + "embassy-executor", + "embassy-futures", + "embassy-net", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embedded-alloc", + "embedded-types", + "panic-probe", + "postcard", + "spacepackets", + "static_cell", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trait-set" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79e2e9c9ab44c6d7c20d5976961b47e8f49ac199154daa514b77cd1ab536625" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] diff --git a/examples/stm32h7-nucleo-embassy/Cargo.toml b/examples/stm32h7-nucleo-embassy/Cargo.toml new file mode 100644 index 0000000..3f37c13 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/Cargo.toml @@ -0,0 +1,75 @@ +[package] +name = "stm32h7-nucleo-embassy" +edition = "2024" +version = "0.1.0" +default-run = "stm32h7-nucleo-embassy" + +[lib] +harness = false + +# needed for each integration test +[[test]] +name = "integration" +harness = false + +[dependencies] +embedded-types = { path = "../embedded-types", features = ["defmt"] } + +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } +arbitrary-int = "2" +cortex-m-rt = "0.7" +defmt = "1" +defmt-rtt = "1" +panic-probe = { version = "1", features = ["print-defmt"] } +embedded-alloc = "0.7" +static_cell = "2" +spacepackets = { version = "0.18", default-features = false, features = ["defmt"] } +postcard = "1" + +embassy-stm32 = { version = "0.6", features = ["stm32h753zi", "memory-x", "defmt", "time-driver-any"] } +embassy-executor = { version = "0.10", features = ["platform-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5", features = ["defmt-timestamp-uptime-ms"] } +embassy-net = { version = "0.9", features = ["medium-ethernet", "proto-ipv4", "tcp", "udp", "auto-icmp-echo-reply", "dhcpv4", "defmt"] } +embassy-sync = "0.8" +embassy-futures = "0.1" + +[dev-dependencies] +defmt-test = "0.5" + +# cargo build/run +[profile.dev] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 's' # <- +overflow-checks = true # <- + +# cargo test +[profile.test] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 3 # <- +overflow-checks = true # <- + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + +# cargo test --release +[profile.bench] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- diff --git a/examples/stm32h7-nucleo-embassy/LICENSE-APACHE b/examples/stm32h7-nucleo-embassy/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/examples/stm32h7-nucleo-embassy/README.md b/examples/stm32h7-nucleo-embassy/README.md new file mode 100644 index 0000000..c34753f --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/README.md @@ -0,0 +1,109 @@ +sat-rs embassy example for the STM32H753ZI-Nucleo board +======= + +This example application shows how the [sat-rs library](https://egit.irs.uni-stuttgart.de/rust/sat-rs) +can be used on an embedded target. +It also shows how a relatively simple OBSW could be built when no standard runtime is available. +It uses the [embassy](https://embassy.dev/) executor as the concurrency framework and the +[defmt](https://defmt.ferrous-systems.com/) framework for logging. + +This is the embassy variant of the +[`stm32h7-nucleo-rtic`](../stm32h7-nucleo-rtic) example. Both provide the same functionality. + +The STM32H753ZIT device was picked because it is one of the more powerful Cortex-M based STM32 +devices. It has more RAM available and allows commanding via Ethernet. The example is written for +the NUCLEO-H753ZI board, which uses the MB1364 Nucleo-144 board layout. + +## Pre-Requisites + +Make sure the following tools are installed: + +1. [`probe-rs`](https://probe.rs/): Application used to flash and debug the MCU. +2. Optional and recommended: [VS Code](https://code.visualstudio.com/) with + [probe-rs plugin](https://marketplace.visualstudio.com/items?itemName=probe-rs.probe-rs-debugger) + for debugging. + +## Preparing Rust and the repository + +Building an application requires the `thumbv7em-none-eabihf` cross-compiler toolchain. +If you have not installed it yet, you can do so with + +```sh +rustup target add thumbv7em-none-eabihf +``` + +A default `.cargo` config file is provided as `.cargo/config.toml.template`. The build script +copies it to `.cargo/config.toml` if that file does not exist yet. The copy is not tracked by git, +so you can change settings like the runner for your setup. + +Cargo reads the configuration before the build script runs, so the very first build on a fresh +checkout does not use it yet and might fail. Simply run the build again, or copy the file +manually beforehand: + +```sh +cp .cargo/config.toml.template .cargo/config.toml +``` + +The configuration file also sets the target so it does not always have to be specified with +the `--target` argument. + +## Building + +After that, assuming that you have a `.cargo/config.toml` setting the correct build target, +you can simply build the application with + +```sh +cargo build +``` + +## Flashing from the command line + +You can flash the application from the command line using `probe-rs`: + +```sh +probe-rs run --chip STM32H753ZITx +``` + +## Debugging with VS Code + +The Nucleo board comes with an on-board ST-Link so all that is required to flash and debug +the board is a USB cable. The code in this repository was debugged using [`probe-rs`](https://probe.rs/docs/tools/debuggerA) +and the VS Code [`probe-rs` plugin](https://marketplace.visualstudio.com/items?itemName=probe-rs.probe-rs-debugger). +Make sure to install this plugin first. + +## Commanding the board + +The board is commanded via UDP on port 7301. It gets its IP address via DHCP, so it needs to be +connected to a network with a DHCP server. The network configuration including the IP address is +logged after startup. According to the board user manual UM2407, jumper JP6 and solder bridge SB72 +must be ON when using Ethernet. The telecommands are CCSDS space packets with a +[`postcard`](https://docs.rs/postcard) serialized payload. + +The [`embedded-client`](../embedded-client) application is used to command the board. Set the +address of the board inside `embedded-client/config.toml`, for example: + +```toml +[interface] +udp_addr = "192.168.1.50:7301" +``` + +Then run the client from inside the `embedded-client` directory. For example, you can send a ping +to the MCU using + +```sh +cargo run --bin stm32h7-client -- --ping +``` + +and set the LED blink frequency to 500 ms using + +```sh +cargo run --bin stm32h7-client -- --set-led-frequency 500 +``` + +You can also pass the board address with `--udp-addr` instead of setting it inside the +configuration file. + +## Resources + +- [STM32H743ZI Ethernet link checker example](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/ethernet-nucleo-h743zi2.rs) +- [smoltcp DHCP client](https://github.com/smoltcp-rs/smoltcp/blob/main/examples/dhcp_client.rs) diff --git a/examples/stm32h7-nucleo-embassy/build.rs b/examples/stm32h7-nucleo-embassy/build.rs new file mode 100644 index 0000000..93b7aa1 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/build.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; +use std::{env, fs}; + +fn main() { + let manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let cargo_dir = manifest_dir.join(".cargo"); + let config = cargo_dir.join("config.toml"); + let config_template = cargo_dir.join("config.toml.template"); + + if !config.exists() && config_template.exists() { + fs::create_dir_all(&cargo_dir).unwrap(); + fs::copy(&config_template, &config).unwrap(); + } +} diff --git a/examples/stm32h7-nucleo-embassy/rust-toolchain.toml b/examples/stm32h7-nucleo-embassy/rust-toolchain.toml new file mode 100644 index 0000000..f66f701 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +targets = ["thumbv7em-none-eabihf"] diff --git a/examples/stm32h7-nucleo-embassy/src/bin/blinky.rs b/examples/stm32h7-nucleo-embassy/src/bin/blinky.rs new file mode 100644 index 0000000..ec3427f --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/src/bin/blinky.rs @@ -0,0 +1,43 @@ +//! Blinks an LED +//! +//! This assumes that LD1 (green) is connected to PB0, LD2 (yellow) to PE1 and LD3 (red) to +//! PB14. This assumption is true for the MB1364 Nucleo-144 board, for example the +//! NUCLEO-H753ZI. + +#![no_std] +#![no_main] +use embassy_executor::Spawner; +use embassy_stm32::gpio; +use stm32h7_nucleo_embassy as _; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + defmt::info!("Hello World!"); + let ld1 = gpio::Output::new(p.PB0, gpio::Level::High, gpio::Speed::Low); + let ld2 = gpio::Output::new(p.PE1, gpio::Level::High, gpio::Speed::Low); + let ld3 = gpio::Output::new(p.PB14, gpio::Level::High, gpio::Speed::Low); + + spawner.spawn(blink(ld1, ld2, ld3).expect("spawning blink task failed")); +} + +#[embassy_executor::task] +async fn blink( + mut ld1: gpio::Output<'static>, + mut ld2: gpio::Output<'static>, + mut ld3: gpio::Output<'static>, +) { + loop { + defmt::info!("high"); + ld1.set_high(); + ld2.set_high(); + ld3.set_high(); + embassy_time::Timer::after_millis(500).await; + + defmt::info!("low"); + ld1.set_low(); + ld2.set_low(); + ld3.set_low(); + embassy_time::Timer::after_millis(500).await; + } +} diff --git a/examples/stm32h7-nucleo-embassy/src/bin/hello.rs b/examples/stm32h7-nucleo-embassy/src/bin/hello.rs new file mode 100644 index 0000000..4fd2388 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/src/bin/hello.rs @@ -0,0 +1,13 @@ +#![no_main] +#![no_std] + +// global logger + panicking-behavior + memory layout +use stm32h7_nucleo_embassy as _; + +#[cortex_m_rt::entry] +fn main() -> ! { + loop { + defmt::println!("Hello, world!"); + cortex_m::asm::delay(100_000_000); + } +} diff --git a/examples/stm32h7-nucleo-embassy/src/lib.rs b/examples/stm32h7-nucleo-embassy/src/lib.rs new file mode 100644 index 0000000..b5b3332 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/src/lib.rs @@ -0,0 +1,34 @@ +#![no_main] +#![no_std] + +use defmt_rtt as _; +use embassy_stm32 as _; +use panic_probe as _; + +// same panicking *behavior* as `panic-probe` but doesn't print a panic message +// this prevents the panic message being printed *twice* when `defmt::panic` is invoked +#[defmt::panic_handler] +fn panic() -> ! { + cortex_m::asm::udf() +} + +/// Hardfault handler. +/// +/// Terminates the application and makes a semihosting-capable debug tool exit +/// with an error. This seems better than the default, which is to spin in a +/// loop. +#[cortex_m_rt::exception] +unsafe fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! { + panic!("unexpected hard fault"); +} + +#[cfg(test)] +#[defmt_test::tests] +mod unit_tests { + use defmt::assert; + + #[test] + fn it_works() { + assert!(true) + } +} diff --git a/examples/stm32h7-nucleo-embassy/src/main.rs b/examples/stm32h7-nucleo-embassy/src/main.rs new file mode 100644 index 0000000..f00bc79 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/src/main.rs @@ -0,0 +1,296 @@ +#![no_main] +#![no_std] +extern crate alloc; + +use core::mem::MaybeUninit; +use core::sync::atomic::{AtomicU32, Ordering}; + +use alloc::vec::Vec; +use arbitrary_int::u14; +use embassy_executor::Spawner; +use embassy_futures::select::{Either3, select3}; +use embassy_net::StackResources; +use embassy_net::udp::{PacketMetadata, UdpSocket}; +use embassy_stm32::{bind_interrupts, eth, gpio, peripherals, rng}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::{Channel, Receiver, Sender}; +use embassy_time::Timer; +use embedded_alloc::LlffHeap as Heap; +use embedded_types::{TmHeader, create_tm_packet, stm32h7, tm_size}; +use spacepackets::{CcsdsPacketCreationError, CcsdsPacketIdAndPsc, CcsdsPacketReader, SpHeader}; +use static_cell::{ConstStaticCell, StaticCell}; +// global logger + panicking-behavior + memory layout +use stm32h7_nucleo_embassy as _; + +const DEFAULT_BLINK_FREQ_MS: u32 = 1000; +const PORT: u16 = 7301; +const MTU: usize = 1500; + +const HEAP_SIZE: usize = 131_072; + +#[global_allocator] +static HEAP: Heap = Heap::empty(); + +/// Locally administered MAC address +const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; + +const TC_QUEUE_DEPTH: usize = 32; +const TM_QUEUE_DEPTH: usize = 32; + +static BLINK_FREQ_MS: AtomicU32 = AtomicU32::new(DEFAULT_BLINK_FREQ_MS); + +bind_interrupts!(struct Irqs { + ETH => eth::InterruptHandler; + HASH_RNG => rng::InterruptHandler; +}); + +type Device = eth::Ethernet< + 'static, + peripherals::ETH, + eth::GenericPhy>, +>; + +type TcSender = Sender<'static, NoopRawMutex, Vec, TC_QUEUE_DEPTH>; +type TcReceiver = Receiver<'static, NoopRawMutex, Vec, TC_QUEUE_DEPTH>; +type TmSender = Sender<'static, NoopRawMutex, Vec, TM_QUEUE_DEPTH>; +type TmReceiver = Receiver<'static, NoopRawMutex, Vec, TM_QUEUE_DEPTH>; + +struct BlinkyLeds { + led1: gpio::Output<'static>, + led2: gpio::Output<'static>, +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + defmt::println!("Starting sat-rs demo application for the STM32H753ZIT"); + + static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; + unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } + + let mut config = embassy_stm32::Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = Some(HSIPrescaler::DIV1); + config.rcc.csi = true; + config.rcc.hsi48 = Some(Default::default()); // needed for RNG + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: None, + divr: None, + }); + config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz + config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz + config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.voltage_scale = VoltageScale::Scale1; + } + let periphs = embassy_stm32::init(config); + + let link_led = gpio::Output::new(periphs.PB0, gpio::Level::Low, gpio::Speed::Medium); + // Criss-cross pattern looks cooler. + let leds = BlinkyLeds { + led1: gpio::Output::new(periphs.PE1, gpio::Level::High, gpio::Speed::Medium), + led2: gpio::Output::new(periphs.PB14, gpio::Level::Low, gpio::Speed::Medium), + }; + + static PACKETS: StaticCell> = StaticCell::new(); + // warning: Not all STM32H7 devices have the exact same pins here + // for STM32H747XIH, replace p.PB13 for PG12 + let device = eth::Ethernet::new( + PACKETS.init(eth::PacketQueue::<4, 4>::new()), + periphs.ETH, + Irqs, + periphs.PA1, // ref_clk + periphs.PA7, // CRS_DV: Carrier Sense + periphs.PC4, // RX_D0: Received Bit 0 + periphs.PC5, // RX_D1: Received Bit 1 + periphs.PG13, // TX_D0: Transmit Bit 0 + periphs.PB13, // TX_D1: Transmit Bit 1 + periphs.PG11, // TX_EN: Transmit Enable + MAC_ADDRESS, + periphs.ETH_SMA, + periphs.PA2, // mdio + periphs.PC1, // mdc + ); + + let net_config = embassy_net::Config::dhcpv4(embassy_net::DhcpConfig::default()); + + // Generate random seed. + let mut rng = rng::Rng::new(periphs.RNG, Irqs); + let mut seed = [0; 8]; + rng.fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + net_config, + RESOURCES.init(StackResources::new()), + seed, + ); + + static TC_CHANNEL: ConstStaticCell, TC_QUEUE_DEPTH>> = + ConstStaticCell::new(Channel::new()); + let tc_channel = TC_CHANNEL.take(); + static TM_CHANNEL: ConstStaticCell, TM_QUEUE_DEPTH>> = + ConstStaticCell::new(Channel::new()); + let tm_channel = TM_CHANNEL.take(); + + spawner.spawn(net_stack_task(runner).expect("spawning net stack task failed")); + spawner.spawn( + udp_task(stack, link_led, tc_channel.sender(), tm_channel.receiver()) + .expect("spawning UDP task failed"), + ); + spawner.spawn(blinky(leds).expect("spawning blinky task failed")); + spawner.spawn( + tc_handler(tc_channel.receiver(), tm_channel.sender()) + .expect("spawning TC handler task failed"), + ); +} + +#[embassy_executor::task] +async fn blinky(mut leds: BlinkyLeds) { + loop { + leds.led1.toggle(); + leds.led2.toggle(); + Timer::after_millis(BLINK_FREQ_MS.load(Ordering::Relaxed) as u64).await; + } +} + +#[embassy_executor::task] +async fn net_stack_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn udp_task( + stack: embassy_net::Stack<'static>, + mut link_led: gpio::Output<'static>, + tc_tx: TcSender, + tm_rx: TmReceiver, +) { + // Task futures are allocated statically, so these buffers do not live on the stack. + let mut rx_udp_meta = [PacketMetadata::EMPTY; 8]; + let mut tx_udp_meta = [PacketMetadata::EMPTY; 8]; + let mut rx_udp_buf = [0; MTU]; + let mut tx_udp_buf = [0; MTU]; + let mut rx_buffer = [0; MTU]; + + loop { + stack.wait_link_up().await; + link_led.set_high(); + defmt::info!("Network link is up"); + + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; + defmt::info!("Network task initialized, config: {}", stack.config_v4()); + + let mut udp = UdpSocket::new( + stack, + &mut rx_udp_meta, + &mut rx_udp_buf, + &mut tx_udp_meta, + &mut tx_udp_buf, + ); + defmt::info!("UDP socket bound to port {}", PORT); + udp.bind(PORT).expect("failed to bind UDP socket"); + let mut remote_endpoint = None; + loop { + match select3( + udp.recv_from(&mut rx_buffer), + tm_rx.receive(), + stack.wait_link_down(), + ) + .await + { + Either3::First(Ok((len, meta))) => { + remote_endpoint = Some(meta.endpoint); + defmt::debug!("UDP RX {}, Meta: {}", len, meta); + tc_tx.send(rx_buffer[0..len].to_vec()).await; + } + Either3::First(Err(e)) => { + defmt::warn!("udp receive error: {}", e); + Timer::after_millis(100).await; + } + // TM is only generated as a response to a TC, so the endpoint is usually known. + Either3::Second(packet) => match remote_endpoint { + Some(endpoint) => match udp.send_to(&packet, endpoint).await { + Ok(_) => defmt::debug!("UDP TX: {} bytes to: {}", packet.len(), endpoint), + Err(e) => defmt::warn!("udp send error: {}", e), + }, + None => defmt::warn!("dropping TM, no remote endpoint known"), + }, + Either3::Third(()) => { + defmt::warn!("Network link is down"); + link_led.set_low(); + break; + } + } + } + } +} + +#[embassy_executor::task] +async fn tc_handler(tc_rx: TcReceiver, tm_tx: TmSender) { + let mut sequence_count = u14::new(0); + loop { + let tc = tc_rx.receive().await; + defmt::info!("Received from UDP client: {}", tc.as_slice()); + let packet = match CcsdsPacketReader::new_with_checksum(&tc) { + Ok(packet) => packet, + Err(e) => { + defmt::warn!("Failed to parse received TC packet: {}", e); + continue; + } + }; + let tc_packet_id = CcsdsPacketIdAndPsc { + packet_id: packet.packet_id(), + psc: packet.psc(), + }; + let Ok(request) = postcard::from_bytes::(packet.packet_data()) else { + defmt::warn!("Failed to deserialize TC request"); + continue; + }; + let response = match request { + stm32h7::Request::Ping => { + defmt::info!("Received Ping request"); + stm32h7::Response::Ok + } + stm32h7::Request::ChangeBlinkFrequency(duration) => { + defmt::info!( + "Received blinky frequency change request: {} ms", + duration.as_millis() + ); + let freq_ms = u32::try_from(duration.as_millis()).unwrap_or(u32::MAX); + BLINK_FREQ_MS.store(freq_ms, Ordering::Relaxed); + stm32h7::Response::Ok + } + }; + if let Err(e) = send_tm(tc_packet_id, response, sequence_count, &tm_tx).await { + defmt::warn!("Failed to send TM response: {}", e); + } + sequence_count = sequence_count.wrapping_add(u14::new(1)); + } +} + +async fn send_tm( + tc_packet_id: CcsdsPacketIdAndPsc, + response: stm32h7::Response, + sequence_count: u14, + sender: &TmSender, +) -> Result<(), CcsdsPacketCreationError> { + let sp_header = SpHeader::new_for_unseg_tm(stm32h7::PUS_APID, sequence_count, 0); + let tm_header = TmHeader { + tc_packet_id: Some(tc_packet_id), + uptime_millis: embassy_time::Instant::now().as_millis(), + }; + let mut packet = alloc::vec![0; tm_size(&tm_header, &response)]; + create_tm_packet(&mut packet, sp_header, tm_header, response)?; + sender.send(packet).await; + Ok(()) +} diff --git a/examples/stm32h7-nucleo-embassy/tests/integration.rs b/examples/stm32h7-nucleo-embassy/tests/integration.rs new file mode 100644 index 0000000..2228c66 --- /dev/null +++ b/examples/stm32h7-nucleo-embassy/tests/integration.rs @@ -0,0 +1,16 @@ +#![no_std] +#![no_main] + +use stm32h7_nucleo_embassy as _; // memory layout + panic handler + +// See https://crates.io/crates/defmt-test/0.3.0 for more documentation (e.g. about the 'state' +// feature) +#[defmt_test::tests] +mod tests { + use defmt::assert; + + #[test] + fn it_works() { + assert!(true) + } +} diff --git a/examples/stm32h7-nucleo-rtic/README.md b/examples/stm32h7-nucleo-rtic/README.md index 35bba02..360507b 100644 --- a/examples/stm32h7-nucleo-rtic/README.md +++ b/examples/stm32h7-nucleo-rtic/README.md @@ -68,15 +68,6 @@ the board is a USB cable. The code in this repository was debugged using [`probe and the VS Code [`probe-rs` plugin](https://marketplace.visualstudio.com/items?itemName=probe-rs.probe-rs-debugger). Make sure to install this plugin first. -Sample configuration files are provided inside the `vscode` folder. -Use `cp vscode .vscode -r` to use them for your project. - -Some sample configuration files for VS Code were provided as well. You can simply use `Run` and `Debug` -to automatically rebuild and flash your application. - -The `tasks.json` and `launch.json` files are generic and you can use them immediately by opening -the folder in VS code or adding it to a workspace. - ## Commanding the board The board is commanded via UDP on port 7301. It gets its IP address via DHCP, so it needs to be diff --git a/examples/stm32h7-nucleo-rtic/memory.x.tmp b/examples/stm32h7-nucleo-rtic/memory.x.tmp deleted file mode 100644 index 76ce2ce..0000000 --- a/examples/stm32h7-nucleo-rtic/memory.x.tmp +++ /dev/null @@ -1,119 +0,0 @@ -/* Taken from https://github.com/stm32-rs/stm32h7xx-hal/pull/299, adapted slightly to work with */ -/* flip-link */ -MEMORY -{ - /* This file is intended for parts in the STM32H743/743v/753/753v families (RM0433), */ - /* with the exception of the STM32H742/742v parts which have a different RAM layout. */ - /* - FLASH and RAM are mandatory memory sections. */ - /* - The sum of all non-FLASH sections must add to 1060K total device RAM. */ - /* - The FLASH section size must match your device, see table below. */ - - /* FLASH */ - /* Flash is divided in two independent banks (except 750xB). */ - /* Select the appropriate FLASH size for your device. */ - /* - STM32H750xB 128K (only FLASH1) */ - /* - STM32H750xB 1M (512K + 512K) */ - /* - STM32H743xI/753xI 2M ( 1M + 1M) */ - FLASH1 : ORIGIN = 0x08000000, LENGTH = 1M - FLASH2 : ORIGIN = 0x08100000, LENGTH = 1M - - /* Data TCM */ - /* - Two contiguous 64KB RAMs. */ - /* - Used for interrupt handlers, stacks and general RAM. */ - /* - Zero wait-states. */ - /* - The DTCM is taken as the origin of the base ram. (See below.) */ - /* This is also where the interrupt table and such will live, */ - /* which is required for deterministic performance. */ - /* Need a region called RAM */ - /* DTCM : ORIGIN = 0x20000000, LENGTH = 128K */ - RAM : ORIGIN = 0x20000000, LENGTH = 128K - - /* Instruction TCM */ - /* - Used for latency-critical interrupt handlers etc. */ - /* - Zero wait-states. */ - ITCM : ORIGIN = 0x00000000, LENGTH = 64K - - /* AXI SRAM */ - /* - AXISRAM is in D1 and accessible by all system masters except BDMA. */ - /* - Suitable for application data not stored in DTCM. */ - /* - Zero wait-states. */ - AXISRAM : ORIGIN = 0x24000000, LENGTH = 512K - - /* AHB SRAM */ - /* - SRAM1-3 are in D2 and accessible by all system masters except BDMA. */ - /* Suitable for use as DMA buffers. */ - /* - SRAM4 is in D3 and additionally accessible by the BDMA. Used for BDMA */ - /* buffers, for storing application data in lower-power modes. */ - /* - Zero wait-states. */ - SRAM1 : ORIGIN = 0x30000000, LENGTH = 128K - SRAM2 : ORIGIN = 0x30020000, LENGTH = 128K - SRAM3 : ORIGIN = 0x30040000, LENGTH = 32K - SRAM4 : ORIGIN = 0x38000000, LENGTH = 64K - - /* Backup SRAM */ - BSRAM : ORIGIN = 0x38800000, LENGTH = 4K -} - -/* -/* Assign the memory regions defined above for use. */ -/* - -/* Provide the mandatory FLASH and RAM definitions for cortex-m-rt's linker script. */ -/* These do not work with flip-link */ -REGION_ALIAS(FLASH, FLASH1); -/* REGION_ALIAS(RAM, DTCM); */ - -/* The location of the stack can be overridden using the `_stack_start` symbol. */ -/* - Set the stack location at the end of RAM, using all remaining space. */ -_stack_start = ORIGIN(RAM) + LENGTH(RAM); - -/* The location of the .text section can be overridden using the */ -/* `_stext` symbol. By default it will place after .vector_table. */ -/* _stext = ORIGIN(FLASH) + 0x40c; */ - -/* Define sections for placing symbols into the extra memory regions above. */ -/* This makes them accessible from code. */ -/* - ITCM, DTCM and AXISRAM connect to a 64-bit wide bus -> align to 8 bytes. */ -/* - All other memories connect to a 32-bit wide bus -> align to 4 bytes. */ -SECTIONS { - .flash2 (NOLOAD) : ALIGN(4) { - *(.flash2 .flash2.*); - . = ALIGN(4); - } > FLASH2 - - .itcm (NOLOAD) : ALIGN(8) { - *(.itcm .itcm.*); - . = ALIGN(8); - } > ITCM - - .axisram (NOLOAD) : ALIGN(8) { - *(.axisram .axisram.*); - . = ALIGN(8); - } > AXISRAM - - .sram1 (NOLOAD) : ALIGN(8) { - *(.sram1 .sram1.*); - . = ALIGN(4); - } > SRAM1 - - .sram2 (NOLOAD) : ALIGN(8) { - *(.sram2 .sram2.*); - . = ALIGN(4); - } > SRAM2 - - .sram3 (NOLOAD) : ALIGN(4) { - *(.sram3 .sram3.*); - . = ALIGN(4); - } > SRAM3 - - .sram4 (NOLOAD) : ALIGN(4) { - *(.sram4 .sram4.*); - . = ALIGN(4); - } > SRAM4 - - .bsram (NOLOAD) : ALIGN(4) { - *(.bsram .bsram.*); - . = ALIGN(4); - } > BSRAM - -}; diff --git a/examples/stm32h7-nucleo-rtic/src/main.rs b/examples/stm32h7-nucleo-rtic/src/main.rs index 6176f29..4c5b487 100644 --- a/examples/stm32h7-nucleo-rtic/src/main.rs +++ b/examples/stm32h7-nucleo-rtic/src/main.rs @@ -371,7 +371,7 @@ mod app { TM_QUEUE_DEPTH, >, ) -> Result<(), CcsdsPacketCreationError> { - let sp_header = SpHeader::new_for_unseg_tc(stm32h7::PUS_APID, current_seq_count, 0); + let sp_header = SpHeader::new_for_unseg_tm(stm32h7::PUS_APID, current_seq_count, 0); let tm_header = TmHeader { tc_packet_id: Some(tc_packet_id), uptime_millis: embassy_time::Instant::now().as_millis(), diff --git a/justfile b/justfile index 7e0999a..06f5633 100644 --- a/justfile +++ b/justfile @@ -11,13 +11,17 @@ test: cargo nextest run --all-features cargo test --doc --all-features -embedded: embedded-stm32h7 embedded-stm32f3 +embedded: embedded-stm32h7 embedded-stm32h7-embassy embedded-stm32f3 cargo check -p satrs --target=thumbv7em-none-eabihf --no-default-features [working-directory:"examples/stm32h7-nucleo-rtic"] embedded-stm32h7: cargo build --target=thumbv7em-none-eabihf --release +[working-directory:"examples/stm32h7-nucleo-embassy"] +embedded-stm32h7-embassy: + cargo build --target=thumbv7em-none-eabihf --release + [working-directory:"examples/stm32f3-disco-rtic"] embedded-stm32f3: cargo build --target=thumbv7em-none-eabihf --release diff --git a/satrs/src/legacy/event_man.rs b/satrs/src/legacy/event_man.rs index 58f8bc6..c7dbab7 100644 --- a/satrs/src/legacy/event_man.rs +++ b/satrs/src/legacy/event_man.rs @@ -39,12 +39,8 @@ //! //! # Examples //! -//! You can check [integration test](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/pus_events.rs) -//! for a concrete example using multi-threading where events are routed to -//! different threads. -//! //! The [example-std](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std) -//! also contains a full event manager instance and exposes a test event via the PUS test service. +//! contains a full event manager instance and exposes a test event via the PUS test service. //! The [PUS event](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std/src/legacy/pus/event.rs) //! module and the generic [events module](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std/src/legacy/events.rs) //! show how the event management modules can be integrated into a more complex software. diff --git a/satrs/src/legacy/event_man_legacy.rs b/satrs/src/legacy/event_man_legacy.rs index e743b71..0958747 100644 --- a/satrs/src/legacy/event_man_legacy.rs +++ b/satrs/src/legacy/event_man_legacy.rs @@ -41,12 +41,8 @@ //! //! # Examples //! -//! You can check [integration test](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/pus_events.rs) -//! for a concrete example using multi-threading where events are routed to -//! different threads. -//! //! The [example-std](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std) -//! also contains a full event manager instance and exposes a test event via the PUS test service. +//! contains a full event manager instance and exposes a test event via the PUS test service. //! The [PUS event](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std/src/legacy/pus/event.rs) //! module and the generic [events module](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std/src/legacy/events.rs) //! show how the event management modules can be integrated into a more complex software.