Compare commits
No commits in common. "satrs-shared-v0.2.2" and "satrs-shared-v0.2.1" have entirely different histories.
satrs-shar
...
satrs-shar
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -11,9 +11,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- run: cargo check
|
- run: cargo check --release
|
||||||
# Check example with static pool configuration
|
|
||||||
- run: cargo check -p satrs-example --no-default-features
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Run Tests
|
name: Run Tests
|
||||||
@ -39,7 +37,7 @@ jobs:
|
|||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
targets: "armv7-unknown-linux-gnueabihf, thumbv7em-none-eabihf"
|
targets: "armv7-unknown-linux-gnueabihf, thumbv7em-none-eabihf"
|
||||||
- run: cargo check -p satrs --target=${{matrix.target}} --no-default-features
|
- run: cargo check -p satrs --release --target=${{matrix.target}} --no-default-features
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
name: Check formatting
|
name: Check formatting
|
||||||
|
@ -10,5 +10,5 @@ members = [
|
|||||||
|
|
||||||
exclude = [
|
exclude = [
|
||||||
"embedded-examples/stm32f3-disco-rtic",
|
"embedded-examples/stm32f3-disco-rtic",
|
||||||
"embedded-examples/stm32h7-nucleo-rtic",
|
"embedded-examples/stm32h7-rtic",
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<p align="center"> <img src="misc/satrs-logo-v2.png" width="40%"> </p>
|
<p align="center"> <img src="misc/satrs-logo-v2.png" width="40%"> </p>
|
||||||
|
|
||||||
[](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
|
[](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
|
||||||
[](https://robamu.github.io/sat-rs/book/)
|
[](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/book/)
|
||||||
[](https://crates.io/crates/satrs)
|
[](https://crates.io/crates/satrs)
|
||||||
[](https://docs.rs/satrs)
|
[](https://docs.rs/satrs)
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ sat-rs
|
|||||||
This is the repository of the sat-rs library. Its primary goal is to provide re-usable components
|
This is the repository of the sat-rs library. Its primary goal is to provide re-usable components
|
||||||
to write on-board software for remote systems like rovers or satellites. It is specifically written
|
to write on-board software for remote systems like rovers or satellites. It is specifically written
|
||||||
for the special requirements for these systems. You can find an overview of the project and the
|
for the special requirements for these systems. You can find an overview of the project and the
|
||||||
link to the [more high-level sat-rs book](https://robamu.github.io/sat-rs/book/)
|
link to the [more high-level sat-rs book](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
|
||||||
at the [IRS software projects website](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/).
|
at the [IRS software projects website](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/).
|
||||||
|
|
||||||
This is early-stage software. Important features are missing. New releases
|
This is early-stage software. Important features are missing. New releases
|
||||||
@ -38,7 +38,7 @@ This project currently contains following crates:
|
|||||||
Example of a simple example on-board software using various sat-rs components which can be run
|
Example of a simple example on-board software using various sat-rs components which can be run
|
||||||
on a host computer or on any system with a standard runtime like a Raspberry Pi.
|
on a host computer or on any system with a standard runtime like a Raspberry Pi.
|
||||||
* [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim):
|
* [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim):
|
||||||
Mini-Simulator based on [nexosim](https://github.com/asynchronics/nexosim) which
|
Mini-Simulator based on [asynchronix](https://github.com/asynchronics/asynchronix) which
|
||||||
simulates some physical devices for the `satrs-example` application device handlers.
|
simulates some physical devices for the `satrs-example` application device handlers.
|
||||||
* [`satrs-mib`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-mib):
|
* [`satrs-mib`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-mib):
|
||||||
Components to build a mission information base from the on-board software directly.
|
Components to build a mission information base from the on-board software directly.
|
||||||
|
3
docs.sh
3
docs.sh
@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
export RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options"
|
|
||||||
cargo +nightly doc --all-features --open
|
|
240
embedded-examples/stm32f3-disco-rtic/Cargo.lock
generated
240
embedded-examples/stm32f3-disco-rtic/Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "accelerometer"
|
name = "accelerometer"
|
||||||
@ -12,10 +12,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "atomic-polyfill"
|
||||||
version = "1.4.0"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bare-metal"
|
name = "bare-metal"
|
||||||
@ -68,7 +77,7 @@ version = "0.2.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
|
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version 0.4.1",
|
"rustc_version 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -79,9 +88,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.39"
|
version = "0.4.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
|
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@ -94,12 +103,8 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cobs"
|
name = "cobs"
|
||||||
version = "0.3.0"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/robamu/cobs.rs.git?branch=all_features#c70a7f30fd00a7cbdb7666dec12b437977385d40"
|
||||||
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
@ -116,22 +121,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt"
|
name = "cortex-m-rt"
|
||||||
version = "0.7.5"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6"
|
checksum = "2722f5b7d6ea8583cffa4d247044e280ccbb9fe501bed56552e2ba48b02d5f3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m-rt-macros",
|
"cortex-m-rt-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt-macros"
|
name = "cortex-m-rt-macros"
|
||||||
version = "0.7.5"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
|
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -160,15 +165,15 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "critical-section"
|
name = "critical-section"
|
||||||
version = "1.2.0"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.10"
|
version = "0.20.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"darling_macro",
|
"darling_macro",
|
||||||
@ -176,33 +181,33 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_core"
|
name = "darling_core"
|
||||||
version = "0.20.10"
|
version = "0.20.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.20.10"
|
version = "0.20.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt"
|
name = "defmt"
|
||||||
version = "0.3.10"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130"
|
checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"defmt-macros",
|
"defmt-macros",
|
||||||
@ -220,22 +225,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt-macros"
|
name = "defmt-macros"
|
||||||
version = "0.4.0"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6"
|
checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt-parser",
|
"defmt-parser",
|
||||||
"proc-macro-error2",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt-parser"
|
name = "defmt-parser"
|
||||||
version = "0.4.1"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3"
|
checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
@ -260,7 +265,7 @@ checksum = "984bc6eca246389726ac2826acc2488ca0fe5fcd6b8d9b48797021951d76a125"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -282,7 +287,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -310,15 +315,6 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
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]]
|
[[package]]
|
||||||
name = "embedded-time"
|
name = "embedded-time"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -330,23 +326,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumset"
|
name = "enumset"
|
||||||
version = "1.1.5"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293"
|
checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enumset_derive",
|
"enumset_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumset_derive"
|
name = "enumset_derive"
|
||||||
version = "0.10.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242"
|
checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -372,21 +368,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@ -430,9 +426,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heapless"
|
name = "heapless"
|
||||||
@ -452,9 +448,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.7.1"
|
version = "2.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -559,22 +555,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.7.3"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
|
checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num_enum_derive",
|
"num_enum_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum_derive"
|
name = "num_enum_derive"
|
||||||
version = "0.7.3"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -595,9 +591,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
@ -606,47 +602,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "proc-macro-error"
|
||||||
version = "1.10.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error-attr2"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error2"
|
name = "proc-macro-error-attr"
|
||||||
version = "2.0.1"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr2",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.38"
|
version = "1.0.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -662,14 +654,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic"
|
name = "rtic"
|
||||||
version = "2.1.2"
|
version = "2.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "401961431a1e491124cdd216a313fada2d395aa2b5bee2867c872fc8af7c1bc1"
|
checksum = "c443db16326376bdd64377da268f6616d5f804aba8ce799bac7d1f7f244e9d51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
"bare-metal 1.0.0",
|
"bare-metal 1.0.0",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"portable-atomic",
|
|
||||||
"rtic-core",
|
"rtic-core",
|
||||||
"rtic-macros",
|
"rtic-macros",
|
||||||
]
|
]
|
||||||
@ -691,40 +683,38 @@ checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-macros"
|
name = "rtic-macros"
|
||||||
version = "2.1.2"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac22ab522d80079b48f46ac66ded4d349e1adf81b52430d6a74faa3a7790ed80"
|
checksum = "54053598ea24b1b74937724e366558412a1777eb2680b91ef646db540982789a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"proc-macro-error2",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-monotonics"
|
name = "rtic-monotonics"
|
||||||
version = "2.0.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1cb90bcfdbbacf3ca37340cdab52ec2de5611c744095ef7889e9c50c233b748"
|
checksum = "058c2397dbd5bb4c5650a0e368c3920953e458805ff5097a0511b8147b3619d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
"fugit",
|
"fugit",
|
||||||
"portable-atomic",
|
|
||||||
"rtic-time",
|
"rtic-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-time"
|
name = "rtic-time"
|
||||||
version = "2.0.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7b1d853fa50dc125695414ce4510567a0d420221e455b1568cfa8c9aece9614"
|
checksum = "75b232e7aebc045cfea81cdd164bc2727a10aca9a4568d406d0a5661cdfd0f19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"embedded-hal 1.0.0",
|
|
||||||
"embedded-hal-async",
|
|
||||||
"fugit",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"rtic-common",
|
"rtic-common",
|
||||||
]
|
]
|
||||||
@ -740,11 +730,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.1"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver 1.0.25",
|
"semver 1.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -753,7 +743,7 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "866fcae3b683ccc37b5ad77982483a0ee01d5dc408dea5aad2117ad404b60fe1"
|
checksum = "866fcae3b683ccc37b5ad77982483a0ee01d5dc408dea5aad2117ad404b60fe1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cobs 0.2.3",
|
"cobs 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crc",
|
"crc",
|
||||||
"defmt",
|
"defmt",
|
||||||
"delegate",
|
"delegate",
|
||||||
@ -779,7 +769,7 @@ dependencies = [
|
|||||||
name = "satrs-stm32f3-disco-rtic"
|
name = "satrs-stm32f3-disco-rtic"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cobs 0.3.0",
|
"cobs 0.2.3 (git+https://github.com/robamu/cobs.rs.git?branch=all_features)",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"cortex-m-semihosting",
|
"cortex-m-semihosting",
|
||||||
@ -808,9 +798,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.25"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
|
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver-parser"
|
name = "semver-parser"
|
||||||
@ -932,9 +922,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.96"
|
version = "2.0.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -943,22 +933,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.11"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.11"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -969,9 +959,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.16"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "usb-device"
|
name = "usb-device"
|
||||||
@ -987,9 +977,9 @@ checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
@ -1008,9 +998,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
@ -1018,11 +1008,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.7.35"
|
version = "0.7.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
@ -22,11 +22,12 @@ version = "2"
|
|||||||
features = ["thumbv7-backend"]
|
features = ["thumbv7-backend"]
|
||||||
|
|
||||||
[dependencies.rtic-monotonics]
|
[dependencies.rtic-monotonics]
|
||||||
version = "2"
|
version = "1"
|
||||||
features = ["cortex-m-systick"]
|
features = ["cortex-m-systick"]
|
||||||
|
|
||||||
[dependencies.cobs]
|
[dependencies.cobs]
|
||||||
version = "0.3"
|
git = "https://github.com/robamu/cobs.rs.git"
|
||||||
|
branch = "all_features"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[dependencies.stm32f3xx-hal]
|
[dependencies.stm32f3xx-hal]
|
||||||
|
@ -15,8 +15,8 @@ use rtic::app;
|
|||||||
|
|
||||||
use heapless::{mpmc::Q8, Vec};
|
use heapless::{mpmc::Q8, Vec};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use rtic_monotonics::fugit::{MillisDurationU32, TimerInstantU32};
|
use rtic_monotonics::systick::fugit::{MillisDurationU32, TimerInstantU32};
|
||||||
use rtic_monotonics::systick::prelude::*;
|
use rtic_monotonics::systick::ExtU32;
|
||||||
use satrs::seq_count::SequenceCountProviderCore;
|
use satrs::seq_count::SequenceCountProviderCore;
|
||||||
use satrs::spacepackets::{ecss::PusPacket, ecss::WritablePusPacket};
|
use satrs::spacepackets::{ecss::PusPacket, ecss::WritablePusPacket};
|
||||||
use stm32f3xx_hal::dma::dma1;
|
use stm32f3xx_hal::dma::dma1;
|
||||||
@ -245,6 +245,8 @@ pub fn convert_pus_tc_to_request(
|
|||||||
mod app {
|
mod app {
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::slice::Iter;
|
use core::slice::Iter;
|
||||||
|
use rtic_monotonics::systick::Systick;
|
||||||
|
use rtic_monotonics::Monotonic;
|
||||||
use satrs::pus::verification::{TcStateStarted, VerificationReportCreator};
|
use satrs::pus::verification::{TcStateStarted, VerificationReportCreator};
|
||||||
use satrs::spacepackets::{ecss::tc::PusTcReader, time::cds::P_FIELD_BASE};
|
use satrs::spacepackets::{ecss::tc::PusTcReader, time::cds::P_FIELD_BASE};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
@ -257,8 +259,6 @@ mod app {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
type SerialType = Serial<USART2, (PA2<AF7<PushPull>>, PA3<AF7<PushPull>>)>;
|
type SerialType = Serial<USART2, (PA2<AF7<PushPull>>, PA3<AF7<PushPull>>)>;
|
||||||
|
|
||||||
systick_monotonic!(Mono, 1000);
|
|
||||||
|
|
||||||
#[shared]
|
#[shared]
|
||||||
struct Shared {
|
struct Shared {
|
||||||
blink_freq: MillisDurationU32,
|
blink_freq: MillisDurationU32,
|
||||||
@ -279,7 +279,8 @@ mod app {
|
|||||||
let mut rcc = cx.device.RCC.constrain();
|
let mut rcc = cx.device.RCC.constrain();
|
||||||
|
|
||||||
// Initialize the systick interrupt & obtain the token to prove that we did
|
// Initialize the systick interrupt & obtain the token to prove that we did
|
||||||
Mono::start(cx.core.SYST, 8_000_000);
|
let systick_mono_token = rtic_monotonics::create_systick_token!();
|
||||||
|
Systick::start(cx.core.SYST, 8_000_000, systick_mono_token);
|
||||||
|
|
||||||
let mut flash = cx.device.FLASH.constrain();
|
let mut flash = cx.device.FLASH.constrain();
|
||||||
let clocks = rcc
|
let clocks = rcc
|
||||||
@ -393,7 +394,7 @@ mod app {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let current_blink_freq = cx.shared.blink_freq.lock(|current| *current);
|
let current_blink_freq = cx.shared.blink_freq.lock(|current| *current);
|
||||||
Mono::delay(current_blink_freq).await;
|
Systick::delay(current_blink_freq).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,14 +412,15 @@ mod app {
|
|||||||
if is_idle {
|
if is_idle {
|
||||||
let last_completed = cx.shared.tx_shared.lock(|shared| shared.last_completed);
|
let last_completed = cx.shared.tx_shared.lock(|shared| shared.last_completed);
|
||||||
if let Some(last_completed) = last_completed {
|
if let Some(last_completed) = last_completed {
|
||||||
let elapsed_ms = (Mono::now() - last_completed).to_millis();
|
let elapsed_ms = (Systick::now() - last_completed).to_millis();
|
||||||
if elapsed_ms < MIN_DELAY_BETWEEN_TX_PACKETS_MS {
|
if elapsed_ms < MIN_DELAY_BETWEEN_TX_PACKETS_MS {
|
||||||
Mono::delay((MIN_DELAY_BETWEEN_TX_PACKETS_MS - elapsed_ms).millis()).await;
|
Systick::delay((MIN_DELAY_BETWEEN_TX_PACKETS_MS - elapsed_ms).millis())
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Check for completion after 1 ms
|
// Check for completion after 1 ms
|
||||||
Mono::delay(1.millis()).await;
|
Systick::delay(1.millis()).await;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(vec) = TM_REQUESTS.dequeue() {
|
if let Some(vec) = TM_REQUESTS.dequeue() {
|
||||||
@ -457,11 +459,11 @@ mod app {
|
|||||||
UartTxState::Transmitting(_) => (),
|
UartTxState::Transmitting(_) => (),
|
||||||
});
|
});
|
||||||
// Check for completion after 1 ms
|
// Check for completion after 1 ms
|
||||||
Mono::delay(1.millis()).await;
|
Systick::delay(1.millis()).await;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Nothing to do, and we are idle.
|
// Nothing to do, and we are idle.
|
||||||
Mono::delay(TX_HANDLER_FREQ_MS.millis()).await;
|
Systick::delay(TX_HANDLER_FREQ_MS.millis()).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,7 +657,7 @@ mod app {
|
|||||||
tx_shared.state = UartTxState::Idle(Some(TxIdle { tx, dma_channel }));
|
tx_shared.state = UartTxState::Idle(Some(TxIdle { tx, dma_channel }));
|
||||||
// We cache the last completed time to ensure that there is a minimum delay between consecutive
|
// We cache the last completed time to ensure that there is a minimum delay between consecutive
|
||||||
// transferred packets.
|
// transferred packets.
|
||||||
tx_shared.last_completed = Some(Mono::now());
|
tx_shared.last_completed = Some(Systick::now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
344
embedded-examples/stm32h7-nucleo-rtic/Cargo.lock
generated
344
embedded-examples/stm32h7-nucleo-rtic/Cargo.lock
generated
@ -1,12 +1,21 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-polyfill"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bare-metal"
|
name = "bare-metal"
|
||||||
@ -14,7 +23,7 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version 0.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -23,12 +32,6 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.13.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitfield"
|
name = "bitfield"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
@ -61,18 +64,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cobs"
|
name = "cobs"
|
||||||
version = "0.3.0"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/robamu/cobs.rs.git?branch=all_features#c70a7f30fd00a7cbdb7666dec12b437977385d40"
|
||||||
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]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
@ -89,22 +82,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt"
|
name = "cortex-m-rt"
|
||||||
version = "0.7.5"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6"
|
checksum = "2722f5b7d6ea8583cffa4d247044e280ccbb9fe501bed56552e2ba48b02d5f3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m-rt-macros",
|
"cortex-m-rt-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt-macros"
|
name = "cortex-m-rt-macros"
|
||||||
version = "0.7.5"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
|
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -133,15 +126,15 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "critical-section"
|
name = "critical-section"
|
||||||
version = "1.2.0"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt"
|
name = "defmt"
|
||||||
version = "0.3.10"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130"
|
checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"defmt-macros",
|
"defmt-macros",
|
||||||
@ -159,22 +152,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt-macros"
|
name = "defmt-macros"
|
||||||
version = "0.4.0"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6"
|
checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt-parser",
|
"defmt-parser",
|
||||||
"proc-macro-error2",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "defmt-parser"
|
name = "defmt-parser"
|
||||||
version = "0.4.1"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3"
|
checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
@ -199,41 +192,39 @@ checksum = "984bc6eca246389726ac2826acc2488ca0fe5fcd6b8d9b48797021951d76a125"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "delegate"
|
name = "delegate"
|
||||||
version = "0.13.2"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945"
|
checksum = "0ee5df75c70b95bd3aacc8e2fd098797692fb1d54121019c4de481e42f04c8a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-new"
|
name = "derive-new"
|
||||||
version = "0.7.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc"
|
checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-alloc"
|
name = "embedded-alloc"
|
||||||
version = "0.6.0"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd"
|
checksum = "ddae17915accbac2cfbc64ea0ae6e3b330e6ea124ba108dada63646fd3c6f815"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-default",
|
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"linked_list_allocator",
|
"linked_list_allocator",
|
||||||
"rlsf",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -309,21 +300,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.31"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@ -337,6 +328,15 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
|
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hash32"
|
name = "hash32"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -348,9 +348,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[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.0",
|
||||||
|
"spin",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heapless"
|
name = "heapless"
|
||||||
@ -359,32 +372,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt",
|
"defmt",
|
||||||
"hash32",
|
"hash32 0.3.1",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.7.1"
|
version = "2.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.169"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked_list_allocator"
|
name = "linked_list_allocator"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -417,22 +434,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.7.3"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
|
checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num_enum_derive",
|
"num_enum_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum_derive"
|
name = "num_enum_derive"
|
||||||
version = "0.7.3"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -453,9 +470,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
@ -465,72 +482,62 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.10.0"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
|
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error-attr2"
|
name = "proc-macro-error"
|
||||||
version = "2.0.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error2"
|
name = "proc-macro-error-attr"
|
||||||
version = "2.0.1"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr2",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.82"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.38"
|
version = "1.0.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rlsf"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"const-default",
|
|
||||||
"libc",
|
|
||||||
"svgbobdoc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic"
|
name = "rtic"
|
||||||
version = "2.1.2"
|
version = "2.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "401961431a1e491124cdd216a313fada2d395aa2b5bee2867c872fc8af7c1bc1"
|
checksum = "c443db16326376bdd64377da268f6616d5f804aba8ce799bac7d1f7f244e9d51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
"bare-metal 1.0.0",
|
"bare-metal 1.0.0",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"portable-atomic",
|
|
||||||
"rtic-core",
|
"rtic-core",
|
||||||
"rtic-macros",
|
"rtic-macros",
|
||||||
]
|
]
|
||||||
@ -552,27 +559,28 @@ checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-macros"
|
name = "rtic-macros"
|
||||||
version = "2.1.2"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac22ab522d80079b48f46ac66ded4d349e1adf81b52430d6a74faa3a7790ed80"
|
checksum = "54053598ea24b1b74937724e366558412a1777eb2680b91ef646db540982789a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"proc-macro-error2",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-monotonics"
|
name = "rtic-monotonics"
|
||||||
version = "2.0.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1cb90bcfdbbacf3ca37340cdab52ec2de5611c744095ef7889e9c50c233b748"
|
checksum = "058c2397dbd5bb4c5650a0e368c3920953e458805ff5097a0511b8147b3619d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
"fugit",
|
"fugit",
|
||||||
"portable-atomic",
|
|
||||||
"rtic-time",
|
"rtic-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -587,21 +595,18 @@ dependencies = [
|
|||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
"embedded-hal-bus",
|
"embedded-hal-bus",
|
||||||
"heapless",
|
"heapless 0.8.0",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"rtic-common",
|
"rtic-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-time"
|
name = "rtic-time"
|
||||||
version = "2.0.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7b1d853fa50dc125695414ce4510567a0d420221e455b1568cfa8c9aece9614"
|
checksum = "75b232e7aebc045cfea81cdd164bc2727a10aca9a4568d406d0a5661cdfd0f19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"embedded-hal 1.0.0",
|
|
||||||
"embedded-hal-async",
|
|
||||||
"fugit",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"rtic-common",
|
"rtic-common",
|
||||||
]
|
]
|
||||||
@ -612,7 +617,16 @@ version = "0.2.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"semver 0.9.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver 1.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -624,22 +638,20 @@ dependencies = [
|
|||||||
"defmt",
|
"defmt",
|
||||||
"delegate",
|
"delegate",
|
||||||
"derive-new",
|
"derive-new",
|
||||||
"heapless",
|
"heapless 0.7.17",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"paste",
|
"paste",
|
||||||
"satrs-shared",
|
"satrs-shared",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"spacepackets",
|
"spacepackets",
|
||||||
"static_cell",
|
|
||||||
"thiserror",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "satrs-shared"
|
name = "satrs-shared"
|
||||||
version = "0.2.1"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f10b962c131d0bcb0de06fefa5d4716cbd7f836167f90229f7f38405dc573bd3"
|
checksum = "6042477018c2d43fffccaaa5099bc299a58485139b4d31c5b276889311e474f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"spacepackets",
|
"spacepackets",
|
||||||
]
|
]
|
||||||
@ -664,6 +676,12 @@ dependencies = [
|
|||||||
"stm32h7xx-hal",
|
"stm32h7xx-hal",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -673,6 +691,12 @@ dependencies = [
|
|||||||
"semver-parser",
|
"semver-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver-parser"
|
name = "semver-parser"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -695,41 +719,39 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"defmt",
|
"defmt",
|
||||||
"heapless",
|
"heapless 0.8.0",
|
||||||
"managed",
|
"managed",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spacepackets"
|
name = "spacepackets"
|
||||||
version = "0.13.0"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "591d42bfa6af2ab308e5efd8f0870e2d0eb5dd19a141bdcb7da731f5ff9cc11c"
|
checksum = "e85574d113a06312010c0ba51aadccd4ba2806231ebe9a49fc6473d0534d8696"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc",
|
"crc",
|
||||||
"defmt",
|
"defmt",
|
||||||
"delegate",
|
"delegate",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"paste",
|
|
||||||
"thiserror",
|
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_cell"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e"
|
|
||||||
dependencies = [
|
|
||||||
"portable-atomic",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32h7"
|
name = "stm32h7"
|
||||||
version = "0.15.1"
|
version = "0.15.1"
|
||||||
@ -762,19 +784,6 @@ dependencies = [
|
|||||||
"void",
|
"void",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
@ -788,9 +797,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.96"
|
version = "2.0.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -799,35 +808,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.11"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.11"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.16"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
@ -835,6 +838,12 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -852,20 +861,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.14"
|
version = "0.7.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468"
|
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.14"
|
version = "0.7.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1"
|
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.64",
|
||||||
]
|
]
|
||||||
|
@ -21,11 +21,11 @@ defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
|
|||||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
cortex-m-semihosting = "0.5.0"
|
cortex-m-semihosting = "0.5.0"
|
||||||
stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] }
|
stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] }
|
||||||
embedded-alloc = "0.6"
|
embedded-alloc = "0.5"
|
||||||
rtic-sync = { version = "1", features = ["defmt-03"] }
|
rtic-sync = { version = "1", features = ["defmt-03"] }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.11"
|
version = "0.11.0"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4", "socket-udp", "defmt"]
|
features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4", "socket-udp", "defmt"]
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ version = "2"
|
|||||||
features = ["thumbv7-backend"]
|
features = ["thumbv7-backend"]
|
||||||
|
|
||||||
[dependencies.rtic-monotonics]
|
[dependencies.rtic-monotonics]
|
||||||
version = "2"
|
version = "1"
|
||||||
features = ["cortex-m-systick"]
|
features = ["cortex-m-systick"]
|
||||||
|
|
||||||
[dependencies.satrs]
|
[dependencies.satrs]
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use rtic::app;
|
use rtic::app;
|
||||||
use rtic_monotonics::systick::prelude::*;
|
use rtic_monotonics::systick::Systick;
|
||||||
|
use rtic_monotonics::Monotonic;
|
||||||
use satrs::pool::{PoolAddr, PoolProvider, StaticHeaplessMemoryPool};
|
use satrs::pool::{PoolAddr, PoolProvider, StaticHeaplessMemoryPool};
|
||||||
use satrs::static_subpool;
|
use satrs::static_subpool;
|
||||||
// global logger + panicking-behavior + memory layout
|
// global logger + panicking-behavior + memory layout
|
||||||
@ -12,7 +13,7 @@ use smoltcp::socket::udp::UdpMetadata;
|
|||||||
use smoltcp::socket::{dhcpv4, udp};
|
use smoltcp::socket::{dhcpv4, udp};
|
||||||
|
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
use embedded_alloc::LlffHeap as Heap;
|
use embedded_alloc::Heap;
|
||||||
use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage};
|
use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage};
|
||||||
use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr};
|
use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr};
|
||||||
use stm32h7xx_hal::ethernet;
|
use stm32h7xx_hal::ethernet;
|
||||||
@ -31,8 +32,6 @@ pub type TcSourceRx = rtic_sync::channel::Receiver<'static, PoolAddr, TC_SOURCE_
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static HEAP: Heap = Heap::empty();
|
static HEAP: Heap = Heap::empty();
|
||||||
|
|
||||||
systick_monotonic!(Mono, 1000);
|
|
||||||
|
|
||||||
// We place the memory pool buffers inside the larger AXISRAM.
|
// We place the memory pool buffers inside the larger AXISRAM.
|
||||||
pub const SUBPOOL_SMALL_NUM_BLOCKS: u16 = 32;
|
pub const SUBPOOL_SMALL_NUM_BLOCKS: u16 = 32;
|
||||||
pub const SUBPOOL_SMALL_BLOCK_SIZE: usize = 32;
|
pub const SUBPOOL_SMALL_BLOCK_SIZE: usize = 32;
|
||||||
@ -73,7 +72,7 @@ impl Net {
|
|||||||
let mut iface = Interface::new(
|
let mut iface = Interface::new(
|
||||||
config,
|
config,
|
||||||
&mut ethdev,
|
&mut ethdev,
|
||||||
smoltcp::time::Instant::from_millis(Mono::now().duration_since_epoch().to_millis()),
|
smoltcp::time::Instant::from_millis((Systick::now() - Systick::ZERO).to_millis()),
|
||||||
);
|
);
|
||||||
// Create sockets
|
// Create sockets
|
||||||
let dhcp_socket = dhcpv4::Socket::new();
|
let dhcp_socket = dhcpv4::Socket::new();
|
||||||
@ -92,7 +91,7 @@ impl Net {
|
|||||||
/// Polls on the ethernet interface. You should refer to the smoltcp
|
/// Polls on the ethernet interface. You should refer to the smoltcp
|
||||||
/// documentation for poll() to understand how to call poll efficiently
|
/// documentation for poll() to understand how to call poll efficiently
|
||||||
pub fn poll<'a>(&mut self, sockets: &'a mut SocketSet) -> bool {
|
pub fn poll<'a>(&mut self, sockets: &'a mut SocketSet) -> bool {
|
||||||
let uptime = Mono::now().duration_since_epoch();
|
let uptime = Systick::now() - Systick::ZERO;
|
||||||
let timestamp = smoltcp::time::Instant::from_millis(uptime.to_millis());
|
let timestamp = smoltcp::time::Instant::from_millis(uptime.to_millis());
|
||||||
|
|
||||||
self.iface.poll(timestamp, &mut self.ethdev, sockets)
|
self.iface.poll(timestamp, &mut self.ethdev, sockets)
|
||||||
@ -204,7 +203,8 @@ mod app {
|
|||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use rtic_monotonics::fugit::MillisDurationU32;
|
use rtic_monotonics::systick::fugit::MillisDurationU32;
|
||||||
|
use rtic_monotonics::systick::Systick;
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use stm32h7xx_hal::ethernet::{EthernetMAC, PHY};
|
use stm32h7xx_hal::ethernet::{EthernetMAC, PHY};
|
||||||
use stm32h7xx_hal::gpio::{Output, Pin};
|
use stm32h7xx_hal::gpio::{Output, Pin};
|
||||||
@ -256,7 +256,12 @@ mod app {
|
|||||||
.freeze(pwrcfg, &cx.device.SYSCFG);
|
.freeze(pwrcfg, &cx.device.SYSCFG);
|
||||||
|
|
||||||
// Initialize the systick interrupt & obtain the token to prove that we did
|
// Initialize the systick interrupt & obtain the token to prove that we did
|
||||||
Mono::start(cx.core.SYST, ccdr.clocks.sys_ck().to_Hz());
|
let systick_mono_token = rtic_monotonics::create_systick_token!();
|
||||||
|
Systick::start(
|
||||||
|
cx.core.SYST,
|
||||||
|
ccdr.clocks.sys_ck().to_Hz(),
|
||||||
|
systick_mono_token,
|
||||||
|
);
|
||||||
|
|
||||||
// Those are used in the smoltcp of the stm32h7xx-hal , I am not fully sure what they are
|
// Those are used in the smoltcp of the stm32h7xx-hal , I am not fully sure what they are
|
||||||
// good for.
|
// good for.
|
||||||
@ -372,24 +377,24 @@ mod app {
|
|||||||
|
|
||||||
shared_pool
|
shared_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_SMALL.get_mut().unwrap(),
|
unsafe { SUBPOOL_SMALL.assume_init_mut() },
|
||||||
SUBPOOL_SMALL_SIZES.get_mut().unwrap(),
|
unsafe { SUBPOOL_SMALL_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_SMALL_NUM_BLOCKS,
|
SUBPOOL_SMALL_NUM_BLOCKS,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.expect("growing heapless memory pool failed");
|
.expect("growing heapless memory pool failed");
|
||||||
shared_pool
|
shared_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_MEDIUM.get_mut().unwrap(),
|
unsafe { SUBPOOL_MEDIUM.assume_init_mut() },
|
||||||
SUBPOOL_MEDIUM_SIZES.get_mut().unwrap(),
|
unsafe { SUBPOOL_MEDIUM_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_MEDIUM_NUM_BLOCKS,
|
SUBPOOL_MEDIUM_NUM_BLOCKS,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.expect("growing heapless memory pool failed");
|
.expect("growing heapless memory pool failed");
|
||||||
shared_pool
|
shared_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_LARGE.get_mut().unwrap(),
|
unsafe { SUBPOOL_LARGE.assume_init_mut() },
|
||||||
SUBPOOL_LARGE_SIZES.get_mut().unwrap(),
|
unsafe { SUBPOOL_LARGE_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_LARGE_NUM_BLOCKS,
|
SUBPOOL_LARGE_NUM_BLOCKS,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
@ -398,7 +403,7 @@ mod app {
|
|||||||
// Set up global allocator. Use AXISRAM for the heap.
|
// Set up global allocator. Use AXISRAM for the heap.
|
||||||
#[link_section = ".axisram"]
|
#[link_section = ".axisram"]
|
||||||
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
|
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
|
||||||
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
|
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
|
||||||
|
|
||||||
eth_link_check::spawn().expect("eth link check failed");
|
eth_link_check::spawn().expect("eth link check failed");
|
||||||
blinky::spawn().expect("spawning blink task failed");
|
blinky::spawn().expect("spawning blink task failed");
|
||||||
@ -430,7 +435,7 @@ mod app {
|
|||||||
leds.led1.toggle();
|
leds.led1.toggle();
|
||||||
leds.led2.toggle();
|
leds.led2.toggle();
|
||||||
let current_blink_freq = cx.shared.blink_freq.lock(|current| *current);
|
let current_blink_freq = cx.shared.blink_freq.lock(|current| *current);
|
||||||
Mono::delay(current_blink_freq).await;
|
Systick::delay(current_blink_freq).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +457,7 @@ mod app {
|
|||||||
cx.shared.eth_link_up.lock(|link_up| *link_up = false);
|
cx.shared.eth_link_up.lock(|link_up| *link_up = false);
|
||||||
defmt::info!("Ethernet link down");
|
defmt::info!("Ethernet link down");
|
||||||
}
|
}
|
||||||
Mono::delay(100.millis()).await;
|
Systick::delay(100.millis()).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +483,7 @@ mod app {
|
|||||||
cx.local.udp.poll(sockets, pool);
|
cx.local.udp.poll(sockets, pool);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
Mono::delay(40.millis()).await;
|
Systick::delay(40.millis()).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
Software for space systems oftentimes has different requirements than the software for host
|
Software for space systems oftentimes has different requirements than the software for host
|
||||||
systems or servers. Currently, most space systems are considered embedded systems.
|
systems or servers. Currently, most space systems are considered embedded systems.
|
||||||
|
|
||||||
For these systems, the computation power and the available heap are important resources
|
For these systems, the computation power and the available heap are the most important resources
|
||||||
which are also constrained. This might make completeley heap based memory management schemes which
|
which are constrained. This might make completeley heap based memory management schemes which
|
||||||
are oftentimes used on host and server based systems unfeasable. Still, completely forbidding
|
are oftentimes used on host and server based systems unfeasable. Still, completely forbidding
|
||||||
heap allocations might make software development unnecessarilly difficult, especially in a
|
heap allocations might make software development unnecessarilly difficult, especially in a
|
||||||
time where the OBSW might be running on Linux based systems with hundreds of MBs of RAM.
|
time where the OBSW might be running on Linux based systems with hundreds of MBs of RAM.
|
||||||
|
|
||||||
A useful pattern commonly used in space systems is to limit heap allocations to program
|
A useful pattern used commonly in space systems is to limit heap allocations to program
|
||||||
initialization time and avoid frequent run-time allocations. This prevents issues like
|
initialization time and avoid frequent run-time allocations. This prevents issues like
|
||||||
running out of memory (something even Rust can not protect from) or heap fragmentation on systems
|
running out of memory (something even Rust can not protect from) or heap fragmentation on systems
|
||||||
without a MMU.
|
without a MMU.
|
||||||
|
|
||||||
# Using pre-allocated pool structures
|
# Using pre-allocated pool structures
|
||||||
|
|
||||||
A candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all
|
A huge candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all
|
||||||
candidates where the data size might vary greatly. The regular solution for host systems
|
candidates where the data size might vary greatly. The regular solution for host systems
|
||||||
might be to send around this data as a `Vec<u8>` until it is dropped. `sat-rs` provides
|
might be to send around this data as a `Vec<u8>` until it is dropped. `sat-rs` provides
|
||||||
another solution to avoid run-time allocations by offering pre-allocated static
|
another solution to avoid run-time allocations by offering pre-allocated static
|
||||||
|
@ -20,7 +20,6 @@ thiserror = "2"
|
|||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
strum = { version = "0.26", features = ["derive"] }
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
derive-new = "0.7"
|
derive-new = "0.7"
|
||||||
cfg-if = "1"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
||||||
@ -36,8 +35,8 @@ version = "0.1.1"
|
|||||||
path = "../satrs-mib"
|
path = "../satrs-mib"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
heap_tmtc = []
|
dyn_tmtc = []
|
||||||
default = ["heap_tmtc"]
|
default = ["dyn_tmtc"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
|
@ -14,7 +14,7 @@ You can run the application using `cargo run`.
|
|||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
The example has the `heap_tmtc` feature which is enabled by default. With this feature enabled,
|
The example has the `dyn_tmtc` feature which is enabled by default. With this feature enabled,
|
||||||
TMTC packets are exchanged using the heap as the backing memory instead of pre-allocated static
|
TMTC packets are exchanged using the heap as the backing memory instead of pre-allocated static
|
||||||
stores.
|
stores.
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Example client for the sat-rs example application"""
|
"""Example client for the sat-rs example application"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -12,7 +12,7 @@ authors = [
|
|||||||
{name = "Robin Mueller", email = "robin.mueller.m@gmail.com"},
|
{name = "Robin Mueller", email = "robin.mueller.m@gmail.com"},
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tmtccmd~=8.1",
|
"tmtccmd~=8.0",
|
||||||
"pydantic~=2.7"
|
"pydantic~=2.7"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
from tmtccmd.config import CmdTreeNode
|
|
||||||
|
|
||||||
|
|
||||||
def create_acs_node(mode_node: CmdTreeNode, hk_node: CmdTreeNode) -> CmdTreeNode:
|
|
||||||
acs_node = CmdTreeNode("acs", "ACS Subsystem Node")
|
|
||||||
mgm_node = CmdTreeNode("mgms", "MGM devices node")
|
|
||||||
mgm_node.add_child(mode_node)
|
|
||||||
mgm_node.add_child(hk_node)
|
|
||||||
|
|
||||||
acs_node.add_child(mgm_node)
|
|
||||||
return acs_node
|
|
@ -39,10 +39,7 @@ class EventU32:
|
|||||||
|
|
||||||
|
|
||||||
class AcsId(enum.IntEnum):
|
class AcsId(enum.IntEnum):
|
||||||
SUBSYSTEM = 1
|
MGM_0 = 0
|
||||||
MGM_ASSEMBLY = 2
|
|
||||||
MGM_0 = 3
|
|
||||||
MGM_1 = 4
|
|
||||||
|
|
||||||
|
|
||||||
class AcsHkIds(enum.IntEnum):
|
class AcsHkIds(enum.IntEnum):
|
||||||
|
@ -12,7 +12,7 @@ from pytmtc.pus_tc import create_cmd_definition_tree
|
|||||||
|
|
||||||
class SatrsConfigHook(HookBase):
|
class SatrsConfigHook(HookBase):
|
||||||
def __init__(self, json_cfg_path: str):
|
def __init__(self, json_cfg_path: str):
|
||||||
super().__init__(json_cfg_path)
|
super().__init__(json_cfg_path=json_cfg_path)
|
||||||
|
|
||||||
def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]:
|
def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]:
|
||||||
from tmtccmd.config.com import (
|
from tmtccmd.config.com import (
|
||||||
|
@ -4,7 +4,7 @@ from spacepackets.ecss.pus_3_hk import Subservice
|
|||||||
from spacepackets.ecss import PusTm
|
from spacepackets.ecss import PusTm
|
||||||
|
|
||||||
from pytmtc.common import AcsId, Apid
|
from pytmtc.common import AcsId, Apid
|
||||||
from pytmtc.acs.mgms import handle_mgm_hk_report
|
from pytmtc.mgms import handle_mgm_hk_report
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -17,9 +17,8 @@ from tmtccmd.tmtc import (
|
|||||||
)
|
)
|
||||||
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
|
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
|
||||||
|
|
||||||
from pytmtc.acs import create_acs_node
|
|
||||||
from pytmtc.common import Apid
|
from pytmtc.common import Apid
|
||||||
from pytmtc.acs.mgms import create_mgm_cmds
|
from pytmtc.mgms import create_mgm_cmds
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -68,6 +67,7 @@ class TcHandler(TcHandlerBase):
|
|||||||
|
|
||||||
|
|
||||||
def create_cmd_definition_tree() -> CmdTreeNode:
|
def create_cmd_definition_tree() -> CmdTreeNode:
|
||||||
|
|
||||||
root_node = CmdTreeNode.root_node()
|
root_node = CmdTreeNode.root_node()
|
||||||
|
|
||||||
hk_node = CmdTreeNode("hk", "Housekeeping Node", hide_children_for_print=True)
|
hk_node = CmdTreeNode("hk", "Housekeeping Node", hide_children_for_print=True)
|
||||||
@ -101,7 +101,15 @@ def create_cmd_definition_tree() -> CmdTreeNode:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
root_node.add_child(scheduler_node)
|
root_node.add_child(scheduler_node)
|
||||||
root_node.add_child(create_acs_node(mode_node, hk_node))
|
|
||||||
|
acs_node = CmdTreeNode("acs", "ACS Subsystem Node")
|
||||||
|
mgm_node = CmdTreeNode("mgms", "MGM devices node")
|
||||||
|
mgm_node.add_child(mode_node)
|
||||||
|
mgm_node.add_child(hk_node)
|
||||||
|
|
||||||
|
acs_node.add_child(mgm_node)
|
||||||
|
root_node.add_child(acs_node)
|
||||||
|
|
||||||
return root_node
|
return root_node
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
// TODO: Write the assembly
|
|
@ -1 +0,0 @@
|
|||||||
// TODO: Write dummy controller
|
|
@ -1,8 +1,7 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use satrs::hk::{HkRequest, HkRequestVariant};
|
use satrs::hk::{HkRequest, HkRequestVariant};
|
||||||
use satrs::mode_tree::{ModeChild, ModeNode};
|
|
||||||
use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender};
|
use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender};
|
||||||
use satrs_example::config::pus::PUS_MODE_SERVICE;
|
use satrs::queue::{GenericSendError, GenericTargetedMessagingError};
|
||||||
use satrs_example::{DeviceMode, TimestampHelper};
|
use satrs_example::{DeviceMode, TimestampHelper};
|
||||||
use satrs_minisim::acs::lis3mdl::{
|
use satrs_minisim::acs::lis3mdl::{
|
||||||
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
|
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
|
||||||
@ -16,18 +15,15 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use satrs::mode::{
|
use satrs::mode::{
|
||||||
ModeAndSubmode, ModeError, ModeProvider, ModeReply, ModeRequestHandler,
|
ModeAndSubmode, ModeError, ModeProvider, ModeReply, ModeRequest, ModeRequestHandler,
|
||||||
ModeRequestHandlerMpscBounded,
|
|
||||||
};
|
};
|
||||||
use satrs::pus::{EcssTmSender, PusTmVariant};
|
use satrs::pus::{EcssTmSender, PusTmVariant};
|
||||||
use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
|
use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
|
||||||
use satrs_example::config::components::NO_SENDER;
|
use satrs_example::config::components::{NO_SENDER, PUS_MODE_SERVICE};
|
||||||
|
|
||||||
use crate::hk::PusHkHelper;
|
use crate::hk::PusHkHelper;
|
||||||
use crate::pus::hk::{HkReply, HkReplyVariant};
|
use crate::pus::hk::{HkReply, HkReplyVariant};
|
||||||
use crate::requests::CompositeRequest;
|
use crate::requests::CompositeRequest;
|
||||||
use crate::spi::SpiInterface;
|
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -52,6 +48,11 @@ pub enum TransitionState {
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait SpiInterface {
|
||||||
|
type Error: Debug;
|
||||||
|
fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SpiDummyInterface {
|
pub struct SpiDummyInterface {
|
||||||
pub dummy_values: MgmLis3RawValues,
|
pub dummy_values: MgmLis3RawValues,
|
||||||
@ -128,6 +129,13 @@ pub struct MgmData {
|
|||||||
pub z: f32,
|
pub z: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct MpscModeLeafInterface {
|
||||||
|
pub request_rx: mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
|
pub reply_to_pus_tx: mpsc::Sender<GenericMessage<ModeReply>>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub reply_to_parent_tx: mpsc::SyncSender<GenericMessage<ModeReply>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BufWrapper {
|
pub struct BufWrapper {
|
||||||
tx_buf: [u8; 32],
|
tx_buf: [u8; 32],
|
||||||
@ -158,15 +166,16 @@ impl Default for ModeHelpers {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub struct MgmHandlerLis3Mdl<
|
pub struct MgmHandlerLis3Mdl<
|
||||||
ComInterface: SpiInterface,
|
ComInterface: SpiInterface,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
||||||
> {
|
> {
|
||||||
id: UniqueApidTargetId,
|
id: UniqueApidTargetId,
|
||||||
dev_str: &'static str,
|
dev_str: &'static str,
|
||||||
mode_node: ModeRequestHandlerMpscBounded,
|
mode_interface: MpscModeLeafInterface,
|
||||||
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
hk_reply_tx: mpsc::SyncSender<GenericMessage<HkReply>>,
|
hk_reply_tx: mpsc::Sender<GenericMessage<HkReply>>,
|
||||||
switch_helper: SwitchHelper,
|
switch_helper: SwitchHelper,
|
||||||
tm_sender: TmTcSender,
|
tm_sender: TmSender,
|
||||||
pub com_interface: ComInterface,
|
pub com_interface: ComInterface,
|
||||||
shared_mgm_set: Arc<Mutex<MgmData>>,
|
shared_mgm_set: Arc<Mutex<MgmData>>,
|
||||||
#[new(value = "PusHkHelper::new(id)")]
|
#[new(value = "PusHkHelper::new(id)")]
|
||||||
@ -181,8 +190,9 @@ pub struct MgmHandlerLis3Mdl<
|
|||||||
|
|
||||||
impl<
|
impl<
|
||||||
ComInterface: SpiInterface,
|
ComInterface: SpiInterface,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
||||||
> MgmHandlerLis3Mdl<ComInterface, SwitchHelper>
|
> MgmHandlerLis3Mdl<ComInterface, TmSender, SwitchHelper>
|
||||||
{
|
{
|
||||||
pub fn periodic_operation(&mut self) {
|
pub fn periodic_operation(&mut self) {
|
||||||
self.stamp_helper.update_from_now();
|
self.stamp_helper.update_from_now();
|
||||||
@ -265,28 +275,25 @@ impl<
|
|||||||
pub fn handle_mode_requests(&mut self) {
|
pub fn handle_mode_requests(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
// TODO: Only allow one set mode request per cycle?
|
// TODO: Only allow one set mode request per cycle?
|
||||||
match self.mode_node.try_recv_mode_request() {
|
match self.mode_interface.request_rx.try_recv() {
|
||||||
Ok(opt_msg) => {
|
Ok(msg) => {
|
||||||
if let Some(msg) = opt_msg {
|
let result = self.handle_mode_request(msg);
|
||||||
let result = self.handle_mode_request(msg);
|
// TODO: Trigger event?
|
||||||
// TODO: Trigger event?
|
if result.is_err() {
|
||||||
if result.is_err() {
|
log::warn!(
|
||||||
log::warn!(
|
"{}: mode request failed with error {:?}",
|
||||||
"{}: mode request failed with error {:?}",
|
self.dev_str,
|
||||||
self.dev_str,
|
result.err().unwrap()
|
||||||
result.err().unwrap()
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if e != mpsc::TryRecvError::Empty {
|
||||||
|
log::warn!("{}: failed to receive mode request: {:?}", self.dev_str, e);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => match e {
|
|
||||||
satrs::queue::GenericReceiveError::Empty => break,
|
|
||||||
satrs::queue::GenericReceiveError::TxDisconnected(e) => {
|
|
||||||
log::warn!("{}: failed to receive mode request: {:?}", self.dev_str, e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,8 +365,9 @@ impl<
|
|||||||
|
|
||||||
impl<
|
impl<
|
||||||
ComInterface: SpiInterface,
|
ComInterface: SpiInterface,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
||||||
> ModeProvider for MgmHandlerLis3Mdl<ComInterface, SwitchHelper>
|
> ModeProvider for MgmHandlerLis3Mdl<ComInterface, TmSender, SwitchHelper>
|
||||||
{
|
{
|
||||||
fn mode_and_submode(&self) -> ModeAndSubmode {
|
fn mode_and_submode(&self) -> ModeAndSubmode {
|
||||||
self.mode_helpers.current
|
self.mode_helpers.current
|
||||||
@ -368,8 +376,9 @@ impl<
|
|||||||
|
|
||||||
impl<
|
impl<
|
||||||
ComInterface: SpiInterface,
|
ComInterface: SpiInterface,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
||||||
> ModeRequestHandler for MgmHandlerLis3Mdl<ComInterface, SwitchHelper>
|
> ModeRequestHandler for MgmHandlerLis3Mdl<ComInterface, TmSender, SwitchHelper>
|
||||||
{
|
{
|
||||||
type Error = ModeError;
|
type Error = ModeError;
|
||||||
|
|
||||||
@ -377,7 +386,6 @@ impl<
|
|||||||
&mut self,
|
&mut self,
|
||||||
requestor: MessageMetadata,
|
requestor: MessageMetadata,
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
_forced: bool,
|
|
||||||
) -> Result<(), satrs::mode::ModeError> {
|
) -> Result<(), satrs::mode::ModeError> {
|
||||||
log::info!(
|
log::info!(
|
||||||
"{}: transitioning to mode {:?}",
|
"{}: transitioning to mode {:?}",
|
||||||
@ -440,9 +448,10 @@ impl<
|
|||||||
requestor.sender_id()
|
requestor.sender_id()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.mode_node
|
self.mode_interface
|
||||||
.send_mode_reply(requestor, reply)
|
.reply_to_pus_tx
|
||||||
.map_err(ModeError::Send)?;
|
.send(GenericMessage::new(requestor, reply))
|
||||||
|
.map_err(|_| GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,44 +464,17 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
|
||||||
ComInterface: SpiInterface,
|
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
|
||||||
> ModeNode for MgmHandlerLis3Mdl<ComInterface, SwitchHelper>
|
|
||||||
{
|
|
||||||
fn id(&self) -> satrs::ComponentId {
|
|
||||||
self.id.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
ComInterface: SpiInterface,
|
|
||||||
SwitchHelper: PowerSwitchInfo<PcduSwitch> + PowerSwitcherCommandSender<PcduSwitch>,
|
|
||||||
> ModeChild for MgmHandlerLis3Mdl<ComInterface, SwitchHelper>
|
|
||||||
{
|
|
||||||
type Sender = mpsc::SyncSender<GenericMessage<ModeReply>>;
|
|
||||||
|
|
||||||
fn add_mode_parent(&mut self, id: satrs::ComponentId, reply_sender: Self::Sender) {
|
|
||||||
self.mode_node.add_message_target(id, reply_sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{
|
use std::sync::{mpsc, Arc};
|
||||||
collections::HashMap,
|
|
||||||
sync::{mpsc, Arc},
|
|
||||||
};
|
|
||||||
|
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeReply, ModeRequest},
|
mode::{ModeReply, ModeRequest},
|
||||||
mode_tree::ModeParent,
|
|
||||||
power::SwitchStateBinary,
|
power::SwitchStateBinary,
|
||||||
request::{GenericMessage, UniqueApidTargetId},
|
request::{GenericMessage, UniqueApidTargetId},
|
||||||
tmtc::PacketAsVec,
|
tmtc::PacketAsVec,
|
||||||
ComponentId,
|
|
||||||
};
|
};
|
||||||
use satrs_example::config::{acs::MGM_ASSEMBLY, components::Apid};
|
use satrs_example::config::components::Apid;
|
||||||
use satrs_minisim::acs::lis3mdl::MgmLis3RawValues;
|
use satrs_minisim::acs::lis3mdl::MgmLis3RawValues;
|
||||||
|
|
||||||
use crate::{eps::TestSwitchHelper, pus::hk::HkReply, requests::CompositeRequest};
|
use crate::{eps::TestSwitchHelper, pus::hk::HkReply, requests::CompositeRequest};
|
||||||
@ -520,88 +502,49 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct MgmTestbench {
|
pub struct MgmTestbench {
|
||||||
pub mode_request_tx: mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
pub mode_request_tx: mpsc::Sender<GenericMessage<ModeRequest>>,
|
||||||
pub mode_reply_rx_to_pus: mpsc::Receiver<GenericMessage<ModeReply>>,
|
pub mode_reply_rx_to_pus: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
pub mode_reply_rx_to_parent: mpsc::Receiver<GenericMessage<ModeReply>>,
|
pub mode_reply_rx_to_parent: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
pub composite_request_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
pub composite_request_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
||||||
pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>,
|
pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
pub tm_rx: mpsc::Receiver<PacketAsVec>,
|
pub tm_rx: mpsc::Receiver<PacketAsVec>,
|
||||||
pub handler: MgmHandlerLis3Mdl<TestSpiInterface, TestSwitchHelper>,
|
pub handler:
|
||||||
}
|
MgmHandlerLis3Mdl<TestSpiInterface, mpsc::Sender<PacketAsVec>, TestSwitchHelper>,
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct MgmAssemblyMock(
|
|
||||||
pub HashMap<ComponentId, mpsc::SyncSender<GenericMessage<ModeRequest>>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ModeNode for MgmAssemblyMock {
|
|
||||||
fn id(&self) -> satrs::ComponentId {
|
|
||||||
PUS_MODE_SERVICE.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeParent for MgmAssemblyMock {
|
|
||||||
type Sender = mpsc::SyncSender<GenericMessage<ModeRequest>>;
|
|
||||||
|
|
||||||
fn add_mode_child(&mut self, id: satrs::ComponentId, request_sender: Self::Sender) {
|
|
||||||
self.0.insert(id, request_sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct PusMock {
|
|
||||||
pub request_sender_map: HashMap<ComponentId, mpsc::SyncSender<GenericMessage<ModeRequest>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeNode for PusMock {
|
|
||||||
fn id(&self) -> satrs::ComponentId {
|
|
||||||
PUS_MODE_SERVICE.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeParent for PusMock {
|
|
||||||
type Sender = mpsc::SyncSender<GenericMessage<ModeRequest>>;
|
|
||||||
|
|
||||||
fn add_mode_child(&mut self, id: satrs::ComponentId, request_sender: Self::Sender) {
|
|
||||||
self.request_sender_map.insert(id, request_sender);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MgmTestbench {
|
impl MgmTestbench {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (request_tx, request_rx) = mpsc::sync_channel(5);
|
let (request_tx, request_rx) = mpsc::channel();
|
||||||
let (reply_tx_to_pus, reply_rx_to_pus) = mpsc::sync_channel(5);
|
let (reply_tx_to_pus, reply_rx_to_pus) = mpsc::channel();
|
||||||
let (reply_tx_to_parent, reply_rx_to_parent) = mpsc::sync_channel(5);
|
let (reply_tx_to_parent, reply_rx_to_parent) = mpsc::sync_channel(5);
|
||||||
let id = UniqueApidTargetId::new(Apid::Acs as u16, 1);
|
let mode_interface = MpscModeLeafInterface {
|
||||||
let mode_node = ModeRequestHandlerMpscBounded::new(id.into(), request_rx);
|
request_rx,
|
||||||
|
reply_to_pus_tx: reply_tx_to_pus,
|
||||||
|
reply_to_parent_tx: reply_tx_to_parent,
|
||||||
|
};
|
||||||
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
||||||
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
|
let (hk_reply_tx, hk_reply_rx) = mpsc::channel();
|
||||||
let (tm_tx, tm_rx) = mpsc::sync_channel(10);
|
let (tm_tx, tm_rx) = mpsc::channel::<PacketAsVec>();
|
||||||
let tm_sender = TmTcSender::Heap(tm_tx);
|
|
||||||
let shared_mgm_set = Arc::default();
|
let shared_mgm_set = Arc::default();
|
||||||
let mut handler = MgmHandlerLis3Mdl::new(
|
|
||||||
id,
|
|
||||||
"TEST_MGM",
|
|
||||||
mode_node,
|
|
||||||
composite_request_rx,
|
|
||||||
hk_reply_tx,
|
|
||||||
TestSwitchHelper::default(),
|
|
||||||
tm_sender,
|
|
||||||
TestSpiInterface::default(),
|
|
||||||
shared_mgm_set,
|
|
||||||
);
|
|
||||||
handler.add_mode_parent(PUS_MODE_SERVICE.into(), reply_tx_to_pus);
|
|
||||||
handler.add_mode_parent(MGM_ASSEMBLY.into(), reply_tx_to_parent);
|
|
||||||
Self {
|
Self {
|
||||||
mode_request_tx: request_tx,
|
mode_request_tx: request_tx,
|
||||||
mode_reply_rx_to_pus: reply_rx_to_pus,
|
mode_reply_rx_to_pus: reply_rx_to_pus,
|
||||||
mode_reply_rx_to_parent: reply_rx_to_parent,
|
mode_reply_rx_to_parent: reply_rx_to_parent,
|
||||||
composite_request_tx,
|
composite_request_tx,
|
||||||
handler,
|
|
||||||
tm_rx,
|
tm_rx,
|
||||||
hk_reply_rx,
|
hk_reply_rx,
|
||||||
|
handler: MgmHandlerLis3Mdl::new(
|
||||||
|
UniqueApidTargetId::new(Apid::Acs as u16, 1),
|
||||||
|
"TEST_MGM",
|
||||||
|
mode_interface,
|
||||||
|
composite_request_rx,
|
||||||
|
hk_reply_tx,
|
||||||
|
TestSwitchHelper::default(),
|
||||||
|
tm_tx,
|
||||||
|
TestSpiInterface::default(),
|
||||||
|
shared_mgm_set,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,10 +575,7 @@ mod tests {
|
|||||||
.mode_request_tx
|
.mode_request_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as u32, 0)),
|
||||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.expect("failed to send mode request");
|
.expect("failed to send mode request");
|
||||||
testbench.handler.periodic_operation();
|
testbench.handler.periodic_operation();
|
||||||
@ -693,10 +633,7 @@ mod tests {
|
|||||||
.mode_request_tx
|
.mode_request_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as u32, 0)),
|
||||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.expect("failed to send mode request");
|
.expect("failed to send mode request");
|
||||||
testbench.handler.periodic_operation();
|
testbench.handler.periodic_operation();
|
||||||
|
@ -1,4 +1 @@
|
|||||||
pub mod assembly;
|
|
||||||
pub mod ctrl;
|
|
||||||
pub mod mgm;
|
pub mod mgm;
|
||||||
pub mod subsystem;
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
// TODO: Write subsystem
|
|
@ -29,7 +29,7 @@ fn main() {
|
|||||||
let res = client.recv(&mut buf);
|
let res = client.recv(&mut buf);
|
||||||
match res {
|
match res {
|
||||||
Ok(_len) => {
|
Ok(_len) => {
|
||||||
let pus_tm = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed");
|
let (pus_tm, size) = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed");
|
||||||
if pus_tm.service() == 17 && pus_tm.subservice() == 2 {
|
if pus_tm.service() == 17 && pus_tm.subservice() == 2 {
|
||||||
println!("Received PUS Ping Reply TM[17,2]")
|
println!("Received PUS Ping Reply TM[17,2]")
|
||||||
} else if pus_tm.service() == 1 {
|
} else if pus_tm.service() == 1 {
|
||||||
|
@ -135,33 +135,6 @@ pub mod components {
|
|||||||
Eps = 6,
|
Eps = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum EpsId {
|
|
||||||
Pcdu = 0,
|
|
||||||
Subsystem = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum TmtcId {
|
|
||||||
UdpServer = 0,
|
|
||||||
TcpServer = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const EPS_SUBSYSTEM: UniqueApidTargetId =
|
|
||||||
UniqueApidTargetId::new(Apid::Eps as u16, EpsId::Subsystem as u32);
|
|
||||||
pub const PCDU_HANDLER: UniqueApidTargetId =
|
|
||||||
UniqueApidTargetId::new(Apid::Eps as u16, EpsId::Pcdu as u32);
|
|
||||||
pub const UDP_SERVER: UniqueApidTargetId =
|
|
||||||
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::UdpServer as u32);
|
|
||||||
pub const TCP_SERVER: UniqueApidTargetId =
|
|
||||||
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::TcpServer as u32);
|
|
||||||
pub const NO_SENDER: ComponentId = ComponentId::MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod pus {
|
|
||||||
use super::components::Apid;
|
|
||||||
use satrs::request::UniqueApidTargetId;
|
|
||||||
|
|
||||||
// Component IDs for components with the PUS APID.
|
// Component IDs for components with the PUS APID.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum PusId {
|
pub enum PusId {
|
||||||
@ -172,6 +145,23 @@ pub mod pus {
|
|||||||
PusMode = 4,
|
PusMode = 4,
|
||||||
PusHk = 5,
|
PusHk = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum AcsId {
|
||||||
|
Mgm0 = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum EpsId {
|
||||||
|
Pcdu = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum TmtcId {
|
||||||
|
UdpServer = 0,
|
||||||
|
TcpServer = 1,
|
||||||
|
}
|
||||||
|
|
||||||
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
|
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
|
||||||
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
|
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
|
||||||
@ -186,26 +176,15 @@ pub mod pus {
|
|||||||
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusHk as u32);
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusHk as u32);
|
||||||
pub const PUS_SCHED_SERVICE: UniqueApidTargetId =
|
pub const PUS_SCHED_SERVICE: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::Sched as u16, 0);
|
UniqueApidTargetId::new(Apid::Sched as u16, 0);
|
||||||
}
|
|
||||||
|
|
||||||
pub mod acs {
|
|
||||||
use super::components::Apid;
|
|
||||||
use satrs::request::UniqueApidTargetId;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum AcsId {
|
|
||||||
Subsystem = 1,
|
|
||||||
Assembly = 2,
|
|
||||||
Mgm0 = 3,
|
|
||||||
Mgm1 = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const MGM_ASSEMBLY: UniqueApidTargetId =
|
|
||||||
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Assembly as u32);
|
|
||||||
pub const MGM_HANDLER_0: UniqueApidTargetId =
|
pub const MGM_HANDLER_0: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
|
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
|
||||||
pub const MGM_HANDLER_1: UniqueApidTargetId =
|
pub const PCDU_HANDLER: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
|
UniqueApidTargetId::new(Apid::Eps as u16, EpsId::Pcdu as u32);
|
||||||
|
pub const UDP_SERVER: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::UdpServer as u32);
|
||||||
|
pub const TCP_SERVER: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::TcpServer as u32);
|
||||||
|
pub const NO_SENDER: ComponentId = ComponentId::MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod pool {
|
pub mod pool {
|
||||||
|
@ -8,22 +8,15 @@ use derive_new::new;
|
|||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
hk::{HkRequest, HkRequestVariant},
|
hk::{HkRequest, HkRequestVariant},
|
||||||
mode::{
|
mode::{ModeAndSubmode, ModeError, ModeProvider, ModeReply, ModeRequestHandler},
|
||||||
ModeAndSubmode, ModeError, ModeProvider, ModeReply, ModeRequestHandler,
|
|
||||||
ModeRequestHandlerMpscBounded,
|
|
||||||
},
|
|
||||||
mode_tree::{ModeChild, ModeNode},
|
|
||||||
power::SwitchRequest,
|
power::SwitchRequest,
|
||||||
pus::{EcssTmSender, PusTmVariant},
|
pus::{EcssTmSender, PusTmVariant},
|
||||||
queue::GenericSendError,
|
queue::{GenericSendError, GenericTargetedMessagingError},
|
||||||
request::{GenericMessage, MessageMetadata, UniqueApidTargetId},
|
request::{GenericMessage, MessageMetadata, UniqueApidTargetId},
|
||||||
spacepackets::ByteConversionError,
|
spacepackets::ByteConversionError,
|
||||||
};
|
};
|
||||||
use satrs_example::{
|
use satrs_example::{
|
||||||
config::{
|
config::components::{NO_SENDER, PUS_MODE_SERVICE},
|
||||||
components::{NO_SENDER, PCDU_HANDLER},
|
|
||||||
pus::PUS_MODE_SERVICE,
|
|
||||||
},
|
|
||||||
DeviceMode, TimestampHelper,
|
DeviceMode, TimestampHelper,
|
||||||
};
|
};
|
||||||
use satrs_minisim::{
|
use satrs_minisim::{
|
||||||
@ -35,10 +28,10 @@ use satrs_minisim::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
acs::mgm::MpscModeLeafInterface,
|
||||||
hk::PusHkHelper,
|
hk::PusHkHelper,
|
||||||
pus::hk::{HkReply, HkReplyVariant},
|
pus::hk::{HkReply, HkReplyVariant},
|
||||||
requests::CompositeRequest,
|
requests::CompositeRequest,
|
||||||
tmtc::sender::TmTcSender,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait SerialInterface {
|
pub trait SerialInterface {
|
||||||
@ -207,14 +200,14 @@ pub type SharedSwitchSet = Arc<Mutex<SwitchSet>>;
|
|||||||
/// Example PCDU device handler.
|
/// Example PCDU device handler.
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub struct PcduHandler<ComInterface: SerialInterface> {
|
pub struct PcduHandler<ComInterface: SerialInterface, TmSender: EcssTmSender> {
|
||||||
id: UniqueApidTargetId,
|
id: UniqueApidTargetId,
|
||||||
dev_str: &'static str,
|
dev_str: &'static str,
|
||||||
mode_node: ModeRequestHandlerMpscBounded,
|
mode_interface: MpscModeLeafInterface,
|
||||||
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
hk_reply_tx: mpsc::SyncSender<GenericMessage<HkReply>>,
|
hk_reply_tx: mpsc::Sender<GenericMessage<HkReply>>,
|
||||||
switch_request_rx: mpsc::Receiver<GenericMessage<SwitchRequest>>,
|
switch_request_rx: mpsc::Receiver<GenericMessage<SwitchRequest>>,
|
||||||
tm_sender: TmTcSender,
|
tm_sender: TmSender,
|
||||||
pub com_interface: ComInterface,
|
pub com_interface: ComInterface,
|
||||||
shared_switch_map: Arc<Mutex<SwitchSet>>,
|
shared_switch_map: Arc<Mutex<SwitchSet>>,
|
||||||
#[new(value = "PusHkHelper::new(id)")]
|
#[new(value = "PusHkHelper::new(id)")]
|
||||||
@ -227,7 +220,7 @@ pub struct PcduHandler<ComInterface: SerialInterface> {
|
|||||||
tm_buf: [u8; 256],
|
tm_buf: [u8; 256],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
|
impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInterface, TmSender> {
|
||||||
pub fn periodic_operation(&mut self, op_code: OpCode) {
|
pub fn periodic_operation(&mut self, op_code: OpCode) {
|
||||||
match op_code {
|
match op_code {
|
||||||
OpCode::RegularOp => {
|
OpCode::RegularOp => {
|
||||||
@ -331,30 +324,25 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
|
|||||||
pub fn handle_mode_requests(&mut self) {
|
pub fn handle_mode_requests(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
// TODO: Only allow one set mode request per cycle?
|
// TODO: Only allow one set mode request per cycle?
|
||||||
match self.mode_node.try_recv_mode_request() {
|
match self.mode_interface.request_rx.try_recv() {
|
||||||
Ok(opt_msg) => {
|
Ok(msg) => {
|
||||||
if let Some(msg) = opt_msg {
|
let result = self.handle_mode_request(msg);
|
||||||
let result = self.handle_mode_request(msg);
|
// TODO: Trigger event?
|
||||||
// TODO: Trigger event?
|
if result.is_err() {
|
||||||
if result.is_err() {
|
log::warn!(
|
||||||
log::warn!(
|
"{}: mode request failed with error {:?}",
|
||||||
"{}: mode request failed with error {:?}",
|
self.dev_str,
|
||||||
self.dev_str,
|
result.err().unwrap()
|
||||||
result.err().unwrap()
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if e != mpsc::TryRecvError::Empty {
|
||||||
|
log::warn!("{}: failed to receive mode request: {:?}", self.dev_str, e);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => match e {
|
|
||||||
satrs::queue::GenericReceiveError::Empty => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
satrs::queue::GenericReceiveError::TxDisconnected(_) => {
|
|
||||||
log::warn!("{}: failed to receive mode request: {:?}", self.dev_str, e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,19 +396,22 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SerialInterface> ModeProvider for PcduHandler<ComInterface> {
|
impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeProvider
|
||||||
|
for PcduHandler<ComInterface, TmSender>
|
||||||
|
{
|
||||||
fn mode_and_submode(&self) -> ModeAndSubmode {
|
fn mode_and_submode(&self) -> ModeAndSubmode {
|
||||||
self.mode_and_submode
|
self.mode_and_submode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterface> {
|
impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeRequestHandler
|
||||||
|
for PcduHandler<ComInterface, TmSender>
|
||||||
|
{
|
||||||
type Error = ModeError;
|
type Error = ModeError;
|
||||||
fn start_transition(
|
fn start_transition(
|
||||||
&mut self,
|
&mut self,
|
||||||
requestor: MessageMetadata,
|
requestor: MessageMetadata,
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
_forced: bool,
|
|
||||||
) -> Result<(), satrs::mode::ModeError> {
|
) -> Result<(), satrs::mode::ModeError> {
|
||||||
log::info!(
|
log::info!(
|
||||||
"{}: transitioning to mode {:?}",
|
"{}: transitioning to mode {:?}",
|
||||||
@ -475,9 +466,10 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
|
|||||||
requestor.sender_id()
|
requestor.sender_id()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.mode_node
|
self.mode_interface
|
||||||
.send_mode_reply(requestor, reply)
|
.reply_to_pus_tx
|
||||||
.map_err(|_| GenericSendError::RxDisconnected)?;
|
.send(GenericMessage::new(requestor, reply))
|
||||||
|
.map_err(|_| GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,20 +482,6 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SerialInterface> ModeNode for PcduHandler<ComInterface> {
|
|
||||||
fn id(&self) -> satrs::ComponentId {
|
|
||||||
PCDU_HANDLER.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ComInterface: SerialInterface> ModeChild for PcduHandler<ComInterface> {
|
|
||||||
type Sender = mpsc::SyncSender<GenericMessage<ModeReply>>;
|
|
||||||
|
|
||||||
fn add_mode_parent(&mut self, id: satrs::ComponentId, reply_sender: Self::Sender) {
|
|
||||||
self.mode_node.add_message_target(id, reply_sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
@ -511,10 +489,7 @@ mod tests {
|
|||||||
use satrs::{
|
use satrs::{
|
||||||
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
|
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
|
||||||
};
|
};
|
||||||
use satrs_example::config::{
|
use satrs_example::config::components::{Apid, MGM_HANDLER_0};
|
||||||
acs::MGM_HANDLER_0,
|
|
||||||
components::{Apid, EPS_SUBSYSTEM, PCDU_HANDLER},
|
|
||||||
};
|
|
||||||
use satrs_minisim::eps::SwitchMapBinary;
|
use satrs_minisim::eps::SwitchMapBinary;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -555,41 +530,31 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct PcduTestbench {
|
pub struct PcduTestbench {
|
||||||
pub mode_request_tx: mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
pub mode_request_tx: mpsc::Sender<GenericMessage<ModeRequest>>,
|
||||||
pub mode_reply_rx_to_pus: mpsc::Receiver<GenericMessage<ModeReply>>,
|
pub mode_reply_rx_to_pus: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
pub mode_reply_rx_to_parent: mpsc::Receiver<GenericMessage<ModeReply>>,
|
pub mode_reply_rx_to_parent: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
pub composite_request_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
pub composite_request_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
||||||
pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>,
|
pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
pub tm_rx: mpsc::Receiver<PacketAsVec>,
|
pub tm_rx: mpsc::Receiver<PacketAsVec>,
|
||||||
pub switch_request_tx: mpsc::Sender<GenericMessage<SwitchRequest>>,
|
pub switch_request_tx: mpsc::Sender<GenericMessage<SwitchRequest>>,
|
||||||
pub handler: PcduHandler<SerialInterfaceTest>,
|
pub handler: PcduHandler<SerialInterfaceTest, mpsc::Sender<PacketAsVec>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PcduTestbench {
|
impl PcduTestbench {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (mode_request_tx, mode_request_rx) = mpsc::sync_channel(5);
|
let (mode_request_tx, mode_request_rx) = mpsc::channel();
|
||||||
let (mode_reply_tx_to_pus, mode_reply_rx_to_pus) = mpsc::sync_channel(5);
|
let (mode_reply_tx_to_pus, mode_reply_rx_to_pus) = mpsc::channel();
|
||||||
let (mode_reply_tx_to_parent, mode_reply_rx_to_parent) = mpsc::sync_channel(5);
|
let (mode_reply_tx_to_parent, mode_reply_rx_to_parent) = mpsc::sync_channel(5);
|
||||||
let mode_node =
|
let mode_interface = MpscModeLeafInterface {
|
||||||
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), mode_request_rx);
|
request_rx: mode_request_rx,
|
||||||
|
reply_to_pus_tx: mode_reply_tx_to_pus,
|
||||||
|
reply_to_parent_tx: mode_reply_tx_to_parent,
|
||||||
|
};
|
||||||
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
||||||
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
|
let (hk_reply_tx, hk_reply_rx) = mpsc::channel();
|
||||||
let (tm_tx, tm_rx) = mpsc::sync_channel::<PacketAsVec>(5);
|
let (tm_tx, tm_rx) = mpsc::channel::<PacketAsVec>();
|
||||||
let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
|
let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
|
||||||
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
|
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
|
||||||
let mut handler = PcduHandler::new(
|
|
||||||
UniqueApidTargetId::new(Apid::Eps as u16, 0),
|
|
||||||
"TEST_PCDU",
|
|
||||||
mode_node,
|
|
||||||
composite_request_rx,
|
|
||||||
hk_reply_tx,
|
|
||||||
switch_reqest_rx,
|
|
||||||
TmTcSender::Heap(tm_tx.clone()),
|
|
||||||
SerialInterfaceTest::default(),
|
|
||||||
shared_switch_map,
|
|
||||||
);
|
|
||||||
handler.add_mode_parent(EPS_SUBSYSTEM.into(), mode_reply_tx_to_parent);
|
|
||||||
handler.add_mode_parent(PUS_MODE_SERVICE.into(), mode_reply_tx_to_pus);
|
|
||||||
Self {
|
Self {
|
||||||
mode_request_tx,
|
mode_request_tx,
|
||||||
mode_reply_rx_to_pus,
|
mode_reply_rx_to_pus,
|
||||||
@ -598,7 +563,17 @@ mod tests {
|
|||||||
hk_reply_rx,
|
hk_reply_rx,
|
||||||
tm_rx,
|
tm_rx,
|
||||||
switch_request_tx,
|
switch_request_tx,
|
||||||
handler,
|
handler: PcduHandler::new(
|
||||||
|
UniqueApidTargetId::new(Apid::Eps as u16, 0),
|
||||||
|
"TEST_PCDU",
|
||||||
|
mode_interface,
|
||||||
|
composite_request_rx,
|
||||||
|
hk_reply_tx,
|
||||||
|
switch_reqest_rx,
|
||||||
|
tm_tx,
|
||||||
|
SerialInterfaceTest::default(),
|
||||||
|
shared_switch_map,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,10 +660,7 @@ mod tests {
|
|||||||
.mode_request_tx
|
.mode_request_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as u32, 0)),
|
||||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.expect("failed to send mode request");
|
.expect("failed to send mode request");
|
||||||
let switch_map_shared = testbench.handler.shared_switch_map.lock().unwrap();
|
let switch_map_shared = testbench.handler.shared_switch_map.lock().unwrap();
|
||||||
@ -720,10 +692,7 @@ mod tests {
|
|||||||
.mode_request_tx
|
.mode_request_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as u32, 0)),
|
||||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.expect("failed to send mode request");
|
.expect("failed to send mode request");
|
||||||
testbench
|
testbench
|
||||||
|
@ -16,7 +16,7 @@ use satrs::{
|
|||||||
},
|
},
|
||||||
spacepackets::time::cds::CdsTime,
|
spacepackets::time::cds::CdsTime,
|
||||||
};
|
};
|
||||||
use satrs_example::config::pus::PUS_EVENT_MANAGEMENT;
|
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
||||||
|
|
||||||
use crate::update_time;
|
use crate::update_time;
|
||||||
|
|
||||||
@ -281,7 +281,9 @@ mod tests {
|
|||||||
.try_recv()
|
.try_recv()
|
||||||
.expect("failed to receive TM packet");
|
.expect("failed to receive TM packet");
|
||||||
assert_eq!(tm_packet.sender_id, PUS_EVENT_MANAGEMENT.id());
|
assert_eq!(tm_packet.sender_id, PUS_EVENT_MANAGEMENT.id());
|
||||||
let tm_reader = PusTmReader::new(&tm_packet.packet, 7).expect("failed to create TM reader");
|
let tm_reader = PusTmReader::new(&tm_packet.packet, 7)
|
||||||
|
.expect("failed to create TM reader")
|
||||||
|
.0;
|
||||||
assert_eq!(tm_reader.apid(), TEST_CREATOR_ID.apid);
|
assert_eq!(tm_reader.apid(), TEST_CREATOR_ID.apid);
|
||||||
assert_eq!(tm_reader.user_data().len(), 4);
|
assert_eq!(tm_reader.user_data().len(), 4);
|
||||||
let event_read_back = EventU32::from_be_bytes(tm_reader.user_data().try_into().unwrap());
|
let event_read_back = EventU32::from_be_bytes(tm_reader.user_data().try_into().unwrap());
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashSet, VecDeque},
|
collections::{HashSet, VecDeque},
|
||||||
|
fmt::Debug,
|
||||||
|
marker::PhantomData,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use satrs::tmtc::StoreAndSendError;
|
|
||||||
use satrs::{
|
use satrs::{
|
||||||
encoding::ccsds::{SpValidity, SpacePacketValidator},
|
encoding::ccsds::{SpValidity, SpacePacketValidator},
|
||||||
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
|
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
|
||||||
spacepackets::{CcsdsPacket, PacketId},
|
spacepackets::{CcsdsPacket, PacketId},
|
||||||
tmtc::PacketSource,
|
tmtc::{PacketSenderRaw, PacketSource},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ConnectionFinishedHandler {}
|
pub struct ConnectionFinishedHandler {}
|
||||||
|
|
||||||
@ -112,23 +111,31 @@ pub type TcpServer<ReceivesTc, SendError> = TcpSpacepacketsServer<
|
|||||||
SendError,
|
SendError,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub struct TcpTask(pub TcpServer<TmTcSender, StoreAndSendError>);
|
pub struct TcpTask<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>(
|
||||||
|
pub TcpServer<TcSender, SendError>,
|
||||||
|
PhantomData<SendError>,
|
||||||
|
);
|
||||||
|
|
||||||
impl TcpTask {
|
impl<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>
|
||||||
|
TcpTask<TcSender, SendError>
|
||||||
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: SyncTcpTmSource,
|
tm_source: SyncTcpTmSource,
|
||||||
tc_sender: TmTcSender,
|
tc_sender: TcSender,
|
||||||
valid_ids: HashSet<PacketId>,
|
valid_ids: HashSet<PacketId>,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self(TcpSpacepacketsServer::new(
|
Ok(Self(
|
||||||
cfg,
|
TcpSpacepacketsServer::new(
|
||||||
tm_source,
|
cfg,
|
||||||
tc_sender,
|
tm_source,
|
||||||
SimplePacketValidator { valid_ids },
|
tc_sender,
|
||||||
ConnectionFinishedHandler::default(),
|
SimplePacketValidator { valid_ids },
|
||||||
None,
|
ConnectionFinishedHandler::default(),
|
||||||
)?))
|
None,
|
||||||
|
)?,
|
||||||
|
PhantomData,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn periodic_operation(&mut self) {
|
pub fn periodic_operation(&mut self) {
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
|
use core::fmt::Debug;
|
||||||
use std::net::{SocketAddr, UdpSocket};
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use satrs::pus::HandlingStatus;
|
use satrs::pus::HandlingStatus;
|
||||||
use satrs::tmtc::{PacketAsVec, PacketInPool, StoreAndSendError};
|
use satrs::tmtc::{PacketAsVec, PacketInPool, PacketSenderRaw};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
hal::std::udp_server::{ReceiveResult, UdpTcServer},
|
hal::std::udp_server::{ReceiveResult, UdpTcServer},
|
||||||
pool::{PoolProviderWithGuards, SharedStaticMemoryPool},
|
pool::{PoolProviderWithGuards, SharedStaticMemoryPool},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
|
|
||||||
pub trait UdpTmHandler {
|
pub trait UdpTmHandler {
|
||||||
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, recv_addr: &SocketAddr);
|
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, recv_addr: &SocketAddr);
|
||||||
}
|
}
|
||||||
@ -66,12 +65,21 @@ impl UdpTmHandler for DynamicUdpTmHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UdpTmtcServer<TmHandler: UdpTmHandler> {
|
pub struct UdpTmtcServer<
|
||||||
pub udp_tc_server: UdpTcServer<TmTcSender, StoreAndSendError>,
|
TcSender: PacketSenderRaw<Error = SendError>,
|
||||||
|
TmHandler: UdpTmHandler,
|
||||||
|
SendError,
|
||||||
|
> {
|
||||||
|
pub udp_tc_server: UdpTcServer<TcSender, SendError>,
|
||||||
pub tm_handler: TmHandler,
|
pub tm_handler: TmHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TmHandler: UdpTmHandler> UdpTmtcServer<TmHandler> {
|
impl<
|
||||||
|
TcSender: PacketSenderRaw<Error = SendError>,
|
||||||
|
TmHandler: UdpTmHandler,
|
||||||
|
SendError: Debug + 'static,
|
||||||
|
> UdpTmtcServer<TcSender, TmHandler, SendError>
|
||||||
|
{
|
||||||
pub fn periodic_operation(&mut self) {
|
pub fn periodic_operation(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
if self.poll_tc_server() == HandlingStatus::Empty {
|
if self.poll_tc_server() == HandlingStatus::Empty {
|
||||||
@ -107,6 +115,7 @@ impl<TmHandler: UdpTmHandler> UdpTmtcServer<TmHandler> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
net::IpAddr,
|
net::IpAddr,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
@ -117,16 +126,30 @@ mod tests {
|
|||||||
ecss::{tc::PusTcCreator, WritablePusPacket},
|
ecss::{tc::PusTcCreator, WritablePusPacket},
|
||||||
SpHeader,
|
SpHeader,
|
||||||
},
|
},
|
||||||
|
tmtc::PacketSenderRaw,
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
use satrs_example::config::{components, OBSW_SERVER_ADDR};
|
use satrs_example::config::{components, OBSW_SERVER_ADDR};
|
||||||
|
|
||||||
use crate::tmtc::sender::{MockSender, TmTcSender};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const UDP_SERVER_ID: ComponentId = 0x05;
|
const UDP_SERVER_ID: ComponentId = 0x05;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct TestSender {
|
||||||
|
tc_vec: RefCell<VecDeque<PacketAsVec>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketSenderRaw for TestSender {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
let mut mut_queue = self.tc_vec.borrow_mut();
|
||||||
|
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct TestTmHandler {
|
pub struct TestTmHandler {
|
||||||
addrs_to_send_to: Arc<Mutex<VecDeque<SocketAddr>>>,
|
addrs_to_send_to: Arc<Mutex<VecDeque<SocketAddr>>>,
|
||||||
@ -141,7 +164,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), 0);
|
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), 0);
|
||||||
let test_receiver = TmTcSender::Mock(MockSender::default());
|
let test_receiver = TestSender::default();
|
||||||
|
// let tc_queue = test_receiver.tc_vec.clone();
|
||||||
let udp_tc_server =
|
let udp_tc_server =
|
||||||
UdpTcServer::new(UDP_SERVER_ID, sock_addr, 2048, test_receiver).unwrap();
|
UdpTcServer::new(UDP_SERVER_ID, sock_addr, 2048, test_receiver).unwrap();
|
||||||
let tm_handler = TestTmHandler::default();
|
let tm_handler = TestTmHandler::default();
|
||||||
@ -151,13 +175,7 @@ mod tests {
|
|||||||
tm_handler,
|
tm_handler,
|
||||||
};
|
};
|
||||||
udp_dyn_server.periodic_operation();
|
udp_dyn_server.periodic_operation();
|
||||||
let queue = udp_dyn_server
|
let queue = udp_dyn_server.udp_tc_server.tc_sender.tc_vec.borrow();
|
||||||
.udp_tc_server
|
|
||||||
.tc_sender
|
|
||||||
.get_mock_sender()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.borrow();
|
|
||||||
assert!(queue.is_empty());
|
assert!(queue.is_empty());
|
||||||
assert!(tm_handler_calls.lock().unwrap().is_empty());
|
assert!(tm_handler_calls.lock().unwrap().is_empty());
|
||||||
}
|
}
|
||||||
@ -165,7 +183,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_transactions() {
|
fn test_transactions() {
|
||||||
let sock_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0);
|
let sock_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0);
|
||||||
let test_receiver = TmTcSender::Mock(MockSender::default());
|
let test_receiver = TestSender::default();
|
||||||
|
// let tc_queue = test_receiver.tc_vec.clone();
|
||||||
let udp_tc_server =
|
let udp_tc_server =
|
||||||
UdpTcServer::new(UDP_SERVER_ID, sock_addr, 2048, test_receiver).unwrap();
|
UdpTcServer::new(UDP_SERVER_ID, sock_addr, 2048, test_receiver).unwrap();
|
||||||
let server_addr = udp_tc_server.socket.local_addr().unwrap();
|
let server_addr = udp_tc_server.socket.local_addr().unwrap();
|
||||||
@ -185,13 +204,7 @@ mod tests {
|
|||||||
client.send_to(&ping_tc, server_addr).unwrap();
|
client.send_to(&ping_tc, server_addr).unwrap();
|
||||||
udp_dyn_server.periodic_operation();
|
udp_dyn_server.periodic_operation();
|
||||||
{
|
{
|
||||||
let mut queue = udp_dyn_server
|
let mut queue = udp_dyn_server.udp_tc_server.tc_sender.tc_vec.borrow_mut();
|
||||||
.udp_tc_server
|
|
||||||
.tc_sender
|
|
||||||
.get_mock_sender()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.borrow_mut();
|
|
||||||
assert!(!queue.is_empty());
|
assert!(!queue.is_empty());
|
||||||
let packet_with_sender = queue.pop_front().unwrap();
|
let packet_with_sender = queue.pop_front().unwrap();
|
||||||
assert_eq!(packet_with_sender.packet, ping_tc);
|
assert_eq!(packet_with_sender.packet, ping_tc);
|
||||||
@ -206,13 +219,7 @@ mod tests {
|
|||||||
assert_eq!(received_addr, client_addr);
|
assert_eq!(received_addr, client_addr);
|
||||||
}
|
}
|
||||||
udp_dyn_server.periodic_operation();
|
udp_dyn_server.periodic_operation();
|
||||||
let queue = udp_dyn_server
|
let queue = udp_dyn_server.udp_tc_server.tc_sender.tc_vec.borrow();
|
||||||
.udp_tc_server
|
|
||||||
.tc_sender
|
|
||||||
.get_mock_sender()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.borrow();
|
|
||||||
assert!(queue.is_empty());
|
assert!(queue.is_empty());
|
||||||
drop(queue);
|
drop(queue);
|
||||||
// Still tries to send to the same client.
|
// Still tries to send to the same client.
|
||||||
|
@ -1,73 +1,3 @@
|
|||||||
use std::{
|
|
||||||
net::{IpAddr, SocketAddr},
|
|
||||||
sync::{mpsc, Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use acs::mgm::{MgmHandlerLis3Mdl, SpiDummyInterface, SpiSimInterface, SpiSimInterfaceWrapper};
|
|
||||||
use eps::{
|
|
||||||
pcdu::{PcduHandler, SerialInterfaceDummy, SerialInterfaceToSim, SerialSimInterfaceWrapper},
|
|
||||||
PowerSwitchHelper,
|
|
||||||
};
|
|
||||||
use events::EventHandler;
|
|
||||||
use interface::{
|
|
||||||
sim_client_udp::create_sim_client,
|
|
||||||
tcp::{SyncTcpTmSource, TcpTask},
|
|
||||||
udp::UdpTmtcServer,
|
|
||||||
};
|
|
||||||
use log::info;
|
|
||||||
use logger::setup_logger;
|
|
||||||
use pus::{
|
|
||||||
action::create_action_service,
|
|
||||||
event::create_event_service,
|
|
||||||
hk::create_hk_service,
|
|
||||||
mode::create_mode_service,
|
|
||||||
scheduler::{create_scheduler_service, TcReleaser},
|
|
||||||
stack::PusStack,
|
|
||||||
test::create_test_service,
|
|
||||||
PusTcDistributor, PusTcMpscRouter,
|
|
||||||
};
|
|
||||||
use requests::GenericRequestRouter;
|
|
||||||
use satrs::{
|
|
||||||
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
|
|
||||||
mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestHandlerMpscBounded},
|
|
||||||
mode_tree::connect_mode_nodes,
|
|
||||||
pus::{event_man::EventRequestWithToken, EcssTcInMemConverter, HandlingStatus},
|
|
||||||
request::{GenericMessage, MessageMetadata},
|
|
||||||
spacepackets::time::{cds::CdsTime, TimeWriter},
|
|
||||||
};
|
|
||||||
use satrs_example::{
|
|
||||||
config::{
|
|
||||||
acs::{MGM_HANDLER_0, MGM_HANDLER_1},
|
|
||||||
components::{NO_SENDER, PCDU_HANDLER, TCP_SERVER, UDP_SERVER},
|
|
||||||
pool::create_sched_tc_pool,
|
|
||||||
tasks::{FREQ_MS_AOCS, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS},
|
|
||||||
OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
|
|
||||||
},
|
|
||||||
DeviceMode,
|
|
||||||
};
|
|
||||||
use tmtc::sender::TmTcSender;
|
|
||||||
use tmtc::{tc_source::TcSourceTask, tm_sink::TmSink};
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(feature = "heap_tmtc")] {
|
|
||||||
use interface::udp::DynamicUdpTmHandler;
|
|
||||||
use satrs::pus::EcssTcInVecConverter;
|
|
||||||
use tmtc::{tc_source::TcSourceTaskDynamic, tm_sink::TmSinkDynamic};
|
|
||||||
} else {
|
|
||||||
use std::sync::RwLock;
|
|
||||||
use interface::udp::StaticUdpTmHandler;
|
|
||||||
use satrs::pus::EcssTcInSharedPoolConverter;
|
|
||||||
use satrs::tmtc::{PacketSenderWithSharedPool, SharedPacketPool};
|
|
||||||
use satrs_example::config::pool::create_static_pools;
|
|
||||||
use tmtc::{
|
|
||||||
tc_source::TcSourceTaskStatic,
|
|
||||||
tm_sink::TmSinkStatic,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod acs;
|
mod acs;
|
||||||
mod eps;
|
mod eps;
|
||||||
mod events;
|
mod events;
|
||||||
@ -76,74 +6,106 @@ mod interface;
|
|||||||
mod logger;
|
mod logger;
|
||||||
mod pus;
|
mod pus;
|
||||||
mod requests;
|
mod requests;
|
||||||
mod spi;
|
|
||||||
mod tmtc;
|
mod tmtc;
|
||||||
|
|
||||||
fn main() {
|
use crate::eps::pcdu::{
|
||||||
setup_logger().expect("setting up logging with fern failed");
|
PcduHandler, SerialInterfaceDummy, SerialInterfaceToSim, SerialSimInterfaceWrapper,
|
||||||
println!("Running OBSW example");
|
};
|
||||||
|
use crate::eps::PowerSwitchHelper;
|
||||||
|
use crate::events::EventHandler;
|
||||||
|
use crate::interface::udp::DynamicUdpTmHandler;
|
||||||
|
use crate::pus::stack::PusStack;
|
||||||
|
use crate::tmtc::tc_source::{TcSourceTaskDynamic, TcSourceTaskStatic};
|
||||||
|
use crate::tmtc::tm_sink::{TmSinkDynamic, TmSinkStatic};
|
||||||
|
use log::info;
|
||||||
|
use pus::test::create_test_service_dynamic;
|
||||||
|
use satrs::hal::std::tcp_server::ServerConfig;
|
||||||
|
use satrs::hal::std::udp_server::UdpTcServer;
|
||||||
|
use satrs::pus::HandlingStatus;
|
||||||
|
use satrs::request::{GenericMessage, MessageMetadata};
|
||||||
|
use satrs::tmtc::{PacketSenderWithSharedPool, SharedPacketPool};
|
||||||
|
use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools};
|
||||||
|
use satrs_example::config::tasks::{
|
||||||
|
FREQ_MS_AOCS, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS,
|
||||||
|
};
|
||||||
|
use satrs_example::config::{OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT};
|
||||||
|
use satrs_example::DeviceMode;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
use crate::acs::mgm::{
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
MgmHandlerLis3Mdl, MpscModeLeafInterface, SpiDummyInterface, SpiSimInterface,
|
||||||
let (tm_pool, tc_pool) = create_static_pools();
|
SpiSimInterfaceWrapper,
|
||||||
let shared_tm_pool = Arc::new(RwLock::new(tm_pool));
|
};
|
||||||
let shared_tc_pool = Arc::new(RwLock::new(tc_pool));
|
use crate::interface::sim_client_udp::create_sim_client;
|
||||||
let shared_tm_pool_wrapper = SharedPacketPool::new(&shared_tm_pool);
|
use crate::interface::tcp::{SyncTcpTmSource, TcpTask};
|
||||||
let shared_tc_pool_wrapper = SharedPacketPool::new(&shared_tc_pool);
|
use crate::interface::udp::{StaticUdpTmHandler, UdpTmtcServer};
|
||||||
}
|
use crate::logger::setup_logger;
|
||||||
}
|
use crate::pus::action::{create_action_service_dynamic, create_action_service_static};
|
||||||
|
use crate::pus::event::{create_event_service_dynamic, create_event_service_static};
|
||||||
|
use crate::pus::hk::{create_hk_service_dynamic, create_hk_service_static};
|
||||||
|
use crate::pus::mode::{create_mode_service_dynamic, create_mode_service_static};
|
||||||
|
use crate::pus::scheduler::{create_scheduler_service_dynamic, create_scheduler_service_static};
|
||||||
|
use crate::pus::test::create_test_service_static;
|
||||||
|
use crate::pus::{PusTcDistributor, PusTcMpscRouter};
|
||||||
|
use crate::requests::{CompositeRequest, GenericRequestRouter};
|
||||||
|
use satrs::mode::{Mode, ModeAndSubmode, ModeRequest};
|
||||||
|
use satrs::pus::event_man::EventRequestWithToken;
|
||||||
|
use satrs::spacepackets::{time::cds::CdsTime, time::TimeWriter};
|
||||||
|
use satrs_example::config::components::{
|
||||||
|
MGM_HANDLER_0, NO_SENDER, PCDU_HANDLER, TCP_SERVER, UDP_SERVER,
|
||||||
|
};
|
||||||
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
use std::sync::{mpsc, Mutex};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn static_tmtc_pool_main() {
|
||||||
|
let (tm_pool, tc_pool) = create_static_pools();
|
||||||
|
let shared_tm_pool = Arc::new(RwLock::new(tm_pool));
|
||||||
|
let shared_tc_pool = Arc::new(RwLock::new(tc_pool));
|
||||||
|
let shared_tm_pool_wrapper = SharedPacketPool::new(&shared_tm_pool);
|
||||||
|
let shared_tc_pool_wrapper = SharedPacketPool::new(&shared_tc_pool);
|
||||||
let (tc_source_tx, tc_source_rx) = mpsc::sync_channel(50);
|
let (tc_source_tx, tc_source_rx) = mpsc::sync_channel(50);
|
||||||
let (tm_sink_tx, tm_sink_rx) = mpsc::sync_channel(50);
|
let (tm_sink_tx, tm_sink_rx) = mpsc::sync_channel(50);
|
||||||
let (tm_server_tx, tm_server_rx) = mpsc::sync_channel(50);
|
let (tm_server_tx, tm_server_rx) = mpsc::sync_channel(50);
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
let tm_sink_tx_sender =
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
PacketSenderWithSharedPool::new(tm_sink_tx.clone(), shared_tm_pool_wrapper.clone());
|
||||||
let tm_sender = TmTcSender::Static(
|
|
||||||
PacketSenderWithSharedPool::new(tm_sink_tx.clone(), shared_tm_pool_wrapper.clone())
|
|
||||||
);
|
|
||||||
} else if #[cfg(feature = "heap_tmtc")] {
|
|
||||||
let tm_sender = TmTcSender::Heap(tm_sink_tx.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let (sim_request_tx, sim_request_rx) = mpsc::channel();
|
let (sim_request_tx, sim_request_rx) = mpsc::channel();
|
||||||
let (mgm_0_sim_reply_tx, mgm_0_sim_reply_rx) = mpsc::channel();
|
let (mgm_sim_reply_tx, mgm_sim_reply_rx) = mpsc::channel();
|
||||||
let (mgm_1_sim_reply_tx, mgm_1_sim_reply_rx) = mpsc::channel();
|
|
||||||
let (pcdu_sim_reply_tx, pcdu_sim_reply_rx) = mpsc::channel();
|
let (pcdu_sim_reply_tx, pcdu_sim_reply_rx) = mpsc::channel();
|
||||||
let mut opt_sim_client = create_sim_client(sim_request_rx);
|
let mut opt_sim_client = create_sim_client(sim_request_rx);
|
||||||
|
|
||||||
let (mgm_0_handler_composite_tx, mgm_0_handler_composite_rx) = mpsc::sync_channel(10);
|
let (mgm_handler_composite_tx, mgm_handler_composite_rx) =
|
||||||
let (mgm_1_handler_composite_tx, mgm_1_handler_composite_rx) = mpsc::sync_channel(10);
|
mpsc::sync_channel::<GenericMessage<CompositeRequest>>(10);
|
||||||
let (pcdu_handler_composite_tx, pcdu_handler_composite_rx) = mpsc::sync_channel(30);
|
let (pcdu_handler_composite_tx, pcdu_handler_composite_rx) =
|
||||||
let (mgm_0_handler_mode_tx, mgm_0_handler_mode_rx) = mpsc::sync_channel(5);
|
mpsc::sync_channel::<GenericMessage<CompositeRequest>>(30);
|
||||||
let (mgm_1_handler_mode_tx, mgm_1_handler_mode_rx) = mpsc::sync_channel(5);
|
|
||||||
let (pcdu_handler_mode_tx, pcdu_handler_mode_rx) = mpsc::sync_channel(5);
|
let (mgm_handler_mode_tx, mgm_handler_mode_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<ModeRequest>>(5);
|
||||||
|
let (pcdu_handler_mode_tx, pcdu_handler_mode_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<ModeRequest>>(5);
|
||||||
|
|
||||||
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
let mut request_map = GenericRequestRouter::default();
|
let mut request_map = GenericRequestRouter::default();
|
||||||
request_map
|
request_map
|
||||||
.composite_router_map
|
.composite_router_map
|
||||||
.insert(MGM_HANDLER_0.id(), mgm_0_handler_composite_tx);
|
.insert(MGM_HANDLER_0.id(), mgm_handler_composite_tx);
|
||||||
request_map
|
request_map
|
||||||
.composite_router_map
|
.mode_router_map
|
||||||
.insert(MGM_HANDLER_0.id(), mgm_1_handler_composite_tx);
|
.insert(MGM_HANDLER_0.id(), mgm_handler_mode_tx);
|
||||||
request_map
|
request_map
|
||||||
.composite_router_map
|
.composite_router_map
|
||||||
.insert(PCDU_HANDLER.id(), pcdu_handler_composite_tx);
|
.insert(PCDU_HANDLER.id(), pcdu_handler_composite_tx);
|
||||||
|
request_map
|
||||||
|
.mode_router_map
|
||||||
|
.insert(PCDU_HANDLER.id(), pcdu_handler_mode_tx.clone());
|
||||||
|
|
||||||
// This helper structure is used by all telecommand providers which need to send telecommands
|
// This helper structure is used by all telecommand providers which need to send telecommands
|
||||||
// to the TC source.
|
// to the TC source.
|
||||||
cfg_if::cfg_if! {
|
let tc_source = PacketSenderWithSharedPool::new(tc_source_tx, shared_tc_pool_wrapper.clone());
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
|
||||||
let tc_sender_with_shared_pool =
|
|
||||||
PacketSenderWithSharedPool::new(tc_source_tx, shared_tc_pool_wrapper.clone());
|
|
||||||
let tc_in_mem_converter =
|
|
||||||
EcssTcInMemConverter::Static(EcssTcInSharedPoolConverter::new(shared_tc_pool, 4096));
|
|
||||||
} else if #[cfg(feature = "heap_tmtc")] {
|
|
||||||
let tc_in_mem_converter = EcssTcInMemConverter::Heap(EcssTcInVecConverter::default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create event handling components
|
// Create event handling components
|
||||||
// These sender handles are used to send event requests, for example to enable or disable
|
// These sender handles are used to send event requests, for example to enable or disable
|
||||||
@ -155,24 +117,17 @@ fn main() {
|
|||||||
// in the sat-rs documentation.
|
// in the sat-rs documentation.
|
||||||
let mut event_handler = EventHandler::new(tm_sink_tx.clone(), event_rx, event_request_rx);
|
let mut event_handler = EventHandler::new(tm_sink_tx.clone(), event_rx, event_request_rx);
|
||||||
|
|
||||||
let (pus_test_tx, pus_test_rx) = mpsc::sync_channel(20);
|
let (pus_test_tx, pus_test_rx) = mpsc::channel();
|
||||||
let (pus_event_tx, pus_event_rx) = mpsc::sync_channel(10);
|
let (pus_event_tx, pus_event_rx) = mpsc::channel();
|
||||||
let (pus_sched_tx, pus_sched_rx) = mpsc::sync_channel(50);
|
let (pus_sched_tx, pus_sched_rx) = mpsc::channel();
|
||||||
let (pus_hk_tx, pus_hk_rx) = mpsc::sync_channel(50);
|
let (pus_hk_tx, pus_hk_rx) = mpsc::channel();
|
||||||
let (pus_action_tx, pus_action_rx) = mpsc::sync_channel(50);
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
let (pus_mode_tx, pus_mode_rx) = mpsc::sync_channel(50);
|
let (pus_mode_tx, pus_mode_rx) = mpsc::channel();
|
||||||
|
|
||||||
let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel();
|
let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel();
|
||||||
let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::sync_channel(50);
|
let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel();
|
||||||
let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::sync_channel(30);
|
let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel();
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
|
||||||
let tc_releaser = TcReleaser::Static(tc_sender_with_shared_pool.clone());
|
|
||||||
} else if #[cfg(feature = "heap_tmtc")] {
|
|
||||||
let tc_releaser = TcReleaser::Heap(tc_source_tx.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let pus_router = PusTcMpscRouter {
|
let pus_router = PusTcMpscRouter {
|
||||||
test_tc_sender: pus_test_tx,
|
test_tc_sender: pus_test_tx,
|
||||||
event_tc_sender: pus_event_tx,
|
event_tc_sender: pus_event_tx,
|
||||||
@ -181,42 +136,41 @@ fn main() {
|
|||||||
action_tc_sender: pus_action_tx,
|
action_tc_sender: pus_action_tx,
|
||||||
mode_tc_sender: pus_mode_tx,
|
mode_tc_sender: pus_mode_tx,
|
||||||
};
|
};
|
||||||
let pus_test_service = create_test_service(
|
let pus_test_service = create_test_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
shared_tc_pool.clone(),
|
||||||
event_tx.clone(),
|
event_tx.clone(),
|
||||||
pus_test_rx,
|
pus_test_rx,
|
||||||
);
|
);
|
||||||
let pus_scheduler_service = create_scheduler_service(
|
let pus_scheduler_service = create_scheduler_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
tc_source.clone(),
|
||||||
tc_releaser,
|
|
||||||
pus_sched_rx,
|
pus_sched_rx,
|
||||||
create_sched_tc_pool(),
|
create_sched_tc_pool(),
|
||||||
);
|
);
|
||||||
let pus_event_service = create_event_service(
|
let pus_event_service = create_event_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
shared_tc_pool.clone(),
|
||||||
pus_event_rx,
|
pus_event_rx,
|
||||||
event_request_tx,
|
event_request_tx,
|
||||||
);
|
);
|
||||||
let pus_action_service = create_action_service(
|
let pus_action_service = create_action_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
shared_tc_pool.clone(),
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
request_map.clone(),
|
request_map.clone(),
|
||||||
pus_action_reply_rx,
|
pus_action_reply_rx,
|
||||||
);
|
);
|
||||||
let pus_hk_service = create_hk_service(
|
let pus_hk_service = create_hk_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
shared_tc_pool.clone(),
|
||||||
pus_hk_rx,
|
pus_hk_rx,
|
||||||
request_map.clone(),
|
request_map.clone(),
|
||||||
pus_hk_reply_rx,
|
pus_hk_reply_rx,
|
||||||
);
|
);
|
||||||
let pus_mode_service = create_mode_service(
|
let pus_mode_service = create_mode_service_static(
|
||||||
tm_sender.clone(),
|
tm_sink_tx_sender.clone(),
|
||||||
tc_in_mem_converter.clone(),
|
shared_tc_pool.clone(),
|
||||||
pus_mode_rx,
|
pus_mode_rx,
|
||||||
request_map,
|
request_map,
|
||||||
pus_mode_reply_rx,
|
pus_mode_reply_rx,
|
||||||
@ -230,36 +184,21 @@ fn main() {
|
|||||||
pus_mode_service,
|
pus_mode_service,
|
||||||
);
|
);
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
let mut tmtc_task = TcSourceTaskStatic::new(
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
shared_tc_pool_wrapper.clone(),
|
||||||
let mut tmtc_task = TcSourceTask::Static(TcSourceTaskStatic::new(
|
tc_source_rx,
|
||||||
shared_tc_pool_wrapper.clone(),
|
PusTcDistributor::new(tm_sink_tx_sender, pus_router),
|
||||||
tc_source_rx,
|
);
|
||||||
PusTcDistributor::new(tm_sender.clone(), pus_router),
|
|
||||||
));
|
|
||||||
let tc_sender = TmTcSender::Static(tc_sender_with_shared_pool);
|
|
||||||
let udp_tm_handler = StaticUdpTmHandler {
|
|
||||||
tm_rx: tm_server_rx,
|
|
||||||
tm_store: shared_tm_pool.clone(),
|
|
||||||
};
|
|
||||||
} else if #[cfg(feature = "heap_tmtc")] {
|
|
||||||
let mut tmtc_task = TcSourceTask::Heap(TcSourceTaskDynamic::new(
|
|
||||||
tc_source_rx,
|
|
||||||
PusTcDistributor::new(tm_sender.clone(), pus_router),
|
|
||||||
));
|
|
||||||
let tc_sender = TmTcSender::Heap(tc_source_tx.clone());
|
|
||||||
let udp_tm_handler = DynamicUdpTmHandler {
|
|
||||||
tm_rx: tm_server_rx,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
let udp_tc_server = UdpTcServer::new(UDP_SERVER.id(), sock_addr, 2048, tc_sender.clone())
|
let udp_tc_server = UdpTcServer::new(UDP_SERVER.id(), sock_addr, 2048, tc_source.clone())
|
||||||
.expect("creating UDP TMTC server failed");
|
.expect("creating UDP TMTC server failed");
|
||||||
let mut udp_tmtc_server = UdpTmtcServer {
|
let mut udp_tmtc_server = UdpTmtcServer {
|
||||||
udp_tc_server,
|
udp_tc_server,
|
||||||
tm_handler: udp_tm_handler,
|
tm_handler: StaticUdpTmHandler {
|
||||||
|
tm_rx: tm_server_rx,
|
||||||
|
tm_store: shared_tm_pool.clone(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let tcp_server_cfg = ServerConfig::new(
|
let tcp_server_cfg = ServerConfig::new(
|
||||||
@ -273,96 +212,60 @@ fn main() {
|
|||||||
let mut tcp_server = TcpTask::new(
|
let mut tcp_server = TcpTask::new(
|
||||||
tcp_server_cfg,
|
tcp_server_cfg,
|
||||||
sync_tm_tcp_source.clone(),
|
sync_tm_tcp_source.clone(),
|
||||||
tc_sender,
|
tc_source.clone(),
|
||||||
PACKET_ID_VALIDATOR.clone(),
|
PACKET_ID_VALIDATOR.clone(),
|
||||||
)
|
)
|
||||||
.expect("tcp server creation failed");
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
let mut tm_sink = TmSinkStatic::new(
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
shared_tm_pool_wrapper,
|
||||||
let mut tm_sink = TmSink::Static(TmSinkStatic::new(
|
sync_tm_tcp_source,
|
||||||
shared_tm_pool_wrapper,
|
tm_sink_rx,
|
||||||
sync_tm_tcp_source,
|
tm_server_tx,
|
||||||
tm_sink_rx,
|
);
|
||||||
tm_server_tx,
|
|
||||||
));
|
let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) =
|
||||||
} else if #[cfg(feature = "heap_tmtc")] {
|
mpsc::sync_channel(5);
|
||||||
let mut tm_sink = TmSink::Heap(TmSinkDynamic::new(
|
|
||||||
sync_tm_tcp_source,
|
|
||||||
tm_sink_rx,
|
|
||||||
tm_server_tx,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let shared_switch_set = Arc::new(Mutex::default());
|
let shared_switch_set = Arc::new(Mutex::default());
|
||||||
let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20);
|
let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20);
|
||||||
let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone());
|
let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone());
|
||||||
|
|
||||||
let shared_mgm_0_set = Arc::default();
|
let shared_mgm_set = Arc::default();
|
||||||
let shared_mgm_1_set = Arc::default();
|
let mgm_mode_leaf_interface = MpscModeLeafInterface {
|
||||||
let mgm_0_mode_node =
|
request_rx: mgm_handler_mode_rx,
|
||||||
ModeRequestHandlerMpscBounded::new(MGM_HANDLER_0.into(), mgm_0_handler_mode_rx);
|
reply_to_pus_tx: pus_mode_reply_tx.clone(),
|
||||||
let mgm_1_mode_node =
|
reply_to_parent_tx: mgm_handler_mode_reply_to_parent_tx,
|
||||||
ModeRequestHandlerMpscBounded::new(MGM_HANDLER_1.into(), mgm_1_handler_mode_rx);
|
};
|
||||||
let (mgm_0_spi_interface, mgm_1_spi_interface) =
|
|
||||||
if let Some(sim_client) = opt_sim_client.as_mut() {
|
let mgm_spi_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
||||||
sim_client
|
sim_client.add_reply_recipient(satrs_minisim::SimComponent::MgmLis3Mdl, mgm_sim_reply_tx);
|
||||||
.add_reply_recipient(satrs_minisim::SimComponent::Mgm0Lis3Mdl, mgm_0_sim_reply_tx);
|
SpiSimInterfaceWrapper::Sim(SpiSimInterface {
|
||||||
sim_client
|
sim_request_tx: sim_request_tx.clone(),
|
||||||
.add_reply_recipient(satrs_minisim::SimComponent::Mgm1Lis3Mdl, mgm_1_sim_reply_tx);
|
sim_reply_rx: mgm_sim_reply_rx,
|
||||||
(
|
})
|
||||||
SpiSimInterfaceWrapper::Sim(SpiSimInterface {
|
} else {
|
||||||
sim_request_tx: sim_request_tx.clone(),
|
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default())
|
||||||
sim_reply_rx: mgm_0_sim_reply_rx,
|
};
|
||||||
}),
|
let mut mgm_handler = MgmHandlerLis3Mdl::new(
|
||||||
SpiSimInterfaceWrapper::Sim(SpiSimInterface {
|
|
||||||
sim_request_tx: sim_request_tx.clone(),
|
|
||||||
sim_reply_rx: mgm_1_sim_reply_rx,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default()),
|
|
||||||
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default()),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let mut mgm_0_handler = MgmHandlerLis3Mdl::new(
|
|
||||||
MGM_HANDLER_0,
|
MGM_HANDLER_0,
|
||||||
"MGM_0",
|
"MGM_0",
|
||||||
mgm_0_mode_node,
|
mgm_mode_leaf_interface,
|
||||||
mgm_0_handler_composite_rx,
|
mgm_handler_composite_rx,
|
||||||
pus_hk_reply_tx.clone(),
|
pus_hk_reply_tx.clone(),
|
||||||
switch_helper.clone(),
|
switch_helper.clone(),
|
||||||
tm_sender.clone(),
|
tm_sink_tx.clone(),
|
||||||
mgm_0_spi_interface,
|
mgm_spi_interface,
|
||||||
shared_mgm_0_set,
|
shared_mgm_set,
|
||||||
);
|
|
||||||
let mut mgm_1_handler = MgmHandlerLis3Mdl::new(
|
|
||||||
MGM_HANDLER_1,
|
|
||||||
"MGM_1",
|
|
||||||
mgm_1_mode_node,
|
|
||||||
mgm_1_handler_composite_rx,
|
|
||||||
pus_hk_reply_tx.clone(),
|
|
||||||
switch_helper.clone(),
|
|
||||||
tm_sender.clone(),
|
|
||||||
mgm_1_spi_interface,
|
|
||||||
shared_mgm_1_set,
|
|
||||||
);
|
|
||||||
// Connect PUS service to device handlers.
|
|
||||||
connect_mode_nodes(
|
|
||||||
&mut pus_stack.mode_srv,
|
|
||||||
mgm_0_handler_mode_tx,
|
|
||||||
&mut mgm_0_handler,
|
|
||||||
pus_mode_reply_tx.clone(),
|
|
||||||
);
|
|
||||||
connect_mode_nodes(
|
|
||||||
&mut pus_stack.mode_srv,
|
|
||||||
mgm_1_handler_mode_tx,
|
|
||||||
&mut mgm_1_handler,
|
|
||||||
pus_mode_reply_tx.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let (pcdu_handler_mode_reply_to_parent_tx, _pcdu_handler_mode_reply_to_parent_rx) =
|
||||||
|
mpsc::sync_channel(10);
|
||||||
|
let pcdu_mode_leaf_interface = MpscModeLeafInterface {
|
||||||
|
request_rx: pcdu_handler_mode_rx,
|
||||||
|
reply_to_pus_tx: pus_mode_reply_tx,
|
||||||
|
reply_to_parent_tx: pcdu_handler_mode_reply_to_parent_tx,
|
||||||
|
};
|
||||||
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
||||||
sim_client.add_reply_recipient(satrs_minisim::SimComponent::Pcdu, pcdu_sim_reply_tx);
|
sim_client.add_reply_recipient(satrs_minisim::SimComponent::Pcdu, pcdu_sim_reply_tx);
|
||||||
SerialSimInterfaceWrapper::Sim(SerialInterfaceToSim::new(
|
SerialSimInterfaceWrapper::Sim(SerialInterfaceToSim::new(
|
||||||
@ -372,34 +275,23 @@ fn main() {
|
|||||||
} else {
|
} else {
|
||||||
SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default())
|
SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default())
|
||||||
};
|
};
|
||||||
let pcdu_mode_node =
|
|
||||||
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), pcdu_handler_mode_rx);
|
|
||||||
let mut pcdu_handler = PcduHandler::new(
|
let mut pcdu_handler = PcduHandler::new(
|
||||||
PCDU_HANDLER,
|
PCDU_HANDLER,
|
||||||
"PCDU",
|
"PCDU",
|
||||||
pcdu_mode_node,
|
pcdu_mode_leaf_interface,
|
||||||
pcdu_handler_composite_rx,
|
pcdu_handler_composite_rx,
|
||||||
pus_hk_reply_tx,
|
pus_hk_reply_tx,
|
||||||
switch_request_rx,
|
switch_request_rx,
|
||||||
tm_sender.clone(),
|
tm_sink_tx,
|
||||||
pcdu_serial_interface,
|
pcdu_serial_interface,
|
||||||
shared_switch_set,
|
shared_switch_set,
|
||||||
);
|
);
|
||||||
connect_mode_nodes(
|
|
||||||
&mut pus_stack.mode_srv,
|
|
||||||
pcdu_handler_mode_tx.clone(),
|
|
||||||
&mut pcdu_handler,
|
|
||||||
pus_mode_reply_tx,
|
|
||||||
);
|
|
||||||
|
|
||||||
// The PCDU is a critical component which should be in normal mode immediately.
|
// The PCDU is a critical component which should be in normal mode immediately.
|
||||||
pcdu_handler_mode_tx
|
pcdu_handler_mode_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
MessageMetadata::new(0, NO_SENDER),
|
MessageMetadata::new(0, NO_SENDER),
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as Mode, 0)),
|
||||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as Mode, 0),
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.expect("sending initial mode request failed");
|
.expect("sending initial mode request failed");
|
||||||
|
|
||||||
@ -454,8 +346,7 @@ fn main() {
|
|||||||
let jh_aocs = thread::Builder::new()
|
let jh_aocs = thread::Builder::new()
|
||||||
.name("sat-rs aocs".to_string())
|
.name("sat-rs aocs".to_string())
|
||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
mgm_0_handler.periodic_operation();
|
mgm_handler.periodic_operation();
|
||||||
mgm_1_handler.periodic_operation();
|
|
||||||
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -466,13 +357,11 @@ fn main() {
|
|||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
// TODO: We should introduce something like a fixed timeslot helper to allow a more
|
// TODO: We should introduce something like a fixed timeslot helper to allow a more
|
||||||
// declarative API. It would also be very useful for the AOCS task.
|
// declarative API. It would also be very useful for the AOCS task.
|
||||||
//
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::RegularOp);
|
||||||
// TODO: The fixed timeslot handler exists.. use it.
|
|
||||||
pcdu_handler.periodic_operation(crate::eps::pcdu::OpCode::RegularOp);
|
|
||||||
thread::sleep(Duration::from_millis(50));
|
thread::sleep(Duration::from_millis(50));
|
||||||
pcdu_handler.periodic_operation(crate::eps::pcdu::OpCode::PollAndRecvReplies);
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::PollAndRecvReplies);
|
||||||
thread::sleep(Duration::from_millis(50));
|
thread::sleep(Duration::from_millis(50));
|
||||||
pcdu_handler.periodic_operation(crate::eps::pcdu::OpCode::PollAndRecvReplies);
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::PollAndRecvReplies);
|
||||||
thread::sleep(Duration::from_millis(300));
|
thread::sleep(Duration::from_millis(300));
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -508,6 +397,322 @@ fn main() {
|
|||||||
.expect("Joining PUS handler thread failed");
|
.expect("Joining PUS handler thread failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn dyn_tmtc_pool_main() {
|
||||||
|
let (tc_source_tx, tc_source_rx) = mpsc::channel();
|
||||||
|
let (tm_sink_tx, tm_sink_rx) = mpsc::channel();
|
||||||
|
let (tm_server_tx, tm_server_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let (sim_request_tx, sim_request_rx) = mpsc::channel();
|
||||||
|
let (mgm_sim_reply_tx, mgm_sim_reply_rx) = mpsc::channel();
|
||||||
|
let (pcdu_sim_reply_tx, pcdu_sim_reply_rx) = mpsc::channel();
|
||||||
|
let mut opt_sim_client = create_sim_client(sim_request_rx);
|
||||||
|
|
||||||
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
|
let (mgm_handler_composite_tx, mgm_handler_composite_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<CompositeRequest>>(5);
|
||||||
|
let (pcdu_handler_composite_tx, pcdu_handler_composite_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<CompositeRequest>>(10);
|
||||||
|
let (mgm_handler_mode_tx, mgm_handler_mode_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<ModeRequest>>(5);
|
||||||
|
let (pcdu_handler_mode_tx, pcdu_handler_mode_rx) =
|
||||||
|
mpsc::sync_channel::<GenericMessage<ModeRequest>>(10);
|
||||||
|
|
||||||
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
|
let mut request_map = GenericRequestRouter::default();
|
||||||
|
request_map
|
||||||
|
.composite_router_map
|
||||||
|
.insert(MGM_HANDLER_0.id(), mgm_handler_composite_tx);
|
||||||
|
request_map
|
||||||
|
.mode_router_map
|
||||||
|
.insert(MGM_HANDLER_0.id(), mgm_handler_mode_tx);
|
||||||
|
request_map
|
||||||
|
.composite_router_map
|
||||||
|
.insert(PCDU_HANDLER.id(), pcdu_handler_composite_tx);
|
||||||
|
request_map
|
||||||
|
.mode_router_map
|
||||||
|
.insert(PCDU_HANDLER.id(), pcdu_handler_mode_tx.clone());
|
||||||
|
|
||||||
|
// Create event handling components
|
||||||
|
// These sender handles are used to send event requests, for example to enable or disable
|
||||||
|
// certain events.
|
||||||
|
let (event_tx, event_rx) = mpsc::sync_channel(100);
|
||||||
|
let (event_request_tx, event_request_rx) = mpsc::channel::<EventRequestWithToken>();
|
||||||
|
// The event task is the core handler to perform the event routing and TM handling as specified
|
||||||
|
// in the sat-rs documentation.
|
||||||
|
let mut event_handler = EventHandler::new(tm_sink_tx.clone(), event_rx, event_request_rx);
|
||||||
|
|
||||||
|
let (pus_test_tx, pus_test_rx) = mpsc::channel();
|
||||||
|
let (pus_event_tx, pus_event_rx) = mpsc::channel();
|
||||||
|
let (pus_sched_tx, pus_sched_rx) = mpsc::channel();
|
||||||
|
let (pus_hk_tx, pus_hk_rx) = mpsc::channel();
|
||||||
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_tx, pus_mode_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel();
|
||||||
|
let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let pus_router = PusTcMpscRouter {
|
||||||
|
test_tc_sender: pus_test_tx,
|
||||||
|
event_tc_sender: pus_event_tx,
|
||||||
|
sched_tc_sender: pus_sched_tx,
|
||||||
|
hk_tc_sender: pus_hk_tx,
|
||||||
|
action_tc_sender: pus_action_tx,
|
||||||
|
mode_tc_sender: pus_mode_tx,
|
||||||
|
};
|
||||||
|
|
||||||
|
let pus_test_service =
|
||||||
|
create_test_service_dynamic(tm_sink_tx.clone(), event_tx.clone(), pus_test_rx);
|
||||||
|
let pus_scheduler_service = create_scheduler_service_dynamic(
|
||||||
|
tm_sink_tx.clone(),
|
||||||
|
tc_source_tx.clone(),
|
||||||
|
pus_sched_rx,
|
||||||
|
create_sched_tc_pool(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let pus_event_service =
|
||||||
|
create_event_service_dynamic(tm_sink_tx.clone(), pus_event_rx, event_request_tx);
|
||||||
|
let pus_action_service = create_action_service_dynamic(
|
||||||
|
tm_sink_tx.clone(),
|
||||||
|
pus_action_rx,
|
||||||
|
request_map.clone(),
|
||||||
|
pus_action_reply_rx,
|
||||||
|
);
|
||||||
|
let pus_hk_service = create_hk_service_dynamic(
|
||||||
|
tm_sink_tx.clone(),
|
||||||
|
pus_hk_rx,
|
||||||
|
request_map.clone(),
|
||||||
|
pus_hk_reply_rx,
|
||||||
|
);
|
||||||
|
let pus_mode_service = create_mode_service_dynamic(
|
||||||
|
tm_sink_tx.clone(),
|
||||||
|
pus_mode_rx,
|
||||||
|
request_map,
|
||||||
|
pus_mode_reply_rx,
|
||||||
|
);
|
||||||
|
let mut pus_stack = PusStack::new(
|
||||||
|
pus_test_service,
|
||||||
|
pus_hk_service,
|
||||||
|
pus_event_service,
|
||||||
|
pus_action_service,
|
||||||
|
pus_scheduler_service,
|
||||||
|
pus_mode_service,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut tmtc_task = TcSourceTaskDynamic::new(
|
||||||
|
tc_source_rx,
|
||||||
|
PusTcDistributor::new(tm_sink_tx.clone(), pus_router),
|
||||||
|
);
|
||||||
|
|
||||||
|
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
|
let udp_tc_server = UdpTcServer::new(UDP_SERVER.id(), sock_addr, 2048, tc_source_tx.clone())
|
||||||
|
.expect("creating UDP TMTC server failed");
|
||||||
|
let mut udp_tmtc_server = UdpTmtcServer {
|
||||||
|
udp_tc_server,
|
||||||
|
tm_handler: DynamicUdpTmHandler {
|
||||||
|
tm_rx: tm_server_rx,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let tcp_server_cfg = ServerConfig::new(
|
||||||
|
TCP_SERVER.id(),
|
||||||
|
sock_addr,
|
||||||
|
Duration::from_millis(400),
|
||||||
|
4096,
|
||||||
|
8192,
|
||||||
|
);
|
||||||
|
let sync_tm_tcp_source = SyncTcpTmSource::new(200);
|
||||||
|
let mut tcp_server = TcpTask::new(
|
||||||
|
tcp_server_cfg,
|
||||||
|
sync_tm_tcp_source.clone(),
|
||||||
|
tc_source_tx.clone(),
|
||||||
|
PACKET_ID_VALIDATOR.clone(),
|
||||||
|
)
|
||||||
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
|
let mut tm_funnel = TmSinkDynamic::new(sync_tm_tcp_source, tm_sink_rx, tm_server_tx);
|
||||||
|
|
||||||
|
let shared_switch_set = Arc::new(Mutex::default());
|
||||||
|
let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20);
|
||||||
|
let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone());
|
||||||
|
|
||||||
|
let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) =
|
||||||
|
mpsc::sync_channel(5);
|
||||||
|
let shared_mgm_set = Arc::default();
|
||||||
|
let mode_leaf_interface = MpscModeLeafInterface {
|
||||||
|
request_rx: mgm_handler_mode_rx,
|
||||||
|
reply_to_pus_tx: pus_mode_reply_tx.clone(),
|
||||||
|
reply_to_parent_tx: mgm_handler_mode_reply_to_parent_tx,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mgm_spi_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
||||||
|
sim_client.add_reply_recipient(satrs_minisim::SimComponent::MgmLis3Mdl, mgm_sim_reply_tx);
|
||||||
|
SpiSimInterfaceWrapper::Sim(SpiSimInterface {
|
||||||
|
sim_request_tx: sim_request_tx.clone(),
|
||||||
|
sim_reply_rx: mgm_sim_reply_rx,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default())
|
||||||
|
};
|
||||||
|
let mut mgm_handler = MgmHandlerLis3Mdl::new(
|
||||||
|
MGM_HANDLER_0,
|
||||||
|
"MGM_0",
|
||||||
|
mode_leaf_interface,
|
||||||
|
mgm_handler_composite_rx,
|
||||||
|
pus_hk_reply_tx.clone(),
|
||||||
|
switch_helper.clone(),
|
||||||
|
tm_sink_tx.clone(),
|
||||||
|
mgm_spi_interface,
|
||||||
|
shared_mgm_set,
|
||||||
|
);
|
||||||
|
|
||||||
|
let (pcdu_handler_mode_reply_to_parent_tx, _pcdu_handler_mode_reply_to_parent_rx) =
|
||||||
|
mpsc::sync_channel(10);
|
||||||
|
let pcdu_mode_leaf_interface = MpscModeLeafInterface {
|
||||||
|
request_rx: pcdu_handler_mode_rx,
|
||||||
|
reply_to_pus_tx: pus_mode_reply_tx,
|
||||||
|
reply_to_parent_tx: pcdu_handler_mode_reply_to_parent_tx,
|
||||||
|
};
|
||||||
|
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
||||||
|
sim_client.add_reply_recipient(satrs_minisim::SimComponent::Pcdu, pcdu_sim_reply_tx);
|
||||||
|
SerialSimInterfaceWrapper::Sim(SerialInterfaceToSim::new(
|
||||||
|
sim_request_tx.clone(),
|
||||||
|
pcdu_sim_reply_rx,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default())
|
||||||
|
};
|
||||||
|
let mut pcdu_handler = PcduHandler::new(
|
||||||
|
PCDU_HANDLER,
|
||||||
|
"PCDU",
|
||||||
|
pcdu_mode_leaf_interface,
|
||||||
|
pcdu_handler_composite_rx,
|
||||||
|
pus_hk_reply_tx,
|
||||||
|
switch_request_rx,
|
||||||
|
tm_sink_tx,
|
||||||
|
pcdu_serial_interface,
|
||||||
|
shared_switch_set,
|
||||||
|
);
|
||||||
|
// The PCDU is a critical component which should be in normal mode immediately.
|
||||||
|
pcdu_handler_mode_tx
|
||||||
|
.send(GenericMessage::new(
|
||||||
|
MessageMetadata::new(0, NO_SENDER),
|
||||||
|
ModeRequest::SetMode(ModeAndSubmode::new(DeviceMode::Normal as Mode, 0)),
|
||||||
|
))
|
||||||
|
.expect("sending initial mode request failed");
|
||||||
|
|
||||||
|
info!("Starting TMTC and UDP task");
|
||||||
|
let jh_udp_tmtc = thread::Builder::new()
|
||||||
|
.name("sat-rs tmtc-udp".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
info!("Running UDP server on port {SERVER_PORT}");
|
||||||
|
loop {
|
||||||
|
udp_tmtc_server.periodic_operation();
|
||||||
|
tmtc_task.periodic_operation();
|
||||||
|
thread::sleep(Duration::from_millis(FREQ_MS_UDP_TMTC));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
info!("Starting TCP task");
|
||||||
|
let jh_tcp = thread::Builder::new()
|
||||||
|
.name("sat-rs tcp".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
info!("Running TCP server on port {SERVER_PORT}");
|
||||||
|
loop {
|
||||||
|
tcp_server.periodic_operation();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
info!("Starting TM funnel task");
|
||||||
|
let jh_tm_funnel = thread::Builder::new()
|
||||||
|
.name("sat-rs tm-sink".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
tm_funnel.operation();
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut opt_jh_sim_client = None;
|
||||||
|
if let Some(mut sim_client) = opt_sim_client {
|
||||||
|
info!("Starting UDP sim client task");
|
||||||
|
opt_jh_sim_client = Some(
|
||||||
|
thread::Builder::new()
|
||||||
|
.name("sat-rs sim adapter".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
if sim_client.operation() == HandlingStatus::Empty {
|
||||||
|
std::thread::sleep(Duration::from_millis(SIM_CLIENT_IDLE_DELAY_MS));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Starting AOCS thread");
|
||||||
|
let jh_aocs = thread::Builder::new()
|
||||||
|
.name("sat-rs aocs".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
mgm_handler.periodic_operation();
|
||||||
|
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
info!("Starting EPS thread");
|
||||||
|
let jh_eps = thread::Builder::new()
|
||||||
|
.name("sat-rs eps".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
// TODO: We should introduce something like a fixed timeslot helper to allow a more
|
||||||
|
// declarative API. It would also be very useful for the AOCS task.
|
||||||
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::RegularOp);
|
||||||
|
thread::sleep(Duration::from_millis(50));
|
||||||
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::PollAndRecvReplies);
|
||||||
|
thread::sleep(Duration::from_millis(50));
|
||||||
|
pcdu_handler.periodic_operation(eps::pcdu::OpCode::PollAndRecvReplies);
|
||||||
|
thread::sleep(Duration::from_millis(300));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
info!("Starting PUS handler thread");
|
||||||
|
let jh_pus_handler = thread::Builder::new()
|
||||||
|
.name("sat-rs pus".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
pus_stack.periodic_operation();
|
||||||
|
event_handler.periodic_operation();
|
||||||
|
thread::sleep(Duration::from_millis(FREQ_MS_PUS_STACK));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
jh_udp_tmtc
|
||||||
|
.join()
|
||||||
|
.expect("Joining UDP TMTC server thread failed");
|
||||||
|
jh_tcp
|
||||||
|
.join()
|
||||||
|
.expect("Joining TCP TMTC server thread failed");
|
||||||
|
jh_tm_funnel
|
||||||
|
.join()
|
||||||
|
.expect("Joining TM Funnel thread failed");
|
||||||
|
if let Some(jh_sim_client) = opt_jh_sim_client {
|
||||||
|
jh_sim_client
|
||||||
|
.join()
|
||||||
|
.expect("Joining SIM client thread failed");
|
||||||
|
}
|
||||||
|
jh_aocs.join().expect("Joining AOCS thread failed");
|
||||||
|
jh_eps.join().expect("Joining EPS thread failed");
|
||||||
|
jh_pus_handler
|
||||||
|
.join()
|
||||||
|
.expect("Joining PUS handler thread failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
setup_logger().expect("setting up logging with fern failed");
|
||||||
|
println!("Running OBSW example");
|
||||||
|
#[cfg(not(feature = "dyn_tmtc"))]
|
||||||
|
static_tmtc_pool_main();
|
||||||
|
#[cfg(feature = "dyn_tmtc")]
|
||||||
|
dyn_tmtc_pool_main();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_time(time_provider: &mut CdsTime, timestamp: &mut [u8]) {
|
pub fn update_time(time_provider: &mut CdsTime, timestamp: &mut [u8]) {
|
||||||
time_provider
|
time_provider
|
||||||
.update_from_now()
|
.update_from_now()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
use satrs::action::{ActionRequest, ActionRequestVariant};
|
use satrs::action::{ActionRequest, ActionRequestVariant};
|
||||||
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::action::{
|
use satrs::pus::action::{
|
||||||
ActionReplyPus, ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap,
|
ActionReplyPus, ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap,
|
||||||
};
|
};
|
||||||
@ -9,20 +10,21 @@ use satrs::pus::verification::{
|
|||||||
VerificationReportingProvider, VerificationToken,
|
VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, EcssTmSender, EcssTmtcError,
|
ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
||||||
GenericConversionError, MpscTcReceiver, PusPacketHandlingError, PusReplyHandler,
|
EcssTcInVecConverter, EcssTmSender, EcssTmtcError, GenericConversionError, MpscTcReceiver,
|
||||||
PusServiceHelper, PusTcToRequestConverter,
|
MpscTmAsVecSender, PusPacketHandlingError, PusReplyHandler, PusServiceHelper,
|
||||||
|
PusTcToRequestConverter,
|
||||||
};
|
};
|
||||||
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket, PusServiceId};
|
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket, PusServiceId};
|
||||||
use satrs_example::config::pus::PUS_ACTION_SERVICE;
|
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||||
|
use satrs_example::config::components::PUS_ACTION_SERVICE;
|
||||||
use satrs_example::config::tmtc_err;
|
use satrs_example::config::tmtc_err;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
create_verification_reporter, generic_pus_request_timeout_handler, HandlingStatus,
|
create_verification_reporter, generic_pus_request_timeout_handler, HandlingStatus,
|
||||||
@ -205,20 +207,20 @@ impl PusTcToRequestConverter<ActivePusActionRequestStd, ActionRequest> for Actio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_action_service(
|
pub fn create_action_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tc_in_mem_converter: EcssTcInMemConverter,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
action_router: GenericRequestRouter,
|
action_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||||
) -> ActionServiceWrapper {
|
) -> ActionServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let action_request_handler = PusTargetedRequestService::new(
|
let action_request_handler = PusTargetedRequestService::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
PUS_ACTION_SERVICE.id(),
|
PUS_ACTION_SERVICE.id(),
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_ACTION_SERVICE.id(), PUS_ACTION_SERVICE.apid),
|
create_verification_reporter(PUS_ACTION_SERVICE.id(), PUS_ACTION_SERVICE.apid),
|
||||||
tc_in_mem_converter,
|
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
||||||
),
|
),
|
||||||
ActionRequestConverter::default(),
|
ActionRequestConverter::default(),
|
||||||
// TODO: Implementation which does not use run-time allocation? Maybe something like
|
// TODO: Implementation which does not use run-time allocation? Maybe something like
|
||||||
@ -233,9 +235,36 @@ pub fn create_action_service(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActionServiceWrapper {
|
pub fn create_action_service_dynamic(
|
||||||
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
action_router: GenericRequestRouter,
|
||||||
|
reply_receiver: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||||
|
) -> ActionServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
|
let action_request_handler = PusTargetedRequestService::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_ACTION_SERVICE.id(),
|
||||||
|
pus_action_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_ACTION_SERVICE.id(), PUS_ACTION_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
ActionRequestConverter::default(),
|
||||||
|
DefaultActiveActionRequestMap::default(),
|
||||||
|
ActionReplyHandler::default(),
|
||||||
|
action_router,
|
||||||
|
reply_receiver,
|
||||||
|
);
|
||||||
|
ActionServiceWrapper {
|
||||||
|
service: action_request_handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ActionServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
pub(crate) service: PusTargetedRequestService<
|
pub(crate) service: PusTargetedRequestService<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
|
TmSender,
|
||||||
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
ActionRequestConverter,
|
ActionRequestConverter,
|
||||||
ActionReplyHandler,
|
ActionReplyHandler,
|
||||||
@ -246,7 +275,9 @@ pub struct ActionServiceWrapper {
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetedPusService for ActionServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> TargetedPusService
|
||||||
|
for ActionServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
const SERVICE_ID: u8 = PusServiceId::Action as u8;
|
const SERVICE_ID: u8 = PusServiceId::Action as u8;
|
||||||
const SERVICE_STR: &'static str = "action";
|
const SERVICE_STR: &'static str = "action";
|
||||||
|
|
||||||
@ -272,10 +303,9 @@ mod tests {
|
|||||||
use satrs::pus::test_util::{
|
use satrs::pus::test_util::{
|
||||||
TEST_APID, TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
TEST_APID, TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
||||||
};
|
};
|
||||||
|
use satrs::pus::verification;
|
||||||
use satrs::pus::verification::test_util::TestVerificationReporter;
|
use satrs::pus::verification::test_util::TestVerificationReporter;
|
||||||
use satrs::pus::{verification, EcssTcInVecConverter};
|
|
||||||
use satrs::request::MessageMetadata;
|
use satrs::request::MessageMetadata;
|
||||||
use satrs::tmtc::PacketAsVec;
|
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
res_code::ResultU16,
|
res_code::ResultU16,
|
||||||
@ -308,7 +338,7 @@ mod tests {
|
|||||||
{
|
{
|
||||||
pub fn new_for_action(owner_id: ComponentId, target_id: ComponentId) -> Self {
|
pub fn new_for_action(owner_id: ComponentId, target_id: ComponentId) -> Self {
|
||||||
let _ = env_logger::builder().is_test(true).try_init();
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
let (tm_funnel_tx, tm_funnel_rx) = mpsc::sync_channel(5);
|
let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel();
|
||||||
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
||||||
let (action_req_tx, action_req_rx) = mpsc::sync_channel(10);
|
let (action_req_tx, action_req_rx) = mpsc::sync_channel(10);
|
||||||
@ -322,9 +352,9 @@ mod tests {
|
|||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
owner_id,
|
owner_id,
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
TmTcSender::Heap(tm_funnel_tx.clone()),
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter,
|
verif_reporter,
|
||||||
EcssTcInMemConverter::Heap(EcssTcInVecConverter::default()),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
ActionRequestConverter::default(),
|
ActionRequestConverter::default(),
|
||||||
DefaultActiveActionRequestMap::default(),
|
DefaultActiveActionRequestMap::default(),
|
||||||
@ -367,7 +397,7 @@ mod tests {
|
|||||||
if let Err(mpsc::TryRecvError::Empty) = packet {
|
if let Err(mpsc::TryRecvError::Empty) = packet {
|
||||||
} else {
|
} else {
|
||||||
let tm = packet.unwrap();
|
let tm = packet.unwrap();
|
||||||
let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap();
|
let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap().0;
|
||||||
panic!("unexpected TM packet {unexpected_tm:?}");
|
panic!("unexpected TM packet {unexpected_tm:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,11 +440,7 @@ mod tests {
|
|||||||
|
|
||||||
pub fn add_tc(&mut self, tc: &PusTcCreator) {
|
pub fn add_tc(&mut self, tc: &PusTcCreator) {
|
||||||
self.request_id = Some(verification::RequestId::new(tc).into());
|
self.request_id = Some(verification::RequestId::new(tc).into());
|
||||||
let token = self
|
let token = self.service.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
.service
|
|
||||||
.service_helper
|
|
||||||
.verif_reporter_mut()
|
|
||||||
.start_verification(tc);
|
|
||||||
let accepted_token = self
|
let accepted_token = self
|
||||||
.service
|
.service
|
||||||
.service_helper
|
.service_helper
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use crate::pus::create_verification_reporter;
|
use crate::pus::create_verification_reporter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::event_man::EventRequestWithToken;
|
use satrs::pus::event_man::EventRequestWithToken;
|
||||||
use satrs::pus::event_srv::PusEventServiceHandler;
|
use satrs::pus::event_srv::PusEventServiceHandler;
|
||||||
use satrs::pus::verification::VerificationReporter;
|
use satrs::pus::verification::VerificationReporter;
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConverter, MpscTcReceiver,
|
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConverter,
|
||||||
PartialPusHandlingError, PusServiceHelper,
|
EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTmSender, MpscTcReceiver,
|
||||||
|
MpscTmAsVecSender, PartialPusHandlingError, PusServiceHelper,
|
||||||
};
|
};
|
||||||
use satrs::spacepackets::ecss::PusServiceId;
|
use satrs::spacepackets::ecss::PusServiceId;
|
||||||
use satrs_example::config::pus::PUS_EVENT_MANAGEMENT;
|
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||||
|
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
||||||
|
|
||||||
use super::{DirectPusService, HandlingStatus};
|
use super::{DirectPusService, HandlingStatus};
|
||||||
|
|
||||||
pub fn create_event_service(
|
pub fn create_event_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tm_in_pool_converter: EcssTcInMemConverter,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||||
) -> EventServiceWrapper {
|
) -> EventServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let pus_5_handler = PusEventServiceHandler::new(
|
let pus_5_handler = PusEventServiceHandler::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
PUS_EVENT_MANAGEMENT.id(),
|
PUS_EVENT_MANAGEMENT.id(),
|
||||||
pus_event_rx,
|
pus_event_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_EVENT_MANAGEMENT.id(), PUS_EVENT_MANAGEMENT.apid),
|
create_verification_reporter(PUS_EVENT_MANAGEMENT.id(), PUS_EVENT_MANAGEMENT.apid),
|
||||||
tm_in_pool_converter,
|
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
||||||
),
|
),
|
||||||
event_request_tx,
|
event_request_tx,
|
||||||
);
|
);
|
||||||
@ -35,16 +37,34 @@ pub fn create_event_service(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventServiceWrapper {
|
pub fn create_event_service_dynamic(
|
||||||
pub handler: PusEventServiceHandler<
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
MpscTcReceiver,
|
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
TmTcSender,
|
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||||
EcssTcInMemConverter,
|
) -> EventServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
VerificationReporter,
|
let pus_5_handler = PusEventServiceHandler::new(
|
||||||
>,
|
PusServiceHelper::new(
|
||||||
|
PUS_EVENT_MANAGEMENT.id(),
|
||||||
|
pus_event_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_EVENT_MANAGEMENT.id(), PUS_EVENT_MANAGEMENT.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
event_request_tx,
|
||||||
|
);
|
||||||
|
EventServiceWrapper {
|
||||||
|
handler: pus_5_handler,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectPusService for EventServiceWrapper {
|
pub struct EventServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
|
pub handler:
|
||||||
|
PusEventServiceHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusService
|
||||||
|
for EventServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
const SERVICE_ID: u8 = PusServiceId::Event as u8;
|
const SERVICE_ID: u8 = PusServiceId::Event as u8;
|
||||||
|
|
||||||
const SERVICE_STR: &'static str = "events";
|
const SERVICE_STR: &'static str = "events";
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use satrs::hk::{CollectionIntervalFactor, HkRequest, HkRequestVariant, UniqueId};
|
use satrs::hk::{CollectionIntervalFactor, HkRequest, HkRequestVariant, UniqueId};
|
||||||
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
FailParams, TcStateAccepted, TcStateStarted, VerificationReporter,
|
FailParams, TcStateAccepted, TcStateStarted, VerificationReporter,
|
||||||
VerificationReportingProvider, VerificationToken,
|
VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, EcssTcAndToken,
|
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, EcssTcAndToken,
|
||||||
EcssTcInMemConverter, EcssTmSender, EcssTmtcError, GenericConversionError, MpscTcReceiver,
|
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTmSender,
|
||||||
|
EcssTmtcError, GenericConversionError, MpscTcReceiver, MpscTmAsVecSender,
|
||||||
PusPacketHandlingError, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter,
|
PusPacketHandlingError, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter,
|
||||||
};
|
};
|
||||||
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
||||||
use satrs::res_code::ResultU16;
|
use satrs::res_code::ResultU16;
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId};
|
use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId};
|
||||||
use satrs_example::config::pus::PUS_HK_SERVICE;
|
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||||
|
use satrs_example::config::components::PUS_HK_SERVICE;
|
||||||
use satrs_example::config::{hk_err, tmtc_err};
|
use satrs_example::config::{hk_err, tmtc_err};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::pus::{create_verification_reporter, generic_pus_request_timeout_handler};
|
use crate::pus::{create_verification_reporter, generic_pus_request_timeout_handler};
|
||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
|
|
||||||
use super::{HandlingStatus, PusTargetedRequestService, TargetedPusService};
|
use super::{HandlingStatus, PusTargetedRequestService, TargetedPusService};
|
||||||
|
|
||||||
@ -240,20 +242,20 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_hk_service(
|
pub fn create_hk_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tc_in_mem_converter: EcssTcInMemConverter,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
request_router: GenericRequestRouter,
|
request_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
) -> HkServiceWrapper {
|
) -> HkServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let pus_3_handler = PusTargetedRequestService::new(
|
let pus_3_handler = PusTargetedRequestService::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
PUS_HK_SERVICE.id(),
|
PUS_HK_SERVICE.id(),
|
||||||
pus_hk_rx,
|
pus_hk_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_HK_SERVICE.id(), PUS_HK_SERVICE.apid),
|
create_verification_reporter(PUS_HK_SERVICE.id(), PUS_HK_SERVICE.apid),
|
||||||
tc_in_mem_converter,
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
),
|
),
|
||||||
HkRequestConverter::default(),
|
HkRequestConverter::default(),
|
||||||
DefaultActiveRequestMap::default(),
|
DefaultActiveRequestMap::default(),
|
||||||
@ -266,9 +268,36 @@ pub fn create_hk_service(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HkServiceWrapper {
|
pub fn create_hk_service_dynamic(
|
||||||
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
request_router: GenericRequestRouter,
|
||||||
|
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
|
) -> HkServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
|
let pus_3_handler = PusTargetedRequestService::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_HK_SERVICE.id(),
|
||||||
|
pus_hk_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_HK_SERVICE.id(), PUS_HK_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
HkRequestConverter::default(),
|
||||||
|
DefaultActiveRequestMap::default(),
|
||||||
|
HkReplyHandler::default(),
|
||||||
|
request_router,
|
||||||
|
reply_receiver,
|
||||||
|
);
|
||||||
|
HkServiceWrapper {
|
||||||
|
service: pus_3_handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HkServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
pub(crate) service: PusTargetedRequestService<
|
pub(crate) service: PusTargetedRequestService<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
|
TmSender,
|
||||||
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
HkRequestConverter,
|
HkRequestConverter,
|
||||||
HkReplyHandler,
|
HkReplyHandler,
|
||||||
@ -279,7 +308,9 @@ pub struct HkServiceWrapper {
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetedPusService for HkServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> TargetedPusService
|
||||||
|
for HkServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
const SERVICE_ID: u8 = PusServiceId::Housekeeping as u8;
|
const SERVICE_ID: u8 = PusServiceId::Housekeeping as u8;
|
||||||
const SERVICE_STR: &'static str = "housekeeping";
|
const SERVICE_STR: &'static str = "housekeeping";
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use satrs::pool::PoolAddr;
|
use satrs::pool::PoolAddr;
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
@ -7,10 +6,10 @@ use satrs::pus::verification::{
|
|||||||
VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActiveRequestMapProvider, ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConversionProvider,
|
ActiveRequestMapProvider, ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter,
|
||||||
EcssTcInMemConverter, EcssTcReceiver, EcssTmSender, EcssTmtcError, GenericConversionError,
|
EcssTcReceiver, EcssTmSender, EcssTmtcError, GenericConversionError, GenericRoutingError,
|
||||||
GenericRoutingError, HandlingStatus, PusPacketHandlingError, PusReplyHandler, PusRequestRouter,
|
HandlingStatus, PusPacketHandlingError, PusReplyHandler, PusRequestRouter, PusServiceHelper,
|
||||||
PusServiceHelper, PusTcToRequestConverter, TcInMemory,
|
PusTcToRequestConverter, TcInMemory,
|
||||||
};
|
};
|
||||||
use satrs::queue::{GenericReceiveError, GenericSendError};
|
use satrs::queue::{GenericReceiveError, GenericSendError};
|
||||||
use satrs::request::{Apid, GenericMessage, MessageMetadata};
|
use satrs::request::{Apid, GenericMessage, MessageMetadata};
|
||||||
@ -18,11 +17,11 @@ use satrs::spacepackets::ecss::tc::PusTcReader;
|
|||||||
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
|
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
|
||||||
use satrs::tmtc::{PacketAsVec, PacketInPool};
|
use satrs::tmtc::{PacketAsVec, PacketInPool};
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs_example::config::pus::PUS_ROUTING_SERVICE;
|
use satrs_example::config::components::PUS_ROUTING_SERVICE;
|
||||||
use satrs_example::config::{tmtc_err, CustomPusServiceId};
|
use satrs_example::config::{tmtc_err, CustomPusServiceId};
|
||||||
use satrs_example::TimestampHelper;
|
use satrs_example::TimestampHelper;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc::{self, Sender};
|
||||||
|
|
||||||
pub mod action;
|
pub mod action;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
@ -41,26 +40,26 @@ pub fn create_verification_reporter(owner_id: ComponentId, apid: Apid) -> Verifi
|
|||||||
|
|
||||||
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
||||||
pub struct PusTcMpscRouter {
|
pub struct PusTcMpscRouter {
|
||||||
pub test_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub test_tc_sender: Sender<EcssTcAndToken>,
|
||||||
pub event_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub event_tc_sender: Sender<EcssTcAndToken>,
|
||||||
pub sched_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub sched_tc_sender: Sender<EcssTcAndToken>,
|
||||||
pub hk_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub hk_tc_sender: Sender<EcssTcAndToken>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub action_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub action_tc_sender: Sender<EcssTcAndToken>,
|
||||||
pub mode_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub mode_tc_sender: Sender<EcssTcAndToken>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PusTcDistributor {
|
pub struct PusTcDistributor<TmSender: EcssTmSender> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub id: ComponentId,
|
pub id: ComponentId,
|
||||||
pub tm_sender: TmTcSender,
|
pub tm_sender: TmSender,
|
||||||
pub verif_reporter: VerificationReporter,
|
pub verif_reporter: VerificationReporter,
|
||||||
pub pus_router: PusTcMpscRouter,
|
pub pus_router: PusTcMpscRouter,
|
||||||
stamp_helper: TimestampHelper,
|
stamp_helper: TimestampHelper,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusTcDistributor {
|
impl<TmSender: EcssTmSender> PusTcDistributor<TmSender> {
|
||||||
pub fn new(tm_sender: TmTcSender, pus_router: PusTcMpscRouter) -> Self {
|
pub fn new(tm_sender: TmSender, pus_router: PusTcMpscRouter) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: PUS_ROUTING_SERVICE.raw(),
|
id: PUS_ROUTING_SERVICE.raw(),
|
||||||
tm_sender,
|
tm_sender,
|
||||||
@ -109,8 +108,8 @@ impl PusTcDistributor {
|
|||||||
// TODO: Shouldn't this be an error?
|
// TODO: Shouldn't this be an error?
|
||||||
return Ok(HandlingStatus::HandledOne);
|
return Ok(HandlingStatus::HandledOne);
|
||||||
}
|
}
|
||||||
let pus_tc = pus_tc_result.unwrap();
|
let pus_tc = pus_tc_result.unwrap().0;
|
||||||
let init_token = self.verif_reporter.start_verification(&pus_tc);
|
let init_token = self.verif_reporter.add_tc(&pus_tc);
|
||||||
self.stamp_helper.update_from_now();
|
self.stamp_helper.update_from_now();
|
||||||
let accepted_token = self
|
let accepted_token = self
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
@ -269,6 +268,8 @@ pub trait DirectPusService {
|
|||||||
/// 3. [Self::check_for_request_timeouts] which checks for request timeouts, covering step 7.
|
/// 3. [Self::check_for_request_timeouts] which checks for request timeouts, covering step 7.
|
||||||
pub struct PusTargetedRequestService<
|
pub struct PusTargetedRequestService<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
RequestConverter: PusTcToRequestConverter<ActiveRequestInfo, RequestType, Error = GenericConversionError>,
|
RequestConverter: PusTcToRequestConverter<ActiveRequestInfo, RequestType, Error = GenericConversionError>,
|
||||||
ReplyHandler: PusReplyHandler<ActiveRequestInfo, ReplyType, Error = EcssTmtcError>,
|
ReplyHandler: PusReplyHandler<ActiveRequestInfo, ReplyType, Error = EcssTmtcError>,
|
||||||
@ -278,7 +279,7 @@ pub struct PusTargetedRequestService<
|
|||||||
ReplyType,
|
ReplyType,
|
||||||
> {
|
> {
|
||||||
pub service_helper:
|
pub service_helper:
|
||||||
PusServiceHelper<TcReceiver, TmTcSender, EcssTcInMemConverter, VerificationReporter>,
|
PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
pub request_router: GenericRequestRouter,
|
pub request_router: GenericRequestRouter,
|
||||||
pub request_converter: RequestConverter,
|
pub request_converter: RequestConverter,
|
||||||
pub active_request_map: ActiveRequestMap,
|
pub active_request_map: ActiveRequestMap,
|
||||||
@ -289,6 +290,8 @@ pub struct PusTargetedRequestService<
|
|||||||
|
|
||||||
impl<
|
impl<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
|
TmSender: EcssTmSender,
|
||||||
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
RequestConverter: PusTcToRequestConverter<ActiveRequestInfo, RequestType, Error = GenericConversionError>,
|
RequestConverter: PusTcToRequestConverter<ActiveRequestInfo, RequestType, Error = GenericConversionError>,
|
||||||
ReplyHandler: PusReplyHandler<ActiveRequestInfo, ReplyType, Error = EcssTmtcError>,
|
ReplyHandler: PusReplyHandler<ActiveRequestInfo, ReplyType, Error = EcssTmtcError>,
|
||||||
@ -299,6 +302,8 @@ impl<
|
|||||||
>
|
>
|
||||||
PusTargetedRequestService<
|
PusTargetedRequestService<
|
||||||
TcReceiver,
|
TcReceiver,
|
||||||
|
TmSender,
|
||||||
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
RequestConverter,
|
RequestConverter,
|
||||||
ReplyHandler,
|
ReplyHandler,
|
||||||
@ -313,8 +318,8 @@ where
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
service_helper: PusServiceHelper<
|
service_helper: PusServiceHelper<
|
||||||
TcReceiver,
|
TcReceiver,
|
||||||
TmTcSender,
|
TmSender,
|
||||||
EcssTcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>,
|
>,
|
||||||
request_converter: RequestConverter,
|
request_converter: RequestConverter,
|
||||||
@ -540,7 +545,7 @@ pub(crate) mod tests {
|
|||||||
use satrs::{
|
use satrs::{
|
||||||
pus::{
|
pus::{
|
||||||
verification::test_util::TestVerificationReporter, ActivePusRequestStd,
|
verification::test_util::TestVerificationReporter, ActivePusRequestStd,
|
||||||
ActiveRequestMapProvider, MpscTcReceiver,
|
ActiveRequestMapProvider, EcssTcInVecConverter, MpscTcReceiver,
|
||||||
},
|
},
|
||||||
request::UniqueApidTargetId,
|
request::UniqueApidTargetId,
|
||||||
spacepackets::{
|
spacepackets::{
|
||||||
@ -599,7 +604,7 @@ pub(crate) mod tests {
|
|||||||
) -> (verification::RequestId, ActivePusRequestStd) {
|
) -> (verification::RequestId, ActivePusRequestStd) {
|
||||||
let sp_header = SpHeader::new_from_apid(apid);
|
let sp_header = SpHeader::new_from_apid(apid);
|
||||||
let sec_header_dummy = PusTcSecondaryHeader::new_simple(0, 0);
|
let sec_header_dummy = PusTcSecondaryHeader::new_simple(0, 0);
|
||||||
let init = self.verif_reporter.start_verification(&PusTcCreator::new(
|
let init = self.verif_reporter.add_tc(&PusTcCreator::new(
|
||||||
sp_header,
|
sp_header,
|
||||||
sec_header_dummy,
|
sec_header_dummy,
|
||||||
&[],
|
&[],
|
||||||
@ -706,7 +711,7 @@ pub(crate) mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
pub fn add_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
let token = self.verif_reporter.start_verification(tc);
|
let token = self.verif_reporter.add_tc(tc);
|
||||||
self.current_request_id = Some(verification::RequestId::new(tc));
|
self.current_request_id = Some(verification::RequestId::new(tc));
|
||||||
self.current_packet = Some(tc.to_vec().unwrap());
|
self.current_packet = Some(tc.to_vec().unwrap());
|
||||||
self.verif_reporter
|
self.verif_reporter
|
||||||
@ -734,7 +739,7 @@ pub(crate) mod tests {
|
|||||||
let tc_reader = PusTcReader::new(¤t_packet).unwrap();
|
let tc_reader = PusTcReader::new(¤t_packet).unwrap();
|
||||||
let (active_info, request) = self.converter.convert(
|
let (active_info, request) = self.converter.convert(
|
||||||
token,
|
token,
|
||||||
&tc_reader,
|
&tc_reader.0,
|
||||||
&self.dummy_sender,
|
&self.dummy_sender,
|
||||||
&self.verif_reporter,
|
&self.verif_reporter,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -761,6 +766,8 @@ pub(crate) mod tests {
|
|||||||
> {
|
> {
|
||||||
pub service: PusTargetedRequestService<
|
pub service: PusTargetedRequestService<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
|
MpscTmAsVecSender,
|
||||||
|
EcssTcInVecConverter,
|
||||||
TestVerificationReporter,
|
TestVerificationReporter,
|
||||||
RequestConverter,
|
RequestConverter,
|
||||||
ReplyHandler,
|
ReplyHandler,
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use satrs::mode_tree::{ModeNode, ModeParent};
|
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||||
use satrs_example::config::pus::PUS_MODE_SERVICE;
|
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::verification::VerificationReporter;
|
use satrs::pus::verification::VerificationReporter;
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
DefaultActiveRequestMap, EcssTcAndToken, EcssTcInMemConverter, MpscTcReceiver,
|
DefaultActiveRequestMap, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
||||||
PusPacketHandlingError, PusServiceHelper,
|
EcssTcInVecConverter, MpscTcReceiver, MpscTmAsVecSender, PusPacketHandlingError,
|
||||||
|
PusServiceHelper,
|
||||||
};
|
};
|
||||||
use satrs::request::GenericMessage;
|
use satrs::request::GenericMessage;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
@ -34,6 +34,7 @@ use satrs::{
|
|||||||
},
|
},
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
use satrs_example::config::components::PUS_MODE_SERVICE;
|
||||||
use satrs_example::config::{mode_err, tmtc_err, CustomPusServiceId};
|
use satrs_example::config::{mode_err, tmtc_err, CustomPusServiceId};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -109,7 +110,6 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
ModeReply::ModeInfo(_mode_and_submode) => (),
|
|
||||||
};
|
};
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@ -190,13 +190,7 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
}
|
}
|
||||||
let mode_and_submode = ModeAndSubmode::from_be_bytes(&tc.user_data()[4..])
|
let mode_and_submode = ModeAndSubmode::from_be_bytes(&tc.user_data()[4..])
|
||||||
.expect("mode and submode extraction failed");
|
.expect("mode and submode extraction failed");
|
||||||
Ok((
|
Ok((active_request, ModeRequest::SetMode(mode_and_submode)))
|
||||||
active_request,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode,
|
|
||||||
forced: false,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
Subservice::TcReadMode => Ok((active_request, ModeRequest::ReadMode)),
|
Subservice::TcReadMode => Ok((active_request, ModeRequest::ReadMode)),
|
||||||
Subservice::TcAnnounceMode => Ok((active_request, ModeRequest::AnnounceMode)),
|
Subservice::TcAnnounceMode => Ok((active_request, ModeRequest::AnnounceMode)),
|
||||||
@ -208,20 +202,20 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_mode_service(
|
pub fn create_mode_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tc_in_mem_converter: EcssTcInMemConverter,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
mode_router: GenericRequestRouter,
|
mode_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<ModeReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
) -> ModeServiceWrapper {
|
) -> ModeServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let mode_request_handler = PusTargetedRequestService::new(
|
let mode_request_handler = PusTargetedRequestService::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
PUS_MODE_SERVICE.id(),
|
PUS_MODE_SERVICE.id(),
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_MODE_SERVICE.id(), PUS_MODE_SERVICE.apid),
|
create_verification_reporter(PUS_MODE_SERVICE.id(), PUS_MODE_SERVICE.apid),
|
||||||
tc_in_mem_converter,
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
),
|
),
|
||||||
ModeRequestConverter::default(),
|
ModeRequestConverter::default(),
|
||||||
DefaultActiveRequestMap::default(),
|
DefaultActiveRequestMap::default(),
|
||||||
@ -234,9 +228,36 @@ pub fn create_mode_service(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModeServiceWrapper {
|
pub fn create_mode_service_dynamic(
|
||||||
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
mode_router: GenericRequestRouter,
|
||||||
|
reply_receiver: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
|
) -> ModeServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
|
let mode_request_handler = PusTargetedRequestService::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_MODE_SERVICE.id(),
|
||||||
|
pus_action_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_MODE_SERVICE.id(), PUS_MODE_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
ModeRequestConverter::default(),
|
||||||
|
DefaultActiveRequestMap::default(),
|
||||||
|
ModeReplyHandler::new(PUS_MODE_SERVICE.id()),
|
||||||
|
mode_router,
|
||||||
|
reply_receiver,
|
||||||
|
);
|
||||||
|
ModeServiceWrapper {
|
||||||
|
service: mode_request_handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ModeServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
pub(crate) service: PusTargetedRequestService<
|
pub(crate) service: PusTargetedRequestService<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
|
TmSender,
|
||||||
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
ModeRequestConverter,
|
ModeRequestConverter,
|
||||||
ModeReplyHandler,
|
ModeReplyHandler,
|
||||||
@ -247,24 +268,9 @@ pub struct ModeServiceWrapper {
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModeNode for ModeServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> TargetedPusService
|
||||||
fn id(&self) -> ComponentId {
|
for ModeServiceWrapper<TmSender, TcInMemConverter>
|
||||||
self.service.service_helper.id()
|
{
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeParent for ModeServiceWrapper {
|
|
||||||
type Sender = mpsc::SyncSender<GenericMessage<ModeRequest>>;
|
|
||||||
|
|
||||||
fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender) {
|
|
||||||
self.service
|
|
||||||
.request_router
|
|
||||||
.mode_router_map
|
|
||||||
.insert(id, request_sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TargetedPusService for ModeServiceWrapper {
|
|
||||||
const SERVICE_ID: u8 = CustomPusServiceId::Mode as u8;
|
const SERVICE_ID: u8 = CustomPusServiceId::Mode as u8;
|
||||||
const SERVICE_STR: &'static str = "mode";
|
const SERVICE_STR: &'static str = "mode";
|
||||||
|
|
||||||
@ -340,13 +346,7 @@ mod tests {
|
|||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)
|
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)
|
||||||
.expect("conversion has failed");
|
.expect("conversion has failed");
|
||||||
assert_eq!(
|
assert_eq!(req, ModeRequest::SetMode(mode_and_submode));
|
||||||
req,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode,
|
|
||||||
forced: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2,28 +2,28 @@ use std::sync::mpsc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::pus::create_verification_reporter;
|
use crate::pus::create_verification_reporter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use satrs::pool::{PoolProvider, StaticMemoryPool};
|
use satrs::pool::{PoolProvider, StaticMemoryPool};
|
||||||
use satrs::pus::scheduler::{PusScheduler, TcInfo};
|
use satrs::pus::scheduler::{PusScheduler, TcInfo};
|
||||||
use satrs::pus::scheduler_srv::PusSchedServiceHandler;
|
use satrs::pus::scheduler_srv::PusSchedServiceHandler;
|
||||||
use satrs::pus::verification::VerificationReporter;
|
use satrs::pus::verification::VerificationReporter;
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConverter, MpscTcReceiver,
|
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConverter,
|
||||||
PartialPusHandlingError, PusServiceHelper,
|
EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTmSender, MpscTcReceiver,
|
||||||
|
MpscTmAsVecSender, PartialPusHandlingError, PusServiceHelper,
|
||||||
};
|
};
|
||||||
use satrs::spacepackets::ecss::PusServiceId;
|
use satrs::spacepackets::ecss::PusServiceId;
|
||||||
use satrs::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool};
|
use satrs::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool};
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs_example::config::pus::PUS_SCHED_SERVICE;
|
use satrs_example::config::components::PUS_SCHED_SERVICE;
|
||||||
|
|
||||||
use super::{DirectPusService, HandlingStatus};
|
use super::{DirectPusService, HandlingStatus};
|
||||||
|
|
||||||
pub trait TcReleaseProvider {
|
pub trait TcReleaser {
|
||||||
fn release(&mut self, sender_id: ComponentId, enabled: bool, info: &TcInfo, tc: &[u8]) -> bool;
|
fn release(&mut self, sender_id: ComponentId, enabled: bool, info: &TcInfo, tc: &[u8]) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcReleaseProvider for PacketSenderWithSharedPool {
|
impl TcReleaser for PacketSenderWithSharedPool {
|
||||||
fn release(
|
fn release(
|
||||||
&mut self,
|
&mut self,
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
@ -48,7 +48,7 @@ impl TcReleaseProvider for PacketSenderWithSharedPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcReleaseProvider for mpsc::SyncSender<PacketAsVec> {
|
impl TcReleaser for mpsc::Sender<PacketAsVec> {
|
||||||
fn release(
|
fn release(
|
||||||
&mut self,
|
&mut self,
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
@ -65,35 +65,23 @@ impl TcReleaseProvider for mpsc::SyncSender<PacketAsVec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
pub struct SchedulingServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
|
||||||
pub enum TcReleaser {
|
{
|
||||||
Static(PacketSenderWithSharedPool),
|
|
||||||
Heap(mpsc::SyncSender<PacketAsVec>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TcReleaseProvider for TcReleaser {
|
|
||||||
fn release(&mut self, sender_id: ComponentId, enabled: bool, info: &TcInfo, tc: &[u8]) -> bool {
|
|
||||||
match self {
|
|
||||||
TcReleaser::Static(sender) => sender.release(sender_id, enabled, info, tc),
|
|
||||||
TcReleaser::Heap(sender) => sender.release(sender_id, enabled, info, tc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SchedulingServiceWrapper {
|
|
||||||
pub pus_11_handler: PusSchedServiceHandler<
|
pub pus_11_handler: PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmTcSender,
|
TmSender,
|
||||||
EcssTcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>,
|
>,
|
||||||
pub sched_tc_pool: StaticMemoryPool,
|
pub sched_tc_pool: StaticMemoryPool,
|
||||||
pub releaser_buf: [u8; 4096],
|
pub releaser_buf: [u8; 4096],
|
||||||
pub tc_releaser: TcReleaser,
|
pub tc_releaser: Box<dyn TcReleaser + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectPusService for SchedulingServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusService
|
||||||
|
for SchedulingServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
const SERVICE_ID: u8 = PusServiceId::Verification as u8;
|
const SERVICE_ID: u8 = PusServiceId::Verification as u8;
|
||||||
|
|
||||||
const SERVICE_STR: &'static str = "verification";
|
const SERVICE_STR: &'static str = "verification";
|
||||||
@ -146,7 +134,9 @@ impl DirectPusService for SchedulingServiceWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SchedulingServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
|
||||||
|
SchedulingServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
pub fn release_tcs(&mut self) {
|
pub fn release_tcs(&mut self) {
|
||||||
let id = self.pus_11_handler.service_helper.id();
|
let id = self.pus_11_handler.service_helper.id();
|
||||||
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
|
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
|
||||||
@ -172,13 +162,12 @@ impl SchedulingServiceWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_scheduler_service(
|
pub fn create_scheduler_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tc_in_mem_converter: EcssTcInMemConverter,
|
tc_releaser: PacketSenderWithSharedPool,
|
||||||
tc_releaser: TcReleaser,
|
|
||||||
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
sched_tc_pool: StaticMemoryPool,
|
sched_tc_pool: StaticMemoryPool,
|
||||||
) -> SchedulingServiceWrapper {
|
) -> SchedulingServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
||||||
.expect("Creating PUS Scheduler failed");
|
.expect("Creating PUS Scheduler failed");
|
||||||
let pus_11_handler = PusSchedServiceHandler::new(
|
let pus_11_handler = PusSchedServiceHandler::new(
|
||||||
@ -187,7 +176,7 @@ pub fn create_scheduler_service(
|
|||||||
pus_sched_rx,
|
pus_sched_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_SCHED_SERVICE.id(), PUS_SCHED_SERVICE.apid),
|
create_verification_reporter(PUS_SCHED_SERVICE.id(), PUS_SCHED_SERVICE.apid),
|
||||||
tc_in_mem_converter,
|
EcssTcInSharedStoreConverter::new(tc_releaser.shared_packet_store().0.clone(), 2048),
|
||||||
),
|
),
|
||||||
scheduler,
|
scheduler,
|
||||||
);
|
);
|
||||||
@ -195,6 +184,34 @@ pub fn create_scheduler_service(
|
|||||||
pus_11_handler,
|
pus_11_handler,
|
||||||
sched_tc_pool,
|
sched_tc_pool,
|
||||||
releaser_buf: [0; 4096],
|
releaser_buf: [0; 4096],
|
||||||
tc_releaser,
|
tc_releaser: Box::new(tc_releaser),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_scheduler_service_dynamic(
|
||||||
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
|
tc_source_sender: mpsc::Sender<PacketAsVec>,
|
||||||
|
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
sched_tc_pool: StaticMemoryPool,
|
||||||
|
) -> SchedulingServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
|
//let sched_srv_receiver =
|
||||||
|
//MpscTcReceiver::new(PUS_SCHED_SERVICE.raw(), "PUS_11_TC_RECV", pus_sched_rx);
|
||||||
|
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
||||||
|
.expect("Creating PUS Scheduler failed");
|
||||||
|
let pus_11_handler = PusSchedServiceHandler::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_SCHED_SERVICE.id(),
|
||||||
|
pus_sched_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_SCHED_SERVICE.id(), PUS_SCHED_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
scheduler,
|
||||||
|
);
|
||||||
|
SchedulingServiceWrapper {
|
||||||
|
pus_11_handler,
|
||||||
|
sched_tc_pool,
|
||||||
|
releaser_buf: [0; 4096],
|
||||||
|
tc_releaser: Box::new(tc_source_sender),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::pus::mode::ModeServiceWrapper;
|
use crate::pus::mode::ModeServiceWrapper;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use satrs::spacepackets::time::{cds, TimeWriter};
|
use satrs::{
|
||||||
|
pus::{EcssTcInMemConverter, EcssTmSender},
|
||||||
|
spacepackets::time::{cds, TimeWriter},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper,
|
action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper,
|
||||||
@ -8,17 +11,21 @@ use super::{
|
|||||||
HandlingStatus, TargetedPusService,
|
HandlingStatus, TargetedPusService,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: For better extensibility, we could create 2 vectors: One for direct PUS services and one
|
||||||
|
// for targeted services..
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
pub struct PusStack {
|
pub struct PusStack<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
pub test_srv: TestCustomServiceWrapper,
|
test_srv: TestCustomServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
pub hk_srv_wrapper: HkServiceWrapper,
|
hk_srv_wrapper: HkServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
pub event_srv: EventServiceWrapper,
|
event_srv: EventServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
pub action_srv_wrapper: ActionServiceWrapper,
|
action_srv_wrapper: ActionServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
pub schedule_srv: SchedulingServiceWrapper,
|
schedule_srv: SchedulingServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
pub mode_srv: ModeServiceWrapper,
|
mode_srv: ModeServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusStack {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
|
||||||
|
PusStack<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
pub fn periodic_operation(&mut self) {
|
pub fn periodic_operation(&mut self) {
|
||||||
// Release all telecommands which reached their release time before calling the service
|
// Release all telecommands which reached their release time before calling the service
|
||||||
// handlers.
|
// handlers.
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
use crate::pus::create_verification_reporter;
|
use crate::pus::create_verification_reporter;
|
||||||
use crate::tmtc::sender::TmTcSender;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use satrs::event_man::{EventMessage, EventMessageU32};
|
use satrs::event_man::{EventMessage, EventMessageU32};
|
||||||
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::test::PusService17TestHandler;
|
use satrs::pus::test::PusService17TestHandler;
|
||||||
use satrs::pus::verification::{FailParams, VerificationReporter, VerificationReportingProvider};
|
use satrs::pus::verification::{FailParams, VerificationReporter, VerificationReportingProvider};
|
||||||
use satrs::pus::PartialPusHandlingError;
|
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConversionProvider,
|
DirectPusPacketHandlerResult, EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter,
|
||||||
EcssTcInMemConverter, MpscTcReceiver, PusServiceHelper,
|
EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, PusServiceHelper,
|
||||||
};
|
};
|
||||||
|
use satrs::pus::{EcssTcInSharedStoreConverter, PartialPusHandlingError};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
|
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
|
||||||
use satrs_example::config::pus::PUS_TEST_SERVICE;
|
use satrs::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||||
|
use satrs_example::config::components::PUS_TEST_SERVICE;
|
||||||
use satrs_example::config::{tmtc_err, TEST_EVENT};
|
use satrs_example::config::{tmtc_err, TEST_EVENT};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use super::{DirectPusService, HandlingStatus};
|
use super::{DirectPusService, HandlingStatus};
|
||||||
|
|
||||||
pub fn create_test_service(
|
pub fn create_test_service_static(
|
||||||
tm_sender: TmTcSender,
|
tm_sender: PacketSenderWithSharedPool,
|
||||||
tc_in_mem_converter: EcssTcInMemConverter,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
event_sender: mpsc::SyncSender<EventMessageU32>,
|
event_sender: mpsc::SyncSender<EventMessageU32>,
|
||||||
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
) -> TestCustomServiceWrapper {
|
) -> TestCustomServiceWrapper<PacketSenderWithSharedPool, EcssTcInSharedStoreConverter> {
|
||||||
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
||||||
PUS_TEST_SERVICE.id(),
|
PUS_TEST_SERVICE.id(),
|
||||||
pus_test_rx,
|
pus_test_rx,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
create_verification_reporter(PUS_TEST_SERVICE.id(), PUS_TEST_SERVICE.apid),
|
create_verification_reporter(PUS_TEST_SERVICE.id(), PUS_TEST_SERVICE.apid),
|
||||||
tc_in_mem_converter,
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
));
|
));
|
||||||
TestCustomServiceWrapper {
|
TestCustomServiceWrapper {
|
||||||
handler: pus17_handler,
|
handler: pus17_handler,
|
||||||
@ -36,17 +37,34 @@ pub fn create_test_service(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestCustomServiceWrapper {
|
pub fn create_test_service_dynamic(
|
||||||
pub handler: PusService17TestHandler<
|
tm_funnel_tx: mpsc::Sender<PacketAsVec>,
|
||||||
MpscTcReceiver,
|
event_sender: mpsc::SyncSender<EventMessageU32>,
|
||||||
TmTcSender,
|
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
EcssTcInMemConverter,
|
) -> TestCustomServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
VerificationReporter,
|
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
||||||
>,
|
PUS_TEST_SERVICE.id(),
|
||||||
|
pus_test_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_TEST_SERVICE.id(), PUS_TEST_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
));
|
||||||
|
TestCustomServiceWrapper {
|
||||||
|
handler: pus17_handler,
|
||||||
|
event_tx: event_sender,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TestCustomServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
|
||||||
|
{
|
||||||
|
pub handler:
|
||||||
|
PusService17TestHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
pub event_tx: mpsc::SyncSender<EventMessageU32>,
|
pub event_tx: mpsc::SyncSender<EventMessageU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectPusService for TestCustomServiceWrapper {
|
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusService
|
||||||
|
for TestCustomServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
const SERVICE_ID: u8 = PusServiceId::Test as u8;
|
const SERVICE_ID: u8 = PusServiceId::Test as u8;
|
||||||
|
|
||||||
const SERVICE_STR: &'static str = "test";
|
const SERVICE_STR: &'static str = "test";
|
||||||
@ -90,7 +108,7 @@ impl DirectPusService for TestCustomServiceWrapper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
DirectPusPacketHandlerResult::CustomSubservice(subservice, token) => {
|
DirectPusPacketHandlerResult::CustomSubservice(subservice, token) => {
|
||||||
let tc = PusTcReader::new(
|
let (tc, _) = PusTcReader::new(
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.tc_in_mem_converter
|
.tc_in_mem_converter
|
||||||
|
@ -14,7 +14,7 @@ use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
|
|||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::PusPacket;
|
use satrs::spacepackets::ecss::PusPacket;
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs_example::config::pus::PUS_ROUTING_SERVICE;
|
use satrs_example::config::components::PUS_ROUTING_SERVICE;
|
||||||
use satrs_example::config::tmtc_err;
|
use satrs_example::config::tmtc_err;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
use core::fmt::Debug;
|
|
||||||
|
|
||||||
pub trait SpiInterface {
|
|
||||||
type Error: Debug;
|
|
||||||
fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error>;
|
|
||||||
}
|
|
@ -1,3 +1,2 @@
|
|||||||
pub mod sender;
|
|
||||||
pub mod tc_source;
|
pub mod tc_source;
|
||||||
pub mod tm_sink;
|
pub mod tm_sink;
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
use std::{cell::RefCell, collections::VecDeque, sync::mpsc};
|
|
||||||
|
|
||||||
use satrs::{
|
|
||||||
pus::EcssTmSender,
|
|
||||||
queue::GenericSendError,
|
|
||||||
spacepackets::ecss::WritablePusPacket,
|
|
||||||
tmtc::{PacketAsVec, PacketSenderRaw, PacketSenderWithSharedPool, StoreAndSendError},
|
|
||||||
ComponentId,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
|
||||||
pub struct MockSender(pub RefCell<VecDeque<PacketAsVec>>);
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum TmTcSender {
|
|
||||||
Static(PacketSenderWithSharedPool),
|
|
||||||
Heap(mpsc::SyncSender<PacketAsVec>),
|
|
||||||
Mock(MockSender),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TmTcSender {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn get_mock_sender(&mut self) -> Option<&mut MockSender> {
|
|
||||||
match self {
|
|
||||||
TmTcSender::Mock(sender) => Some(sender),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssTmSender for TmTcSender {
|
|
||||||
fn send_tm(
|
|
||||||
&self,
|
|
||||||
sender_id: satrs::ComponentId,
|
|
||||||
tm: satrs::pus::PusTmVariant,
|
|
||||||
) -> Result<(), satrs::pus::EcssTmtcError> {
|
|
||||||
match self {
|
|
||||||
TmTcSender::Static(sync_sender) => sync_sender.send_tm(sender_id, tm),
|
|
||||||
TmTcSender::Heap(sync_sender) => match tm {
|
|
||||||
satrs::pus::PusTmVariant::InStore(_) => panic!("can not send TM in store"),
|
|
||||||
satrs::pus::PusTmVariant::Direct(pus_tm_creator) => sync_sender
|
|
||||||
.send(PacketAsVec::new(sender_id, pus_tm_creator.to_vec()?))
|
|
||||||
.map_err(|_| GenericSendError::RxDisconnected.into()),
|
|
||||||
},
|
|
||||||
TmTcSender::Mock(_) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PacketSenderRaw for TmTcSender {
|
|
||||||
type Error = StoreAndSendError;
|
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
match self {
|
|
||||||
TmTcSender::Static(packet_sender_with_shared_pool) => {
|
|
||||||
packet_sender_with_shared_pool.send_packet(sender_id, packet)
|
|
||||||
}
|
|
||||||
TmTcSender::Heap(sync_sender) => sync_sender
|
|
||||||
.send_packet(sender_id, packet)
|
|
||||||
.map_err(StoreAndSendError::Send),
|
|
||||||
TmTcSender::Mock(sender) => sender.send_packet(sender_id, packet),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PacketSenderRaw for MockSender {
|
|
||||||
type Error = StoreAndSendError;
|
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
let mut mut_queue = self.0.borrow_mut();
|
|
||||||
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,12 @@
|
|||||||
use satrs::{
|
use satrs::{
|
||||||
pool::PoolProvider,
|
pool::PoolProvider,
|
||||||
pus::HandlingStatus,
|
pus::HandlingStatus,
|
||||||
tmtc::{PacketAsVec, PacketInPool, SharedPacketPool},
|
tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool, SharedPacketPool},
|
||||||
};
|
};
|
||||||
use std::sync::mpsc::{self, TryRecvError};
|
use std::sync::mpsc::{self, TryRecvError};
|
||||||
|
|
||||||
|
use satrs::pus::MpscTmAsVecSender;
|
||||||
|
|
||||||
use crate::pus::PusTcDistributor;
|
use crate::pus::PusTcDistributor;
|
||||||
|
|
||||||
// TC source components where static pools are the backing memory of the received telecommands.
|
// TC source components where static pools are the backing memory of the received telecommands.
|
||||||
@ -12,15 +14,14 @@ pub struct TcSourceTaskStatic {
|
|||||||
shared_tc_pool: SharedPacketPool,
|
shared_tc_pool: SharedPacketPool,
|
||||||
tc_receiver: mpsc::Receiver<PacketInPool>,
|
tc_receiver: mpsc::Receiver<PacketInPool>,
|
||||||
tc_buf: [u8; 4096],
|
tc_buf: [u8; 4096],
|
||||||
pus_distributor: PusTcDistributor,
|
pus_distributor: PusTcDistributor<PacketSenderWithSharedPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl TcSourceTaskStatic {
|
impl TcSourceTaskStatic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_tc_pool: SharedPacketPool,
|
shared_tc_pool: SharedPacketPool,
|
||||||
tc_receiver: mpsc::Receiver<PacketInPool>,
|
tc_receiver: mpsc::Receiver<PacketInPool>,
|
||||||
pus_receiver: PusTcDistributor,
|
pus_receiver: PusTcDistributor<PacketSenderWithSharedPool>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
shared_tc_pool,
|
shared_tc_pool,
|
||||||
@ -66,12 +67,14 @@ impl TcSourceTaskStatic {
|
|||||||
// TC source components where the heap is the backing memory of the received telecommands.
|
// TC source components where the heap is the backing memory of the received telecommands.
|
||||||
pub struct TcSourceTaskDynamic {
|
pub struct TcSourceTaskDynamic {
|
||||||
pub tc_receiver: mpsc::Receiver<PacketAsVec>,
|
pub tc_receiver: mpsc::Receiver<PacketAsVec>,
|
||||||
pus_distributor: PusTcDistributor,
|
pus_distributor: PusTcDistributor<MpscTmAsVecSender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl TcSourceTaskDynamic {
|
impl TcSourceTaskDynamic {
|
||||||
pub fn new(tc_receiver: mpsc::Receiver<PacketAsVec>, pus_receiver: PusTcDistributor) -> Self {
|
pub fn new(
|
||||||
|
tc_receiver: mpsc::Receiver<PacketAsVec>,
|
||||||
|
pus_receiver: PusTcDistributor<MpscTmAsVecSender>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
pus_distributor: pus_receiver,
|
pus_distributor: pus_receiver,
|
||||||
@ -102,18 +105,3 @@ impl TcSourceTaskDynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum TcSourceTask {
|
|
||||||
Static(TcSourceTaskStatic),
|
|
||||||
Heap(TcSourceTaskDynamic),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TcSourceTask {
|
|
||||||
pub fn periodic_operation(&mut self) {
|
|
||||||
match self {
|
|
||||||
TcSourceTask::Static(task) => task.periodic_operation(),
|
|
||||||
TcSourceTask::Heap(task) => task.periodic_operation(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -89,7 +89,6 @@ pub struct TmSinkStatic {
|
|||||||
tm_server_tx: mpsc::SyncSender<PacketInPool>,
|
tm_server_tx: mpsc::SyncSender<PacketInPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl TmSinkStatic {
|
impl TmSinkStatic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_tm_store: SharedPacketPool,
|
shared_tm_store: SharedPacketPool,
|
||||||
@ -133,15 +132,14 @@ impl TmSinkStatic {
|
|||||||
pub struct TmSinkDynamic {
|
pub struct TmSinkDynamic {
|
||||||
common: TmFunnelCommon,
|
common: TmFunnelCommon,
|
||||||
tm_funnel_rx: mpsc::Receiver<PacketAsVec>,
|
tm_funnel_rx: mpsc::Receiver<PacketAsVec>,
|
||||||
tm_server_tx: mpsc::SyncSender<PacketAsVec>,
|
tm_server_tx: mpsc::Sender<PacketAsVec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl TmSinkDynamic {
|
impl TmSinkDynamic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sync_tm_tcp_source: SyncTcpTmSource,
|
sync_tm_tcp_source: SyncTcpTmSource,
|
||||||
tm_funnel_rx: mpsc::Receiver<PacketAsVec>,
|
tm_funnel_rx: mpsc::Receiver<PacketAsVec>,
|
||||||
tm_server_tx: mpsc::SyncSender<PacketAsVec>,
|
tm_server_tx: mpsc::Sender<PacketAsVec>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
||||||
@ -164,18 +162,3 @@ impl TmSinkDynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum TmSink {
|
|
||||||
Static(TmSinkStatic),
|
|
||||||
Heap(TmSinkDynamic),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TmSink {
|
|
||||||
pub fn operation(&mut self) {
|
|
||||||
match self {
|
|
||||||
TmSink::Static(static_sink) => static_sink.operation(),
|
|
||||||
TmSink::Heap(dynamic_sink) => dynamic_sink.operation(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -24,8 +24,8 @@ optional = true
|
|||||||
|
|
||||||
[dependencies.satrs-shared]
|
[dependencies.satrs-shared]
|
||||||
version = ">=0.1.3, <=0.2"
|
version = ">=0.1.3, <=0.2"
|
||||||
path = "../satrs-shared"
|
|
||||||
features = ["serde"]
|
features = ["serde"]
|
||||||
|
path = "../satrs-shared"
|
||||||
|
|
||||||
[dependencies.satrs-mib-codegen]
|
[dependencies.satrs-mib-codegen]
|
||||||
path = "codegen"
|
path = "codegen"
|
||||||
|
@ -28,8 +28,8 @@ features = ["full"]
|
|||||||
trybuild = { version = "1", features = ["diff"] }
|
trybuild = { version = "1", features = ["diff"] }
|
||||||
|
|
||||||
[dev-dependencies.satrs-shared]
|
[dev-dependencies.satrs-shared]
|
||||||
path = "../../satrs-shared"
|
|
||||||
version = ">=0.1.3, <=0.2"
|
version = ">=0.1.3, <=0.2"
|
||||||
|
path = "../../satrs-shared"
|
||||||
|
|
||||||
[dev-dependencies.satrs-mib]
|
[dev-dependencies.satrs-mib]
|
||||||
path = ".."
|
path = ".."
|
||||||
|
@ -14,10 +14,12 @@ fern = "0.7"
|
|||||||
strum = { version = "0.26", features = ["derive"] }
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
num_enum = "0.7"
|
num_enum = "0.7"
|
||||||
humantime = "2"
|
humantime = "2"
|
||||||
tai-time = { version = "0.3", features = ["serde"] }
|
|
||||||
|
|
||||||
[dependencies.nexosim]
|
[dependencies.asynchronix]
|
||||||
version = "0.3.1"
|
version = "0.2.2"
|
||||||
|
# git = "https://github.com/asynchronics/asynchronix.git"
|
||||||
|
# branch = "main"
|
||||||
|
features = ["serde"]
|
||||||
|
|
||||||
[dependencies.satrs]
|
[dependencies.satrs]
|
||||||
path = "../satrs"
|
path = "../satrs"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::{f32::consts::PI, sync::mpsc, time::Duration};
|
use std::{f32::consts::PI, sync::mpsc, time::Duration};
|
||||||
|
|
||||||
use nexosim::{
|
use asynchronix::{
|
||||||
model::{Context, Model},
|
model::{Model, Output},
|
||||||
ports::Output,
|
time::Scheduler,
|
||||||
};
|
};
|
||||||
use satrs::power::SwitchStateBinary;
|
use satrs::power::SwitchStateBinary;
|
||||||
use satrs_minisim::{
|
use satrs_minisim::{
|
||||||
@ -55,7 +55,7 @@ impl<ReplyProvider: MgmReplyProvider> MagnetometerModel<ReplyProvider> {
|
|||||||
self.switch_state = switch_state;
|
self.switch_state = switch_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_sensor_values(&mut self, _: (), scheduler: &mut Context<Self>) {
|
pub async fn send_sensor_values(&mut self, _: (), scheduler: &Scheduler<Self>) {
|
||||||
self.reply_sender
|
self.reply_sender
|
||||||
.send(ReplyProvider::create_mgm_reply(MgmReplyCommon {
|
.send(ReplyProvider::create_mgm_reply(MgmReplyCommon {
|
||||||
switch_state: self.switch_state,
|
switch_state: self.switch_state,
|
||||||
@ -114,11 +114,11 @@ impl MagnetorquerModel {
|
|||||||
pub async fn apply_torque(
|
pub async fn apply_torque(
|
||||||
&mut self,
|
&mut self,
|
||||||
duration_and_dipole: (Duration, MgtDipole),
|
duration_and_dipole: (Duration, MgtDipole),
|
||||||
cx: &mut Context<Self>,
|
scheduler: &Scheduler<Self>,
|
||||||
) {
|
) {
|
||||||
self.torque_dipole = duration_and_dipole.1;
|
self.torque_dipole = duration_and_dipole.1;
|
||||||
self.torquing = true;
|
self.torquing = true;
|
||||||
if cx
|
if scheduler
|
||||||
.schedule_event(duration_and_dipole.0, Self::clear_torque, ())
|
.schedule_event(duration_and_dipole.0, Self::clear_torque, ())
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
@ -138,11 +138,12 @@ impl MagnetorquerModel {
|
|||||||
self.generate_magnetic_field(()).await;
|
self.generate_magnetic_field(()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_housekeeping_data(&mut self, _: (), cx: &mut Context<Self>) {
|
pub async fn request_housekeeping_data(&mut self, _: (), scheduler: &Scheduler<Self>) {
|
||||||
if self.switch_state != SwitchStateBinary::On {
|
if self.switch_state != SwitchStateBinary::On {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cx.schedule_event(Duration::from_millis(15), Self::send_housekeeping_data, ())
|
scheduler
|
||||||
|
.schedule_event(Duration::from_millis(15), Self::send_housekeeping_data, ())
|
||||||
.expect("requesting housekeeping data failed")
|
.expect("requesting housekeeping data failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,11 +200,11 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply = sim_testbench.try_receive_next_reply();
|
let sim_reply = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply.is_some());
|
assert!(sim_reply.is_some());
|
||||||
let sim_reply = sim_reply.unwrap();
|
let sim_reply = sim_reply.unwrap();
|
||||||
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl);
|
assert_eq!(sim_reply.component(), SimComponent::MgmLis3Mdl);
|
||||||
let reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
|
let reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
|
||||||
.expect("failed to deserialize MGM sensor values");
|
.expect("failed to deserialize MGM sensor values");
|
||||||
assert_eq!(reply.common.switch_state, SwitchStateBinary::Off);
|
assert_eq!(reply.common.switch_state, SwitchStateBinary::Off);
|
||||||
@ -222,21 +223,21 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let mut sim_reply_res = sim_testbench.try_receive_next_reply();
|
let mut sim_reply_res = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply_res.is_some());
|
assert!(sim_reply_res.is_some());
|
||||||
let mut sim_reply = sim_reply_res.unwrap();
|
let mut sim_reply = sim_reply_res.unwrap();
|
||||||
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl);
|
assert_eq!(sim_reply.component(), SimComponent::MgmLis3Mdl);
|
||||||
let first_reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
|
let first_reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
|
||||||
.expect("failed to deserialize MGM sensor values");
|
.expect("failed to deserialize MGM sensor values");
|
||||||
sim_testbench.step_until(Duration::from_millis(50)).unwrap();
|
sim_testbench.step_by(Duration::from_millis(50));
|
||||||
|
|
||||||
request = SimRequest::new_with_epoch_time(MgmRequestLis3Mdl::RequestSensorData);
|
request = SimRequest::new_with_epoch_time(MgmRequestLis3Mdl::RequestSensorData);
|
||||||
sim_testbench
|
sim_testbench
|
||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
sim_reply_res = sim_testbench.try_receive_next_reply();
|
sim_reply_res = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply_res.is_some());
|
assert!(sim_reply_res.is_some());
|
||||||
sim_reply = sim_reply_res.unwrap();
|
sim_reply = sim_reply_res.unwrap();
|
||||||
@ -271,7 +272,7 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply_res.is_none());
|
assert!(sim_reply_res.is_none());
|
||||||
}
|
}
|
||||||
@ -286,7 +287,7 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply_res.is_some());
|
assert!(sim_reply_res.is_some());
|
||||||
let sim_reply = sim_reply_res.unwrap();
|
let sim_reply = sim_reply_res.unwrap();
|
||||||
@ -307,7 +308,7 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
let sim_reply_res = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply_res.is_some());
|
assert!(sim_reply_res.is_some());
|
||||||
let sim_reply = sim_reply_res.unwrap();
|
let sim_reply = sim_reply_res.unwrap();
|
||||||
@ -338,7 +339,7 @@ pub mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step_until(Duration::from_millis(5)).unwrap();
|
sim_testbench.step_by(Duration::from_millis(5));
|
||||||
|
|
||||||
check_mgt_hk(
|
check_mgt_hk(
|
||||||
&mut sim_testbench,
|
&mut sim_testbench,
|
||||||
@ -347,9 +348,7 @@ pub mod tests {
|
|||||||
torquing: true,
|
torquing: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
sim_testbench
|
sim_testbench.step_by(Duration::from_millis(100));
|
||||||
.step_until(Duration::from_millis(100))
|
|
||||||
.unwrap();
|
|
||||||
check_mgt_hk(
|
check_mgt_hk(
|
||||||
&mut sim_testbench,
|
&mut sim_testbench,
|
||||||
MgtHkSet {
|
MgtHkSet {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{sync::mpsc, time::Duration};
|
use std::{sync::mpsc, time::Duration};
|
||||||
|
|
||||||
use nexosim::{
|
use asynchronix::{
|
||||||
simulation::{Address, Scheduler, Simulation},
|
simulation::{Address, Simulation},
|
||||||
time::{Clock, MonotonicTime, SystemClock},
|
time::{Clock, MonotonicTime, SystemClock},
|
||||||
};
|
};
|
||||||
use satrs_minisim::{
|
use satrs_minisim::{
|
||||||
@ -23,55 +23,35 @@ const MGM_REQ_WIRETAPPING: bool = false;
|
|||||||
const PCDU_REQ_WIRETAPPING: bool = false;
|
const PCDU_REQ_WIRETAPPING: bool = false;
|
||||||
const MGT_REQ_WIRETAPPING: bool = false;
|
const MGT_REQ_WIRETAPPING: bool = false;
|
||||||
|
|
||||||
pub struct ModelAddrWrapper {
|
|
||||||
mgm_0_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
|
||||||
mgm_1_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
|
||||||
pcdu_addr: Address<PcduModel>,
|
|
||||||
mgt_addr: Address<MagnetorquerModel>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// The simulation controller processes requests and drives the simulation.
|
// The simulation controller processes requests and drives the simulation.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct SimController {
|
pub struct SimController {
|
||||||
pub sys_clock: SystemClock,
|
pub sys_clock: SystemClock,
|
||||||
pub request_receiver: mpsc::Receiver<SimRequest>,
|
pub request_receiver: mpsc::Receiver<SimRequest>,
|
||||||
pub reply_sender: mpsc::Sender<SimReply>,
|
pub reply_sender: mpsc::Sender<SimReply>,
|
||||||
pub simulation: Simulation,
|
pub simulation: Simulation,
|
||||||
pub scheduler: Scheduler,
|
pub mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
||||||
pub addr_wrapper: ModelAddrWrapper,
|
pub pcdu_addr: Address<PcduModel>,
|
||||||
|
pub mgt_addr: Address<MagnetorquerModel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModelAddrWrapper {
|
|
||||||
pub fn new(
|
|
||||||
mgm_0_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
|
||||||
mgm_1_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
|
||||||
pcdu_addr: Address<PcduModel>,
|
|
||||||
mgt_addr: Address<MagnetorquerModel>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
mgm_0_addr,
|
|
||||||
mgm_1_addr,
|
|
||||||
pcdu_addr,
|
|
||||||
mgt_addr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl SimController {
|
impl SimController {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sys_clock: SystemClock,
|
sys_clock: SystemClock,
|
||||||
request_receiver: mpsc::Receiver<SimRequest>,
|
request_receiver: mpsc::Receiver<SimRequest>,
|
||||||
reply_sender: mpsc::Sender<SimReply>,
|
reply_sender: mpsc::Sender<SimReply>,
|
||||||
simulation: Simulation,
|
simulation: Simulation,
|
||||||
scheduler: Scheduler,
|
mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
|
||||||
addr_wrapper: ModelAddrWrapper,
|
pcdu_addr: Address<PcduModel>,
|
||||||
|
mgt_addr: Address<MagnetorquerModel>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sys_clock,
|
sys_clock,
|
||||||
request_receiver,
|
request_receiver,
|
||||||
reply_sender,
|
reply_sender,
|
||||||
simulation,
|
simulation,
|
||||||
scheduler,
|
mgm_addr,
|
||||||
addr_wrapper,
|
pcdu_addr,
|
||||||
|
mgt_addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +62,7 @@ impl SimController {
|
|||||||
// Check for UDP requests every millisecond. Shift the simulator ahead here to prevent
|
// Check for UDP requests every millisecond. Shift the simulator ahead here to prevent
|
||||||
// replies lying in the past.
|
// replies lying in the past.
|
||||||
t += Duration::from_millis(udp_polling_interval_ms);
|
t += Duration::from_millis(udp_polling_interval_ms);
|
||||||
let _synch_status = self.sys_clock.synchronize(t);
|
self.sys_clock.synchronize(t);
|
||||||
self.handle_sim_requests(t_old);
|
self.handle_sim_requests(t_old);
|
||||||
self.simulation
|
self.simulation
|
||||||
.step_until(t)
|
.step_until(t)
|
||||||
@ -99,8 +79,7 @@ impl SimController {
|
|||||||
}
|
}
|
||||||
if let Err(e) = match request.component() {
|
if let Err(e) = match request.component() {
|
||||||
SimComponent::SimCtrl => self.handle_ctrl_request(&request),
|
SimComponent::SimCtrl => self.handle_ctrl_request(&request),
|
||||||
SimComponent::Mgm0Lis3Mdl => self.handle_mgm_request(0, &request),
|
SimComponent::MgmLis3Mdl => self.handle_mgm_request(&request),
|
||||||
SimComponent::Mgm1Lis3Mdl => self.handle_mgm_request(1, &request),
|
|
||||||
SimComponent::Mgt => self.handle_mgt_request(&request),
|
SimComponent::Mgt => self.handle_mgt_request(&request),
|
||||||
SimComponent::Pcdu => self.handle_pcdu_request(&request),
|
SimComponent::Pcdu => self.handle_pcdu_request(&request),
|
||||||
} {
|
} {
|
||||||
@ -132,26 +111,18 @@ impl SimController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mgm_request(
|
fn handle_mgm_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> {
|
||||||
&mut self,
|
|
||||||
mgm_idx: usize,
|
|
||||||
request: &SimRequest,
|
|
||||||
) -> Result<(), SimRequestError> {
|
|
||||||
let mgm_request = MgmRequestLis3Mdl::from_sim_message(request)?;
|
let mgm_request = MgmRequestLis3Mdl::from_sim_message(request)?;
|
||||||
if MGM_REQ_WIRETAPPING {
|
if MGM_REQ_WIRETAPPING {
|
||||||
log::info!("received MGM request: {:?}", mgm_request);
|
log::info!("received MGM request: {:?}", mgm_request);
|
||||||
}
|
}
|
||||||
match mgm_request {
|
match mgm_request {
|
||||||
MgmRequestLis3Mdl::RequestSensorData => {
|
MgmRequestLis3Mdl::RequestSensorData => {
|
||||||
let addr = match mgm_idx {
|
self.simulation.send_event(
|
||||||
0 => &self.addr_wrapper.mgm_0_addr,
|
MagnetometerModel::send_sensor_values,
|
||||||
1 => &self.addr_wrapper.mgm_1_addr,
|
(),
|
||||||
|
&self.mgm_addr,
|
||||||
_ => panic!("invalid mgm index"),
|
);
|
||||||
};
|
|
||||||
self.simulation
|
|
||||||
.process_event(MagnetometerModel::send_sensor_values, (), addr)
|
|
||||||
.expect("event execution error for mgm");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -165,21 +136,14 @@ impl SimController {
|
|||||||
match pcdu_request {
|
match pcdu_request {
|
||||||
PcduRequest::RequestSwitchInfo => {
|
PcduRequest::RequestSwitchInfo => {
|
||||||
self.simulation
|
self.simulation
|
||||||
.process_event(
|
.send_event(PcduModel::request_switch_info, (), &self.pcdu_addr);
|
||||||
PcduModel::request_switch_info,
|
|
||||||
(),
|
|
||||||
&self.addr_wrapper.pcdu_addr,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
PcduRequest::SwitchDevice { switch, state } => {
|
PcduRequest::SwitchDevice { switch, state } => {
|
||||||
self.simulation
|
self.simulation.send_event(
|
||||||
.process_event(
|
PcduModel::switch_device,
|
||||||
PcduModel::switch_device,
|
(switch, state),
|
||||||
(switch, state),
|
&self.pcdu_addr,
|
||||||
&self.addr_wrapper.pcdu_addr,
|
);
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -191,23 +155,17 @@ impl SimController {
|
|||||||
log::info!("received MGT request: {:?}", mgt_request);
|
log::info!("received MGT request: {:?}", mgt_request);
|
||||||
}
|
}
|
||||||
match mgt_request {
|
match mgt_request {
|
||||||
MgtRequest::ApplyTorque { duration, dipole } => self
|
MgtRequest::ApplyTorque { duration, dipole } => self.simulation.send_event(
|
||||||
.simulation
|
MagnetorquerModel::apply_torque,
|
||||||
.process_event(
|
(duration, dipole),
|
||||||
MagnetorquerModel::apply_torque,
|
&self.mgt_addr,
|
||||||
(duration, dipole),
|
),
|
||||||
&self.addr_wrapper.mgt_addr,
|
MgtRequest::RequestHk => self.simulation.send_event(
|
||||||
)
|
MagnetorquerModel::request_housekeeping_data,
|
||||||
.unwrap(),
|
(),
|
||||||
MgtRequest::RequestHk => self
|
&self.mgt_addr,
|
||||||
.simulation
|
),
|
||||||
.process_event(
|
}
|
||||||
MagnetorquerModel::request_housekeeping_data,
|
|
||||||
(),
|
|
||||||
&self.addr_wrapper.mgt_addr,
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
};
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +199,7 @@ mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending sim ctrl request failed");
|
.expect("sending sim ctrl request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply = sim_testbench.try_receive_next_reply();
|
let sim_reply = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply.is_some());
|
assert!(sim_reply.is_some());
|
||||||
let sim_reply = sim_reply.unwrap();
|
let sim_reply = sim_reply.unwrap();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::{sync::mpsc, time::Duration};
|
use std::{sync::mpsc, time::Duration};
|
||||||
|
|
||||||
use nexosim::{
|
use asynchronix::{
|
||||||
model::{Context, Model},
|
model::{Model, Output},
|
||||||
ports::Output,
|
time::Scheduler,
|
||||||
};
|
};
|
||||||
use satrs::power::SwitchStateBinary;
|
use satrs::power::SwitchStateBinary;
|
||||||
use satrs_minisim::{
|
use satrs_minisim::{
|
||||||
@ -14,8 +14,7 @@ pub const SWITCH_INFO_DELAY_MS: u64 = 10;
|
|||||||
|
|
||||||
pub struct PcduModel {
|
pub struct PcduModel {
|
||||||
pub switcher_map: SwitchMapBinaryWrapper,
|
pub switcher_map: SwitchMapBinaryWrapper,
|
||||||
pub mgm_0_switch: Output<SwitchStateBinary>,
|
pub mgm_switch: Output<SwitchStateBinary>,
|
||||||
pub mgm_1_switch: Output<SwitchStateBinary>,
|
|
||||||
pub mgt_switch: Output<SwitchStateBinary>,
|
pub mgt_switch: Output<SwitchStateBinary>,
|
||||||
pub reply_sender: mpsc::Sender<SimReply>,
|
pub reply_sender: mpsc::Sender<SimReply>,
|
||||||
}
|
}
|
||||||
@ -24,20 +23,20 @@ impl PcduModel {
|
|||||||
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self {
|
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
switcher_map: Default::default(),
|
switcher_map: Default::default(),
|
||||||
mgm_0_switch: Output::new(),
|
mgm_switch: Output::new(),
|
||||||
mgm_1_switch: Output::new(),
|
|
||||||
mgt_switch: Output::new(),
|
mgt_switch: Output::new(),
|
||||||
reply_sender,
|
reply_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_switch_info(&mut self, _: (), cx: &mut Context<Self>) {
|
pub async fn request_switch_info(&mut self, _: (), scheduler: &Scheduler<Self>) {
|
||||||
cx.schedule_event(
|
scheduler
|
||||||
Duration::from_millis(SWITCH_INFO_DELAY_MS),
|
.schedule_event(
|
||||||
Self::send_switch_info,
|
Duration::from_millis(SWITCH_INFO_DELAY_MS),
|
||||||
(),
|
Self::send_switch_info,
|
||||||
)
|
(),
|
||||||
.expect("requesting switch info failed");
|
)
|
||||||
|
.expect("requesting switch info failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_switch_info(&mut self) {
|
pub fn send_switch_info(&mut self) {
|
||||||
@ -57,7 +56,7 @@ impl PcduModel {
|
|||||||
*val = switch_and_target_state.1;
|
*val = switch_and_target_state.1;
|
||||||
match switch_and_target_state.0 {
|
match switch_and_target_state.0 {
|
||||||
PcduSwitch::Mgm => {
|
PcduSwitch::Mgm => {
|
||||||
self.mgm_0_switch.send(switch_and_target_state.1).await;
|
self.mgm_switch.send(switch_and_target_state.1).await;
|
||||||
}
|
}
|
||||||
PcduSwitch::Mgt => {
|
PcduSwitch::Mgt => {
|
||||||
self.mgt_switch.send(switch_and_target_state.1).await;
|
self.mgt_switch.send(switch_and_target_state.1).await;
|
||||||
@ -93,7 +92,7 @@ pub(crate) mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM switch request failed");
|
.expect("sending MGM switch request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -114,7 +113,7 @@ pub(crate) mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step().unwrap();
|
sim_testbench.step();
|
||||||
let sim_reply = sim_testbench.try_receive_next_reply();
|
let sim_reply = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply.is_some());
|
assert!(sim_reply.is_some());
|
||||||
let sim_reply = sim_reply.unwrap();
|
let sim_reply = sim_reply.unwrap();
|
||||||
@ -144,12 +143,12 @@ pub(crate) mod tests {
|
|||||||
.send_request(request)
|
.send_request(request)
|
||||||
.expect("sending MGM request failed");
|
.expect("sending MGM request failed");
|
||||||
sim_testbench.handle_sim_requests_time_agnostic();
|
sim_testbench.handle_sim_requests_time_agnostic();
|
||||||
sim_testbench.step_until(Duration::from_millis(1)).unwrap();
|
sim_testbench.step_by(Duration::from_millis(1));
|
||||||
|
|
||||||
let sim_reply = sim_testbench.try_receive_next_reply();
|
let sim_reply = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply.is_none());
|
assert!(sim_reply.is_none());
|
||||||
// Reply takes 20ms
|
// Reply takes 20ms
|
||||||
sim_testbench.step_until(Duration::from_millis(25)).unwrap();
|
sim_testbench.step_by(Duration::from_millis(25));
|
||||||
let sim_reply = sim_testbench.try_receive_next_reply();
|
let sim_reply = sim_testbench.try_receive_next_reply();
|
||||||
assert!(sim_reply.is_some());
|
assert!(sim_reply.is_some());
|
||||||
let sim_reply = sim_reply.unwrap();
|
let sim_reply = sim_reply.unwrap();
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use nexosim::time::MonotonicTime;
|
use asynchronix::time::MonotonicTime;
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||||
pub enum SimComponent {
|
pub enum SimComponent {
|
||||||
SimCtrl,
|
SimCtrl,
|
||||||
Mgm0Lis3Mdl,
|
MgmLis3Mdl,
|
||||||
Mgm1Lis3Mdl,
|
|
||||||
Mgt,
|
Mgt,
|
||||||
Pcdu,
|
Pcdu,
|
||||||
}
|
}
|
||||||
@ -278,7 +277,7 @@ pub mod acs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SerializableSimMsgPayload<SimRequest> for MgmRequestLis3Mdl {
|
impl SerializableSimMsgPayload<SimRequest> for MgmRequestLis3Mdl {
|
||||||
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl;
|
const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normally, small magnetometers generate their output as a signed 16 bit raw format or something
|
// Normally, small magnetometers generate their output as a signed 16 bit raw format or something
|
||||||
@ -369,7 +368,7 @@ pub mod acs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SerializableSimMsgPayload<SimReply> for MgmLis3MdlReply {
|
impl SerializableSimMsgPayload<SimReply> for MgmLis3MdlReply {
|
||||||
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl;
|
const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MgmReplyProvider for MgmLis3MdlReply {
|
impl MgmReplyProvider for MgmLis3MdlReply {
|
||||||
@ -419,7 +418,7 @@ pub mod acs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SerializableSimMsgPayload<SimReply> for MgtReply {
|
impl SerializableSimMsgPayload<SimReply> for MgtReply {
|
||||||
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl;
|
const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use acs::{MagnetometerModel, MagnetorquerModel};
|
use acs::{MagnetometerModel, MagnetorquerModel};
|
||||||
use controller::{ModelAddrWrapper, SimController};
|
use asynchronix::simulation::{Mailbox, SimInit};
|
||||||
|
use asynchronix::time::{MonotonicTime, SystemClock};
|
||||||
|
use controller::SimController;
|
||||||
use eps::PcduModel;
|
use eps::PcduModel;
|
||||||
use nexosim::simulation::{Mailbox, SimInit};
|
|
||||||
use nexosim::time::{MonotonicTime, SystemClock};
|
|
||||||
use satrs_minisim::udp::SIM_CTRL_PORT;
|
use satrs_minisim::udp::SIM_CTRL_PORT;
|
||||||
use satrs_minisim::{SimReply, SimRequest};
|
use satrs_minisim::{SimReply, SimRequest};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
@ -31,15 +31,11 @@ fn create_sim_controller(
|
|||||||
request_receiver: mpsc::Receiver<SimRequest>,
|
request_receiver: mpsc::Receiver<SimRequest>,
|
||||||
) -> SimController {
|
) -> SimController {
|
||||||
// Instantiate models and their mailboxes.
|
// Instantiate models and their mailboxes.
|
||||||
let mgm_0_model =
|
let mgm_model =
|
||||||
MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone());
|
|
||||||
let mgm_1_model =
|
|
||||||
MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone());
|
MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone());
|
||||||
|
|
||||||
let mgm_0_mailbox = Mailbox::new();
|
let mgm_mailbox = Mailbox::new();
|
||||||
let mgm_0_addr = mgm_0_mailbox.address();
|
let mgm_addr = mgm_mailbox.address();
|
||||||
let mgm_1_mailbox = Mailbox::new();
|
|
||||||
let mgm_1_addr = mgm_1_mailbox.address();
|
|
||||||
let pcdu_mailbox = Mailbox::new();
|
let pcdu_mailbox = Mailbox::new();
|
||||||
let pcdu_addr = pcdu_mailbox.address();
|
let pcdu_addr = pcdu_mailbox.address();
|
||||||
let mgt_mailbox = Mailbox::new();
|
let mgt_mailbox = Mailbox::new();
|
||||||
@ -47,11 +43,8 @@ fn create_sim_controller(
|
|||||||
|
|
||||||
let mut pcdu_model = PcduModel::new(reply_sender.clone());
|
let mut pcdu_model = PcduModel::new(reply_sender.clone());
|
||||||
pcdu_model
|
pcdu_model
|
||||||
.mgm_0_switch
|
.mgm_switch
|
||||||
.connect(MagnetometerModel::switch_device, &mgm_0_addr);
|
.connect(MagnetometerModel::switch_device, &mgm_addr);
|
||||||
pcdu_model
|
|
||||||
.mgm_1_switch
|
|
||||||
.connect(MagnetometerModel::switch_device, &mgm_1_addr);
|
|
||||||
|
|
||||||
let mut mgt_model = MagnetorquerModel::new(reply_sender.clone());
|
let mut mgt_model = MagnetorquerModel::new(reply_sender.clone());
|
||||||
// Input connections.
|
// Input connections.
|
||||||
@ -59,14 +52,9 @@ fn create_sim_controller(
|
|||||||
.mgt_switch
|
.mgt_switch
|
||||||
.connect(MagnetorquerModel::switch_device, &mgt_addr);
|
.connect(MagnetorquerModel::switch_device, &mgt_addr);
|
||||||
// Output connections.
|
// Output connections.
|
||||||
mgt_model.gen_magnetic_field.connect(
|
mgt_model
|
||||||
MagnetometerModel::apply_external_magnetic_field,
|
.gen_magnetic_field
|
||||||
&mgm_0_addr,
|
.connect(MagnetometerModel::apply_external_magnetic_field, &mgm_addr);
|
||||||
);
|
|
||||||
mgt_model.gen_magnetic_field.connect(
|
|
||||||
MagnetometerModel::apply_external_magnetic_field,
|
|
||||||
&mgm_1_addr,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Instantiate the simulator
|
// Instantiate the simulator
|
||||||
let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now());
|
let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now());
|
||||||
@ -75,21 +63,19 @@ fn create_sim_controller(
|
|||||||
} else {
|
} else {
|
||||||
SimInit::new()
|
SimInit::new()
|
||||||
};
|
};
|
||||||
let addrs = ModelAddrWrapper::new(mgm_0_addr, mgm_1_addr, pcdu_addr, mgt_addr);
|
let simulation = sim_init
|
||||||
let (simulation, scheduler) = sim_init
|
.add_model(mgm_model, mgm_mailbox)
|
||||||
.add_model(mgm_0_model, mgm_0_mailbox, "MGM 0 model")
|
.add_model(pcdu_model, pcdu_mailbox)
|
||||||
.add_model(mgm_1_model, mgm_1_mailbox, "MGM 1 model")
|
.add_model(mgt_model, mgt_mailbox)
|
||||||
.add_model(pcdu_model, pcdu_mailbox, "PCDU model")
|
.init(start_time);
|
||||||
.add_model(mgt_model, mgt_mailbox, "MGT model")
|
|
||||||
.init(start_time)
|
|
||||||
.unwrap();
|
|
||||||
SimController::new(
|
SimController::new(
|
||||||
sys_clock,
|
sys_clock,
|
||||||
request_receiver,
|
request_receiver,
|
||||||
reply_sender,
|
reply_sender,
|
||||||
simulation,
|
simulation,
|
||||||
scheduler,
|
mgm_addr,
|
||||||
addrs,
|
pcdu_addr,
|
||||||
|
mgt_addr,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
use std::sync::mpsc;
|
use std::{sync::mpsc, time::Duration};
|
||||||
|
|
||||||
use nexosim::{
|
use asynchronix::time::MonotonicTime;
|
||||||
simulation::ExecutionError,
|
|
||||||
time::{Deadline, MonotonicTime},
|
|
||||||
};
|
|
||||||
use satrs_minisim::{SimReply, SimRequest};
|
use satrs_minisim::{SimReply, SimRequest};
|
||||||
|
|
||||||
use crate::{controller::SimController, create_sim_controller, ThreadingModel};
|
use crate::{controller::SimController, create_sim_controller, ThreadingModel};
|
||||||
@ -38,8 +35,8 @@ impl SimTestbench {
|
|||||||
pub fn handle_sim_requests(&mut self, old_timestamp: MonotonicTime);
|
pub fn handle_sim_requests(&mut self, old_timestamp: MonotonicTime);
|
||||||
}
|
}
|
||||||
to self.sim_controller.simulation {
|
to self.sim_controller.simulation {
|
||||||
pub fn step(&mut self) -> Result<(), ExecutionError>;
|
pub fn step(&mut self);
|
||||||
pub fn step_until(&mut self, duration: impl Deadline) -> Result<(), ExecutionError>;
|
pub fn step_by(&mut self, duration: Duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use nexosim::time::MonotonicTime;
|
use asynchronix::time::MonotonicTime;
|
||||||
|
|
||||||
pub fn current_millis(time: MonotonicTime) -> u64 {
|
pub fn current_millis(time: MonotonicTime) -> u64 {
|
||||||
(time.as_secs() as u64 * 1000) + (time.subsec_nanos() as u64 / 1_000_000)
|
(time.as_secs() as u64 * 1000) + (time.subsec_nanos() as u64 / 1_000_000)
|
||||||
|
@ -8,14 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v0.2.2] 2025-05-10
|
|
||||||
|
|
||||||
- Bump to `spacepackests` v0.14
|
|
||||||
|
|
||||||
# [v0.2.1] 2024-11-15
|
|
||||||
|
|
||||||
Increased allowed spacepackets to v0.13
|
|
||||||
|
|
||||||
# [v0.2.0] 2024-11-04
|
# [v0.2.0] 2024-11-04
|
||||||
|
|
||||||
Semver bump, due to added features in v0.1.4
|
Semver bump, due to added features in v0.1.4
|
||||||
@ -45,6 +37,3 @@ Allow `spacepackets` range starting with v0.10 and v0.11.
|
|||||||
# [v0.1.0] 2024-02-12
|
# [v0.1.0] 2024-02-12
|
||||||
|
|
||||||
Initial release.
|
Initial release.
|
||||||
|
|
||||||
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.2...HEAD
|
|
||||||
[v0.2.2]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.1...satrs-shared-v0.2.2
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "satrs-shared"
|
name = "satrs-shared"
|
||||||
description = "Components shared by multiple sat-rs crates"
|
description = "Components shared by multiple sat-rs crates"
|
||||||
version = "0.2.2"
|
version = "0.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||||
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
|
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
|
||||||
@ -18,11 +18,11 @@ default-features = false
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.defmt]
|
[dependencies.defmt]
|
||||||
version = "1"
|
version = "0.3"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.spacepackets]
|
[dependencies.spacepackets]
|
||||||
version = "0.14"
|
version = ">0.9, <=0.13"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -8,10 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v0.3.0-alpha.0] 2025-02-18
|
|
||||||
|
|
||||||
`spacepackets` v0.13
|
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- Renamed `StaticPoolConfig::new` to `StaticPoolConfig::new_from_subpool_cfg_tuples`. The new
|
- Renamed `StaticPoolConfig::new` to `StaticPoolConfig::new_from_subpool_cfg_tuples`. The new
|
||||||
@ -23,18 +19,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
## Added
|
## Added
|
||||||
|
|
||||||
- `StaticHeaplessMemoryPool` which can be grown with user-provided static buffers.
|
- `StaticHeaplessMemoryPool` which can be grown with user-provided static buffers.
|
||||||
- Scheduling table for systems with a standard runtime
|
|
||||||
- Mode Tree Feature which allows building a network of mode components which can send mode
|
|
||||||
messages to each other.
|
|
||||||
- Added first helper features like the `SubsystemExecutionHelper` and the
|
|
||||||
`SubsystemCommandingHelper` which allows to build subsystem components. Subsystem components
|
|
||||||
are able to execute mode sequences and perform target keeping based on a declarative table
|
|
||||||
format.
|
|
||||||
- Added `DevManagerCommandingHelper` which performs some of the boilerplate logik required
|
|
||||||
by Assembly and Device Management components. This includes forwarding mode requests and
|
|
||||||
handling mode replies.
|
|
||||||
- First basic health module with `HealthState`s and the `HealthTableProvider` trait. These
|
|
||||||
components are important for any FDIR components which get added in the future.
|
|
||||||
|
|
||||||
# [v0.2.1] 2024-05-19
|
# [v0.2.1] 2024-05-19
|
||||||
|
|
||||||
|
102
satrs/Cargo.toml
102
satrs/Cargo.toml
@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "satrs"
|
name = "satrs"
|
||||||
version = "0.3.0-alpha.0"
|
version = "0.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.82.0"
|
rust-version = "1.71.1"
|
||||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||||
description = "A framework to build software for remote systems"
|
description = "A framework to build software for remote systems"
|
||||||
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
|
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
|
||||||
@ -13,33 +13,89 @@ keywords = ["no-std", "space", "aerospace"]
|
|||||||
categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-support", "embedded"]
|
categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-support", "embedded"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
satrs-shared = { version = ">=0.1.3, <=0.2", path = "../satrs-shared" }
|
|
||||||
delegate = ">0.7, <=0.13"
|
delegate = ">0.7, <=0.13"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
derive-new = ">=0.6, <=0.7"
|
derive-new = ">=0.6, <=0.7"
|
||||||
num_enum = { version = ">0.5, <=0.7", default-features = false }
|
smallvec = "1"
|
||||||
spacepackets = { version = "0.14", default-features = false }
|
crc = "3"
|
||||||
cobs = { version = "0.4", default-features = false, git = "https://github.com/jamesmunns/cobs.rs.git", branch = "main" }
|
|
||||||
thiserror = { version = "2", default-features = false }
|
|
||||||
|
|
||||||
hashbrown = { version = ">=0.14, <=0.15", optional = true }
|
[dependencies.satrs-shared]
|
||||||
static_cell = { version = "2", optional = true }
|
version = ">=0.1.3, <=0.2"
|
||||||
dyn-clone = { version = "1", optional = true }
|
path = "../satrs-shared"
|
||||||
heapless = { version = "0.8", optional = true }
|
|
||||||
downcast-rs = { version = "2", default-features = false, optional = true }
|
[dependencies.num_enum]
|
||||||
bus = { version = "2.2", optional = true }
|
version = ">0.5, <=0.7"
|
||||||
crossbeam-channel = { version = "0.5", default-features = false, optional = true }
|
default-features = false
|
||||||
serde = { version = "1", default-features = false, optional = true }
|
|
||||||
socket2 = { version = "0.5", features = ["all"], optional = true }
|
[dependencies.spacepackets]
|
||||||
mio = { version = "1", features = ["os-poll", "net"], optional = true }
|
version = "0.13"
|
||||||
defmt = { version = "0.3", optional = true }
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.cobs]
|
||||||
|
git = "https://github.com/robamu/cobs.rs.git"
|
||||||
|
version = "0.2.3"
|
||||||
|
branch = "all_features"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.num-traits]
|
||||||
|
version = "0.2"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.dyn-clone]
|
||||||
|
version = "1"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.hashbrown]
|
||||||
|
version = ">=0.14, <=0.15"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.heapless]
|
||||||
|
version = "0.8"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.downcast-rs]
|
||||||
|
version = "1.2"
|
||||||
|
default-features = false
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.bus]
|
||||||
|
version = "2.2"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.crossbeam-channel]
|
||||||
|
version= "0.5"
|
||||||
|
default-features = false
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.thiserror]
|
||||||
|
version = "2"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1"
|
||||||
|
default-features = false
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.socket2]
|
||||||
|
version = "0.5.4"
|
||||||
|
features = ["all"]
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.mio]
|
||||||
|
version = "1"
|
||||||
|
features = ["os-poll", "net"]
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.defmt]
|
||||||
|
version = "0.3"
|
||||||
|
optional = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = "1"
|
serde = "1"
|
||||||
zerocopy = "0.8"
|
zerocopy = "0.8"
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
rand = "0.9"
|
rand = "0.8"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
|
||||||
[dev-dependencies.postcard]
|
[dev-dependencies.postcard]
|
||||||
@ -51,6 +107,7 @@ std = [
|
|||||||
"downcast-rs/std",
|
"downcast-rs/std",
|
||||||
"alloc",
|
"alloc",
|
||||||
"bus",
|
"bus",
|
||||||
|
"postcard/use-std",
|
||||||
"crossbeam-channel/std",
|
"crossbeam-channel/std",
|
||||||
"serde/std",
|
"serde/std",
|
||||||
"spacepackets/std",
|
"spacepackets/std",
|
||||||
@ -68,15 +125,10 @@ alloc = [
|
|||||||
]
|
]
|
||||||
serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"]
|
serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"]
|
||||||
crossbeam = ["crossbeam-channel"]
|
crossbeam = ["crossbeam-channel"]
|
||||||
heapless = ["dep:heapless", "static_cell"]
|
heapless = ["dep:heapless"]
|
||||||
defmt = ["dep:defmt", "spacepackets/defmt"]
|
defmt = ["dep:defmt", "spacepackets/defmt"]
|
||||||
test_util = []
|
test_util = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--generate-link-to-definition"]
|
rustdoc-args = ["--generate-link-to-definition"]
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "event_test"
|
|
||||||
path = "tests/pus_events.rs"
|
|
||||||
required-features = ["test_util"]
|
|
||||||
|
@ -1,448 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
mode::{ModeAndSubmode, ModeReply, ModeRequest, ModeRequestSender},
|
|
||||||
mode_tree::{ModeStoreProvider, ModeStoreVec},
|
|
||||||
queue::{GenericSendError, GenericTargetedMessagingError},
|
|
||||||
request::{GenericMessage, RequestId},
|
|
||||||
ComponentId,
|
|
||||||
};
|
|
||||||
use core::fmt::Debug;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct ActiveModeCommandContext {
|
|
||||||
pub target_mode: ModeAndSubmode,
|
|
||||||
pub active_request_id: RequestId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
|
||||||
pub enum DevManagerHelperResult {
|
|
||||||
#[default]
|
|
||||||
Idle,
|
|
||||||
Busy,
|
|
||||||
ModeCommandingDone(ActiveModeCommandContext),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum DevManagerHelperError {
|
|
||||||
ChildNotInStore,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DevManagerUserHook: Debug {
|
|
||||||
fn send_mode_cmd_to_child(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
target_id: ComponentId,
|
|
||||||
mode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
children_mode_store: &mut ModeStoreVec,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError>;
|
|
||||||
|
|
||||||
fn send_mode_cmds_to_children(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
commanded_parent_mode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
children_mode_store: &mut ModeStoreVec,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct TransparentDevManagerHook {}
|
|
||||||
|
|
||||||
impl DevManagerUserHook for TransparentDevManagerHook {
|
|
||||||
fn send_mode_cmds_to_children(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
commanded_parent_mode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
children_mode_store: &mut ModeStoreVec,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
for child in children_mode_store {
|
|
||||||
mode_req_sender.send_mode_request(
|
|
||||||
request_id,
|
|
||||||
child.id(),
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode: commanded_parent_mode,
|
|
||||||
forced,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
child.awaiting_reply = true;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_mode_cmd_to_child(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
target_id: ComponentId,
|
|
||||||
mode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
children_mode_store: &mut ModeStoreVec,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
let mut_val = children_mode_store
|
|
||||||
.get_mut(target_id)
|
|
||||||
.ok_or(GenericSendError::TargetDoesNotExist(target_id))?;
|
|
||||||
mut_val.awaiting_reply = true;
|
|
||||||
mode_req_sender.send_mode_request(
|
|
||||||
request_id,
|
|
||||||
target_id,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode: mode,
|
|
||||||
forced,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum DevManagerCommandingState {
|
|
||||||
#[default]
|
|
||||||
Idle,
|
|
||||||
AwaitingReplies(ActiveModeCommandContext),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DevManagerCommandingState {
|
|
||||||
fn new_active_cmd(mode_and_submode: ModeAndSubmode, active_request_id: RequestId) -> Self {
|
|
||||||
DevManagerCommandingState::AwaitingReplies(ActiveModeCommandContext {
|
|
||||||
target_mode: mode_and_submode,
|
|
||||||
active_request_id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A generic helper for manager components which manage child components in a mode tree.
|
|
||||||
///
|
|
||||||
/// Mode commands are usually forwarded to all children components transparently.
|
|
||||||
/// For example, this could be used in an Assembly component which manages multiple redundant
|
|
||||||
/// child components. It can also be used inside a manager component which only manages one device.
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct DevManagerCommandingHelper<UserHook: DevManagerUserHook> {
|
|
||||||
/// The IDs, modes and reply awaition status of all children are tracked in this data
|
|
||||||
/// structure.
|
|
||||||
pub children_mode_store: ModeStoreVec,
|
|
||||||
pub user_hook: UserHook,
|
|
||||||
pub state: DevManagerCommandingState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<UserHook: DevManagerUserHook> DevManagerCommandingHelper<UserHook> {
|
|
||||||
pub fn new(user_hook: UserHook) -> Self {
|
|
||||||
Self {
|
|
||||||
children_mode_store: Default::default(),
|
|
||||||
user_hook,
|
|
||||||
state: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_mode_cmd_to_one_child(
|
|
||||||
&mut self,
|
|
||||||
request_id: RequestId,
|
|
||||||
target_id: ComponentId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
self.state = DevManagerCommandingState::new_active_cmd(mode_and_submode, request_id);
|
|
||||||
self.user_hook.send_mode_cmd_to_child(
|
|
||||||
request_id,
|
|
||||||
target_id,
|
|
||||||
mode_and_submode,
|
|
||||||
forced,
|
|
||||||
&mut self.children_mode_store,
|
|
||||||
mode_req_sender,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_mode_cmd_to_all_children(
|
|
||||||
&mut self,
|
|
||||||
request_id: RequestId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
self.state = DevManagerCommandingState::new_active_cmd(mode_and_submode, request_id);
|
|
||||||
self.user_hook.send_mode_cmds_to_children(
|
|
||||||
request_id,
|
|
||||||
mode_and_submode,
|
|
||||||
forced,
|
|
||||||
&mut self.children_mode_store,
|
|
||||||
mode_req_sender,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn target_mode(&self) -> Option<ModeAndSubmode> {
|
|
||||||
match self.state {
|
|
||||||
DevManagerCommandingState::Idle => None,
|
|
||||||
DevManagerCommandingState::AwaitingReplies(context) => Some(context.target_mode),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn state(&self) -> DevManagerCommandingState {
|
|
||||||
self.state
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_announce_mode_cmd_to_children(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
mode_req_sender: &impl ModeRequestSender,
|
|
||||||
recursive: bool,
|
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
|
||||||
let mut request = ModeRequest::AnnounceMode;
|
|
||||||
if recursive {
|
|
||||||
request = ModeRequest::AnnounceModeRecursive;
|
|
||||||
}
|
|
||||||
for child in self.children_mode_store.0.iter() {
|
|
||||||
mode_req_sender.send_mode_request(request_id, child.id(), request)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_mode_child(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
|
|
||||||
self.children_mode_store.add_component(target_id, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper method which counts the number of children which have a certain mode.
|
|
||||||
pub fn count_number_of_children_with_mode(&self, mode_and_submode: ModeAndSubmode) -> usize {
|
|
||||||
let mut children_in_target_mode = 0;
|
|
||||||
for child in &self.children_mode_store {
|
|
||||||
if child.mode_and_submode() == mode_and_submode {
|
|
||||||
children_in_target_mode += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
children_in_target_mode
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_mode_reply(
|
|
||||||
&mut self,
|
|
||||||
mode_reply: &GenericMessage<ModeReply>,
|
|
||||||
) -> Result<DevManagerHelperResult, DevManagerHelperError> {
|
|
||||||
let context = match self.state {
|
|
||||||
DevManagerCommandingState::Idle => return Ok(DevManagerHelperResult::Idle),
|
|
||||||
DevManagerCommandingState::AwaitingReplies(active_mode_command_context) => {
|
|
||||||
Some(active_mode_command_context)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !self
|
|
||||||
.children_mode_store
|
|
||||||
.has_component(mode_reply.sender_id())
|
|
||||||
{
|
|
||||||
return Err(DevManagerHelperError::ChildNotInStore);
|
|
||||||
}
|
|
||||||
let mut generic_mode_reply_handler = |mode_and_submode: Option<ModeAndSubmode>| {
|
|
||||||
// Tying the reply awaition to the request ID ensures that something like replies
|
|
||||||
// belonging to older requests do not interfere with the completion handling of
|
|
||||||
// the mode commanding. This is important for forced mode commands.
|
|
||||||
let mut handle_awaition = false;
|
|
||||||
if let DevManagerCommandingState::AwaitingReplies { .. } = self.state {
|
|
||||||
handle_awaition = true;
|
|
||||||
}
|
|
||||||
let still_awating_replies = self.children_mode_store.mode_reply_handler(
|
|
||||||
mode_reply.sender_id(),
|
|
||||||
mode_and_submode,
|
|
||||||
handle_awaition,
|
|
||||||
);
|
|
||||||
// It is okay to unwrap: If awaition should be handled, the returned value should
|
|
||||||
// always be some valid value.
|
|
||||||
if handle_awaition && !still_awating_replies.unwrap() {
|
|
||||||
self.state = DevManagerCommandingState::Idle;
|
|
||||||
return Ok(DevManagerHelperResult::ModeCommandingDone(context.unwrap()));
|
|
||||||
}
|
|
||||||
Ok(DevManagerHelperResult::Busy)
|
|
||||||
};
|
|
||||||
match mode_reply.message {
|
|
||||||
ModeReply::ModeInfo(mode_and_submode) | ModeReply::ModeReply(mode_and_submode) => {
|
|
||||||
generic_mode_reply_handler(Some(mode_and_submode))
|
|
||||||
}
|
|
||||||
ModeReply::CantReachMode(_result_u16) => generic_mode_reply_handler(None),
|
|
||||||
ModeReply::WrongMode {
|
|
||||||
expected: _,
|
|
||||||
reached,
|
|
||||||
} => generic_mode_reply_handler(Some(reached)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{
|
|
||||||
mode::{tests::ModeReqSenderMock, UNKNOWN_MODE},
|
|
||||||
request::MessageMetadata,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub enum ExampleId {
|
|
||||||
Id1 = 1,
|
|
||||||
Id2 = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExampleMode {
|
|
||||||
Mode1 = 1,
|
|
||||||
Mode2 = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_basic() {
|
|
||||||
let assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
|
||||||
assert_eq!(assy_helper.state(), DevManagerCommandingState::Idle);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mode_announce() {
|
|
||||||
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
|
||||||
assy_helper
|
|
||||||
.send_announce_mode_cmd_to_children(1, &mode_req_sender, false)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
|
||||||
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
|
||||||
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mode_announce_recursive() {
|
|
||||||
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
|
||||||
assy_helper
|
|
||||||
.send_announce_mode_cmd_to_children(1, &mode_req_sender, true)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
|
||||||
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
|
||||||
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mode_commanding_one_child() {
|
|
||||||
let mut dev_mgmt_helper =
|
|
||||||
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
|
||||||
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode1 as u32, 0);
|
|
||||||
dev_mgmt_helper
|
|
||||||
.send_mode_cmd_to_one_child(
|
|
||||||
1,
|
|
||||||
ExampleId::Id1 as u64,
|
|
||||||
expected_mode,
|
|
||||||
false,
|
|
||||||
&mode_req_sender,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 1);
|
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(
|
|
||||||
req.request,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode: expected_mode,
|
|
||||||
forced: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
matches!(
|
|
||||||
dev_mgmt_helper.state(),
|
|
||||||
DevManagerCommandingState::AwaitingReplies { .. }
|
|
||||||
);
|
|
||||||
if let DevManagerCommandingState::AwaitingReplies(ctx) = dev_mgmt_helper.state() {
|
|
||||||
assert_eq!(ctx.target_mode, expected_mode);
|
|
||||||
assert_eq!(ctx.active_request_id, 1);
|
|
||||||
}
|
|
||||||
let reply = GenericMessage::new(
|
|
||||||
MessageMetadata::new(1, ExampleId::Id1 as u64),
|
|
||||||
ModeReply::ModeReply(expected_mode),
|
|
||||||
);
|
|
||||||
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
|
||||||
target_mode,
|
|
||||||
active_request_id,
|
|
||||||
}) = dev_mgmt_helper.handle_mode_reply(&reply).unwrap()
|
|
||||||
{
|
|
||||||
assert_eq!(target_mode, expected_mode);
|
|
||||||
assert_eq!(active_request_id, 1);
|
|
||||||
}
|
|
||||||
matches!(dev_mgmt_helper.state(), DevManagerCommandingState::Idle);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mode_commanding_multi_child() {
|
|
||||||
let mut dev_mgmt_helper =
|
|
||||||
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
|
||||||
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode2 as u32, 0);
|
|
||||||
dev_mgmt_helper
|
|
||||||
.send_mode_cmd_to_all_children(1, expected_mode, false, &mode_req_sender)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(
|
|
||||||
req.request,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode: expected_mode,
|
|
||||||
forced: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
|
||||||
assert_eq!(req.request_id, 1);
|
|
||||||
assert_eq!(
|
|
||||||
req.request,
|
|
||||||
ModeRequest::SetMode {
|
|
||||||
mode_and_submode: expected_mode,
|
|
||||||
forced: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
matches!(
|
|
||||||
dev_mgmt_helper.state(),
|
|
||||||
DevManagerCommandingState::AwaitingReplies { .. }
|
|
||||||
);
|
|
||||||
if let DevManagerCommandingState::AwaitingReplies(ctx) = dev_mgmt_helper.state() {
|
|
||||||
assert_eq!(ctx.target_mode, expected_mode);
|
|
||||||
assert_eq!(ctx.active_request_id, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let reply = GenericMessage::new(
|
|
||||||
MessageMetadata::new(1, ExampleId::Id1 as u64),
|
|
||||||
ModeReply::ModeReply(expected_mode),
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
dev_mgmt_helper.handle_mode_reply(&reply).unwrap(),
|
|
||||||
DevManagerHelperResult::Busy
|
|
||||||
);
|
|
||||||
let reply = GenericMessage::new(
|
|
||||||
MessageMetadata::new(1, ExampleId::Id2 as u64),
|
|
||||||
ModeReply::ModeReply(expected_mode),
|
|
||||||
);
|
|
||||||
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
|
||||||
target_mode,
|
|
||||||
active_request_id,
|
|
||||||
}) = dev_mgmt_helper.handle_mode_reply(&reply).unwrap()
|
|
||||||
{
|
|
||||||
assert_eq!(target_mode, expected_mode);
|
|
||||||
assert_eq!(active_request_id, 1);
|
|
||||||
}
|
|
||||||
matches!(dev_mgmt_helper.state(), DevManagerCommandingState::Idle);
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,8 +24,8 @@ use cobs::{decode_in_place, encode, max_encoding_length};
|
|||||||
/// assert!(encode_packet_with_cobs(&INVERTED_PACKET, &mut encoding_buf, &mut current_idx));
|
/// assert!(encode_packet_with_cobs(&INVERTED_PACKET, &mut encoding_buf, &mut current_idx));
|
||||||
/// assert_eq!(encoding_buf[0], 0);
|
/// assert_eq!(encoding_buf[0], 0);
|
||||||
/// let dec_report = decode_in_place_report(&mut encoding_buf[1..]).expect("decoding failed");
|
/// let dec_report = decode_in_place_report(&mut encoding_buf[1..]).expect("decoding failed");
|
||||||
/// assert_eq!(encoding_buf[1 + dec_report.parsed_size()], 0);
|
/// assert_eq!(encoding_buf[1 + dec_report.src_used], 0);
|
||||||
/// assert_eq!(dec_report.frame_size(), 5);
|
/// assert_eq!(dec_report.dst_used, 5);
|
||||||
/// assert_eq!(current_idx, 16);
|
/// assert_eq!(current_idx, 16);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn encode_packet_with_cobs(
|
pub fn encode_packet_with_cobs(
|
||||||
|
@ -162,7 +162,7 @@ pub trait SenderMapProvider<
|
|||||||
/// * `ListenerMap`: [ListenerMapProvider] which maps listener keys to channel IDs.
|
/// * `ListenerMap`: [ListenerMapProvider] which maps listener keys to channel IDs.
|
||||||
/// * `EventSender`: [EventSendProvider] contained within the sender map which sends the events.
|
/// * `EventSender`: [EventSendProvider] contained within the sender map which sends the events.
|
||||||
/// * `Event`: The event type. This type must implement the [GenericEvent]. Currently only [EventU32]
|
/// * `Event`: The event type. This type must implement the [GenericEvent]. Currently only [EventU32]
|
||||||
/// and [EventU16] are supported.
|
/// and [EventU16] are supported.
|
||||||
/// * `ParamProvider`: Auxiliary data which is sent with the event to provide optional context
|
/// * `ParamProvider`: Auxiliary data which is sent with the event to provide optional context
|
||||||
/// information
|
/// information
|
||||||
pub struct EventManager<
|
pub struct EventManager<
|
||||||
|
@ -312,11 +312,11 @@ impl EventU32 {
|
|||||||
/// # Parameter
|
/// # Parameter
|
||||||
///
|
///
|
||||||
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
|
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
|
||||||
/// be stored inside the uppermost 2 bits of the raw event ID
|
/// be stored inside the uppermost 2 bits of the raw event ID
|
||||||
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
|
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
|
||||||
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
|
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
|
||||||
/// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
|
/// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
|
||||||
/// raw event ID
|
/// raw event ID
|
||||||
pub fn new_checked(
|
pub fn new_checked(
|
||||||
severity: Severity,
|
severity: Severity,
|
||||||
group_id: <Self as GenericEvent>::GroupId,
|
group_id: <Self as GenericEvent>::GroupId,
|
||||||
@ -486,11 +486,11 @@ impl EventU16 {
|
|||||||
/// # Parameter
|
/// # Parameter
|
||||||
///
|
///
|
||||||
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
|
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
|
||||||
/// be stored inside the uppermost 2 bits of the raw event ID
|
/// be stored inside the uppermost 2 bits of the raw event ID
|
||||||
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
|
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
|
||||||
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F.
|
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F.
|
||||||
/// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the
|
/// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the
|
||||||
/// raw event ID
|
/// raw event ID
|
||||||
pub fn new_checked(
|
pub fn new_checked(
|
||||||
severity: Severity,
|
severity: Severity,
|
||||||
group_id: <Self as GenericEvent>::GroupId,
|
group_id: <Self as GenericEvent>::GroupId,
|
||||||
|
@ -15,38 +15,31 @@ pub enum OpResult {
|
|||||||
TerminationRequested,
|
TerminationRequested,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ExecutionType {
|
pub enum ExecutionType {
|
||||||
Infinite,
|
Infinite,
|
||||||
Cycles(u32),
|
Cycles(u32),
|
||||||
OneShot,
|
OneShot,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Executable {
|
pub trait Executable: Send {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
|
fn exec_type(&self) -> ExecutionType;
|
||||||
fn task_name(&self) -> &'static str;
|
fn task_name(&self) -> &'static str;
|
||||||
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error>;
|
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExecutableWithType: Executable {
|
|
||||||
fn exec_type(&self) -> ExecutionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function allows executing one task which implements the [Executable] trait
|
/// This function allows executing one task which implements the [Executable] trait
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `executable`: Executable task
|
/// * `executable`: Executable task
|
||||||
/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks.
|
/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks.
|
||||||
/// If [None] is passed, no sleeping will be performed.
|
/// If [None] is passed, no sleeping will be performed.
|
||||||
/// * `op_code`: Operation code which is passed to the executable task
|
/// * `op_code`: Operation code which is passed to the executable task
|
||||||
/// [operation call][Executable::periodic_op]
|
/// [operation call][Executable::periodic_op]
|
||||||
/// * `termination`: Optional termination handler which can cancel threads with a broadcast
|
/// * `termination`: Optional termination handler which can cancel threads with a broadcast
|
||||||
pub fn exec_sched_single<
|
pub fn exec_sched_single<T: Executable<Error = E> + Send + 'static + ?Sized, E: Send + 'static>(
|
||||||
T: ExecutableWithType<Error = E> + Send + 'static + ?Sized,
|
|
||||||
E: Send + 'static,
|
|
||||||
>(
|
|
||||||
mut executable: Box<T>,
|
mut executable: Box<T>,
|
||||||
task_freq: Option<Duration>,
|
task_freq: Option<Duration>,
|
||||||
op_code: i32,
|
op_code: i32,
|
||||||
@ -95,10 +88,7 @@ pub fn exec_sched_single<
|
|||||||
/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks
|
/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks
|
||||||
/// * `op_code`: Operation code which is passed to the executable task [operation call][Executable::periodic_op]
|
/// * `op_code`: Operation code which is passed to the executable task [operation call][Executable::periodic_op]
|
||||||
/// * `termination`: Optional termination handler which can cancel threads with a broadcast
|
/// * `termination`: Optional termination handler which can cancel threads with a broadcast
|
||||||
pub fn exec_sched_multi<
|
pub fn exec_sched_multi<T: Executable<Error = E> + Send + 'static + ?Sized, E: Send + 'static>(
|
||||||
T: ExecutableWithType<Error = E> + Send + 'static + ?Sized,
|
|
||||||
E: Send + 'static,
|
|
||||||
>(
|
|
||||||
task_name: &'static str,
|
task_name: &'static str,
|
||||||
mut executable_vec: Vec<Box<T>>,
|
mut executable_vec: Vec<Box<T>>,
|
||||||
task_freq: Option<Duration>,
|
task_freq: Option<Duration>,
|
||||||
@ -152,10 +142,7 @@ pub fn exec_sched_multi<
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{exec_sched_multi, exec_sched_single, Executable, ExecutionType, OpResult};
|
||||||
exec_sched_multi, exec_sched_single, Executable, ExecutableWithType, ExecutionType,
|
|
||||||
OpResult,
|
|
||||||
};
|
|
||||||
use bus::Bus;
|
use bus::Bus;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@ -221,6 +208,10 @@ mod tests {
|
|||||||
impl Executable for OneShotTask {
|
impl Executable for OneShotTask {
|
||||||
type Error = ExampleError;
|
type Error = ExampleError;
|
||||||
|
|
||||||
|
fn exec_type(&self) -> ExecutionType {
|
||||||
|
ExecutionType::OneShot
|
||||||
|
}
|
||||||
|
|
||||||
fn task_name(&self) -> &'static str {
|
fn task_name(&self) -> &'static str {
|
||||||
ONE_SHOT_TASK_NAME
|
ONE_SHOT_TASK_NAME
|
||||||
}
|
}
|
||||||
@ -238,17 +229,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecutableWithType for OneShotTask {
|
|
||||||
fn exec_type(&self) -> ExecutionType {
|
|
||||||
ExecutionType::OneShot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CYCLE_TASK_NAME: &str = "Fixed Cycles Task";
|
const CYCLE_TASK_NAME: &str = "Fixed Cycles Task";
|
||||||
|
|
||||||
impl Executable for FixedCyclesTask {
|
impl Executable for FixedCyclesTask {
|
||||||
type Error = ExampleError;
|
type Error = ExampleError;
|
||||||
|
|
||||||
|
fn exec_type(&self) -> ExecutionType {
|
||||||
|
ExecutionType::Cycles(self.cycles)
|
||||||
|
}
|
||||||
|
|
||||||
fn task_name(&self) -> &'static str {
|
fn task_name(&self) -> &'static str {
|
||||||
CYCLE_TASK_NAME
|
CYCLE_TASK_NAME
|
||||||
}
|
}
|
||||||
@ -266,17 +255,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecutableWithType for FixedCyclesTask {
|
|
||||||
fn exec_type(&self) -> ExecutionType {
|
|
||||||
ExecutionType::Cycles(self.cycles)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const PERIODIC_TASK_NAME: &str = "Periodic Task";
|
const PERIODIC_TASK_NAME: &str = "Periodic Task";
|
||||||
|
|
||||||
impl Executable for PeriodicTask {
|
impl Executable for PeriodicTask {
|
||||||
type Error = ExampleError;
|
type Error = ExampleError;
|
||||||
|
|
||||||
|
fn exec_type(&self) -> ExecutionType {
|
||||||
|
ExecutionType::Infinite
|
||||||
|
}
|
||||||
|
|
||||||
fn task_name(&self) -> &'static str {
|
fn task_name(&self) -> &'static str {
|
||||||
PERIODIC_TASK_NAME
|
PERIODIC_TASK_NAME
|
||||||
}
|
}
|
||||||
@ -294,12 +281,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecutableWithType for PeriodicTask {
|
|
||||||
fn exec_type(&self) -> ExecutionType {
|
|
||||||
ExecutionType::Infinite
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_one_shot() {
|
fn test_simple_one_shot() {
|
||||||
let expected_op_code = 42;
|
let expected_op_code = 42;
|
||||||
@ -442,7 +423,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_eq!(cycled_task_0.task_name(), CYCLE_TASK_NAME);
|
assert_eq!(cycled_task_0.task_name(), CYCLE_TASK_NAME);
|
||||||
assert_eq!(one_shot_task.task_name(), ONE_SHOT_TASK_NAME);
|
assert_eq!(one_shot_task.task_name(), ONE_SHOT_TASK_NAME);
|
||||||
let task_vec: Vec<Box<dyn ExecutableWithType<Error = ExampleError> + Send>> =
|
let task_vec: Vec<Box<dyn Executable<Error = ExampleError>>> =
|
||||||
vec![one_shot_task, cycled_task_0, cycled_task_1];
|
vec![one_shot_task, cycled_task_0, cycled_task_1];
|
||||||
let jh = exec_sched_multi(
|
let jh = exec_sched_multi(
|
||||||
"multi-task-name",
|
"multi-task-name",
|
||||||
@ -512,7 +493,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_eq!(periodic_task_0.task_name(), PERIODIC_TASK_NAME);
|
assert_eq!(periodic_task_0.task_name(), PERIODIC_TASK_NAME);
|
||||||
assert_eq!(periodic_task_1.task_name(), PERIODIC_TASK_NAME);
|
assert_eq!(periodic_task_1.task_name(), PERIODIC_TASK_NAME);
|
||||||
let task_vec: Vec<Box<dyn ExecutableWithType<Error = ExampleError> + Send>> =
|
let task_vec: Vec<Box<dyn Executable<Error = ExampleError>>> =
|
||||||
vec![cycled_task, periodic_task_0, periodic_task_1];
|
vec![cycled_task, periodic_task_0, periodic_task_1];
|
||||||
let jh = exec_sched_multi(
|
let jh = exec_sched_multi(
|
||||||
"multi-task-name",
|
"multi-task-name",
|
||||||
|
@ -150,9 +150,9 @@ impl<
|
|||||||
///
|
///
|
||||||
/// * `cfg` - Configuration of the server.
|
/// * `cfg` - Configuration of the server.
|
||||||
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
||||||
/// then sent back to the client.
|
/// then sent back to the client.
|
||||||
/// * `tc_receiver` - Any received telecommands which were decoded successfully will be
|
/// * `tc_receiver` - Any received telecommands which were decoded successfully will be
|
||||||
/// forwarded to this TC receiver.
|
/// forwarded to this TC receiver.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
@ -377,13 +377,13 @@ mod tests {
|
|||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
|
let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
|
||||||
.expect("COBS decoding failed");
|
.expect("COBS decoding failed");
|
||||||
assert_eq!(dec_report.frame_size(), 5);
|
assert_eq!(dec_report.dst_used, 5);
|
||||||
// Skip first sentinel byte.
|
// Skip first sentinel byte.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&read_buf[current_idx..current_idx + INVERTED_PACKET.len()],
|
&read_buf[current_idx..current_idx + INVERTED_PACKET.len()],
|
||||||
&INVERTED_PACKET
|
&INVERTED_PACKET
|
||||||
);
|
);
|
||||||
current_idx += dec_report.parsed_size();
|
current_idx += dec_report.src_used;
|
||||||
// End sentinel.
|
// End sentinel.
|
||||||
assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte");
|
assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte");
|
||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
@ -393,13 +393,13 @@ mod tests {
|
|||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
|
dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
|
||||||
.expect("COBS decoding failed");
|
.expect("COBS decoding failed");
|
||||||
assert_eq!(dec_report.frame_size(), 5);
|
assert_eq!(dec_report.dst_used, 5);
|
||||||
// Skip first sentinel byte.
|
// Skip first sentinel byte.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&read_buf[current_idx..current_idx + SIMPLE_PACKET.len()],
|
&read_buf[current_idx..current_idx + SIMPLE_PACKET.len()],
|
||||||
&SIMPLE_PACKET
|
&SIMPLE_PACKET
|
||||||
);
|
);
|
||||||
current_idx += dec_report.parsed_size();
|
current_idx += dec_report.src_used;
|
||||||
// End sentinel.
|
// End sentinel.
|
||||||
assert_eq!(read_buf[current_idx], 0);
|
assert_eq!(read_buf[current_idx], 0);
|
||||||
break;
|
break;
|
||||||
|
@ -25,22 +25,22 @@ pub use crate::hal::std::tcp_spacepackets_server::{SpacepacketsTmSender, TcpSpac
|
|||||||
///
|
///
|
||||||
/// * `addr` - Address of the TCP server.
|
/// * `addr` - Address of the TCP server.
|
||||||
/// * `inner_loop_delay` - If a client connects for a longer period, but no TC is received or
|
/// * `inner_loop_delay` - If a client connects for a longer period, but no TC is received or
|
||||||
/// no TM needs to be sent, the TCP server will delay for the specified amount of time
|
/// no TM needs to be sent, the TCP server will delay for the specified amount of time
|
||||||
/// to reduce CPU load.
|
/// to reduce CPU load.
|
||||||
/// * `tm_buffer_size` - Size of the TM buffer used to read TM from the [PacketSource] and
|
/// * `tm_buffer_size` - Size of the TM buffer used to read TM from the [PacketSource] and
|
||||||
/// encoding of that data. This buffer should at large enough to hold the maximum expected
|
/// encoding of that data. This buffer should at large enough to hold the maximum expected
|
||||||
/// TM size read from the packet source.
|
/// TM size read from the packet source.
|
||||||
/// * `tc_buffer_size` - Size of the TC buffer used to read encoded telecommands sent from
|
/// * `tc_buffer_size` - Size of the TC buffer used to read encoded telecommands sent from
|
||||||
/// the client. It is recommended to make this buffer larger to allow reading multiple
|
/// the client. It is recommended to make this buffer larger to allow reading multiple
|
||||||
/// consecutive packets as well, for example by using common buffer sizes like 4096 or 8192
|
/// consecutive packets as well, for example by using common buffer sizes like 4096 or 8192
|
||||||
/// byte. The buffer should at the very least be large enough to hold the maximum expected
|
/// byte. The buffer should at the very least be large enough to hold the maximum expected
|
||||||
/// telecommand size.
|
/// telecommand size.
|
||||||
/// * `reuse_addr` - Can be used to set the `SO_REUSEADDR` option on the raw socket. This is
|
/// * `reuse_addr` - Can be used to set the `SO_REUSEADDR` option on the raw socket. This is
|
||||||
/// especially useful if the address and port are static for the server. Set to false by
|
/// especially useful if the address and port are static for the server. Set to false by
|
||||||
/// default.
|
/// default.
|
||||||
/// * `reuse_port` - Can be used to set the `SO_REUSEPORT` option on the raw socket. This is
|
/// * `reuse_port` - Can be used to set the `SO_REUSEPORT` option on the raw socket. This is
|
||||||
/// especially useful if the address and port are static for the server. Set to false by
|
/// especially useful if the address and port are static for the server. Set to false by
|
||||||
/// default.
|
/// default.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
pub id: ComponentId,
|
pub id: ComponentId,
|
||||||
@ -211,12 +211,12 @@ impl<
|
|||||||
///
|
///
|
||||||
/// * `cfg` - Configuration of the server.
|
/// * `cfg` - Configuration of the server.
|
||||||
/// * `tc_parser` - Parser which extracts telecommands from the raw bytestream received from
|
/// * `tc_parser` - Parser which extracts telecommands from the raw bytestream received from
|
||||||
/// the client.
|
/// the client.
|
||||||
/// * `tm_sender` - Sends back telemetry to the client using the specified TM source.
|
/// * `tm_sender` - Sends back telemetry to the client using the specified TM source.
|
||||||
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
||||||
/// then sent back to the client.
|
/// then sent back to the client.
|
||||||
/// * `tc_sender` - Any received telecommand which was decoded successfully will be forwarded
|
/// * `tc_sender` - Any received telecommand which was decoded successfully will be forwarded
|
||||||
/// using this TC sender.
|
/// using this TC sender.
|
||||||
/// * `stop_signal` - Can be used to stop the server even if a connection is ongoing.
|
/// * `stop_signal` - Can be used to stop the server even if a connection is ongoing.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
|
@ -120,15 +120,15 @@ impl<
|
|||||||
///
|
///
|
||||||
/// * `cfg` - Configuration of the server.
|
/// * `cfg` - Configuration of the server.
|
||||||
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
||||||
/// then sent back to the client.
|
/// then sent back to the client.
|
||||||
/// * `tc_sender` - Any received telecommands which were decoded successfully will be
|
/// * `tc_sender` - Any received telecommands which were decoded successfully will be
|
||||||
/// forwarded using this [PacketSenderRaw].
|
/// forwarded using this [PacketSenderRaw].
|
||||||
/// * `validator` - Used to determine the space packets relevant for further processing and
|
/// * `validator` - Used to determine the space packets relevant for further processing and
|
||||||
/// to detect broken space packets.
|
/// to detect broken space packets.
|
||||||
/// * `handled_connection_hook` - Called to notify the user about a succesfully handled
|
/// * `handled_connection_hook` - Called to notify the user about a succesfully handled
|
||||||
/// connection.
|
/// connection.
|
||||||
/// * `stop_signal` - Can be used to shut down the TCP server even for longer running
|
/// * `stop_signal` - Can be used to shut down the TCP server even for longer running
|
||||||
/// connections.
|
/// connections.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
use crate::ComponentId;
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum HealthState {
|
|
||||||
Healthy = 1,
|
|
||||||
Faulty = 2,
|
|
||||||
PermanentFaulty = 3,
|
|
||||||
ExternalControl = 4,
|
|
||||||
NeedsRecovery = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HealthTableProvider {
|
|
||||||
fn health(&self, id: ComponentId) -> Option<HealthState>;
|
|
||||||
fn set_health(&mut self, id: ComponentId, health: HealthState);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct HealthTableMapSync(
|
|
||||||
std::sync::Arc<std::sync::Mutex<hashbrown::HashMap<ComponentId, HealthState>>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl HealthTableMapSync {
|
|
||||||
pub fn new(health_table: hashbrown::HashMap<ComponentId, HealthState>) -> Self {
|
|
||||||
Self(std::sync::Arc::new(std::sync::Mutex::new(health_table)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl HealthTableProvider for HealthTableMapSync {
|
|
||||||
fn health(&self, id: ComponentId) -> Option<HealthState> {
|
|
||||||
self.0.lock().unwrap().get(&id).copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_health(&mut self, id: ComponentId, health: HealthState) {
|
|
||||||
self.0.lock().unwrap().insert(id, health);
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,34 +22,28 @@ extern crate downcast_rs;
|
|||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
pub mod action;
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub mod dev_mgmt;
|
|
||||||
pub mod encoding;
|
pub mod encoding;
|
||||||
pub mod event_man;
|
pub mod event_man;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod executable;
|
pub mod executable;
|
||||||
pub mod hal;
|
pub mod hal;
|
||||||
pub mod health;
|
|
||||||
pub mod hk;
|
|
||||||
pub mod mode;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod mode_tree;
|
pub mod mode_tree;
|
||||||
pub mod params;
|
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
pub mod power;
|
pub mod power;
|
||||||
pub mod pus;
|
pub mod pus;
|
||||||
pub mod queue;
|
pub mod queue;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
pub mod res_code;
|
pub mod res_code;
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub mod scheduling;
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub mod subsystem;
|
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod tmtc;
|
pub mod tmtc;
|
||||||
|
|
||||||
|
pub mod action;
|
||||||
|
pub mod hk;
|
||||||
|
pub mod mode;
|
||||||
|
pub mod params;
|
||||||
|
|
||||||
pub use spacepackets;
|
pub use spacepackets;
|
||||||
|
|
||||||
use spacepackets::PacketId;
|
use spacepackets::PacketId;
|
||||||
|
@ -11,10 +11,8 @@ pub use alloc_mod::*;
|
|||||||
pub use std_mod::*;
|
pub use std_mod::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
queue::GenericTargetedMessagingError,
|
||||||
request::{
|
request::{GenericMessage, MessageMetadata, MessageReceiver, MessageReceiverWithId, RequestId},
|
||||||
GenericMessage, MessageMetadata, MessageReceiverProvider, MessageReceiverWithId, RequestId,
|
|
||||||
},
|
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,11 +26,6 @@ pub struct ModeAndSubmode {
|
|||||||
submode: Submode,
|
submode: Submode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const INVALID_MODE_VAL: Mode = Mode::MAX;
|
|
||||||
pub const UNKNOWN_MODE_VAL: Mode = Mode::MAX - 1;
|
|
||||||
pub const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(INVALID_MODE_VAL, 0);
|
|
||||||
pub const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(UNKNOWN_MODE_VAL, 0);
|
|
||||||
|
|
||||||
impl ModeAndSubmode {
|
impl ModeAndSubmode {
|
||||||
pub const RAW_LEN: usize = size_of::<Mode>() + size_of::<Submode>();
|
pub const RAW_LEN: usize = size_of::<Mode>() + size_of::<Submode>();
|
||||||
|
|
||||||
@ -118,10 +111,7 @@ impl TargetedModeCommand {
|
|||||||
pub enum ModeRequest {
|
pub enum ModeRequest {
|
||||||
/// Mode information. Can be used to notify other components of changed modes.
|
/// Mode information. Can be used to notify other components of changed modes.
|
||||||
ModeInfo(ModeAndSubmode),
|
ModeInfo(ModeAndSubmode),
|
||||||
SetMode {
|
SetMode(ModeAndSubmode),
|
||||||
mode_and_submode: ModeAndSubmode,
|
|
||||||
forced: bool,
|
|
||||||
},
|
|
||||||
ReadMode,
|
ReadMode,
|
||||||
AnnounceMode,
|
AnnounceMode,
|
||||||
AnnounceModeRecursive,
|
AnnounceModeRecursive,
|
||||||
@ -137,8 +127,6 @@ pub struct TargetedModeRequest {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum ModeReply {
|
pub enum ModeReply {
|
||||||
/// Mode information. Can be used to notify other components of changed modes.
|
|
||||||
ModeInfo(ModeAndSubmode),
|
|
||||||
/// Reply to a mode request to confirm the commanded mode was reached.
|
/// Reply to a mode request to confirm the commanded mode was reached.
|
||||||
ModeReply(ModeAndSubmode),
|
ModeReply(ModeAndSubmode),
|
||||||
// Can not reach the commanded mode. Contains a reason as a [ResultU16].
|
// Can not reach the commanded mode. Contains a reason as a [ResultU16].
|
||||||
@ -159,33 +147,34 @@ pub trait ModeRequestSender {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericSendError>;
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModeRequestReceiver {
|
pub trait ModeRequestReceiver {
|
||||||
fn try_recv_mode_request(
|
fn try_recv_mode_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeRequest>>, GenericReceiveError>;
|
) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: MessageReceiverProvider<ModeRequest>> ModeRequestReceiver
|
impl<R: MessageReceiver<ModeRequest>> ModeRequestReceiver
|
||||||
for MessageReceiverWithId<ModeRequest, R>
|
for MessageReceiverWithId<ModeRequest, R>
|
||||||
{
|
{
|
||||||
fn try_recv_mode_request(
|
fn try_recv_mode_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeRequest>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, thiserror::Error)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ModeError {
|
pub enum ModeError {
|
||||||
#[error("Messaging send error: {0}")]
|
Messaging(GenericTargetedMessagingError),
|
||||||
Send(#[from] GenericSendError),
|
}
|
||||||
#[error("Messaging receive error: {0}")]
|
|
||||||
Receive(#[from] GenericReceiveError),
|
impl From<GenericTargetedMessagingError> for ModeError {
|
||||||
#[error("busy with other mode request")]
|
fn from(value: GenericTargetedMessagingError) -> Self {
|
||||||
Busy,
|
Self::Messaging(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModeProvider {
|
pub trait ModeProvider {
|
||||||
@ -207,7 +196,6 @@ pub trait ModeRequestHandler: ModeProvider {
|
|||||||
&mut self,
|
&mut self,
|
||||||
requestor: MessageMetadata,
|
requestor: MessageMetadata,
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
forced: bool,
|
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn announce_mode(&self, requestor_info: Option<MessageMetadata>, recursive: bool);
|
fn announce_mode(&self, requestor_info: Option<MessageMetadata>, recursive: bool);
|
||||||
@ -234,10 +222,9 @@ pub trait ModeRequestHandler: ModeProvider {
|
|||||||
request: GenericMessage<ModeRequest>,
|
request: GenericMessage<ModeRequest>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
match request.message {
|
match request.message {
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode(mode_and_submode) => {
|
||||||
mode_and_submode,
|
self.start_transition(request.requestor_info, mode_and_submode)
|
||||||
forced,
|
}
|
||||||
} => self.start_transition(request.requestor_info, mode_and_submode, forced),
|
|
||||||
ModeRequest::ReadMode => self.send_mode_reply(
|
ModeRequest::ReadMode => self.send_mode_reply(
|
||||||
request.requestor_info,
|
request.requestor_info,
|
||||||
ModeReply::ModeReply(self.mode_and_submode()),
|
ModeReply::ModeReply(self.mode_and_submode()),
|
||||||
@ -256,16 +243,15 @@ pub trait ModeRequestHandler: ModeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModeReplyReceiver {
|
pub trait ModeReplyReceiver {
|
||||||
fn try_recv_mode_reply(&self)
|
|
||||||
-> Result<Option<GenericMessage<ModeReply>>, GenericReceiveError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: MessageReceiverProvider<ModeReply>> ModeReplyReceiver
|
|
||||||
for MessageReceiverWithId<ModeReply, R>
|
|
||||||
{
|
|
||||||
fn try_recv_mode_reply(
|
fn try_recv_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeReply>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: MessageReceiver<ModeReply>> ModeReplyReceiver for MessageReceiverWithId<ModeReply, R> {
|
||||||
|
fn try_recv_mode_reply(
|
||||||
|
&self,
|
||||||
|
) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,28 +264,24 @@ pub trait ModeReplySender {
|
|||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
reply: ModeReply,
|
reply: ModeReply,
|
||||||
) -> Result<(), GenericSendError>;
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub mod alloc_mod {
|
pub mod alloc_mod {
|
||||||
use crate::{
|
use crate::request::{
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
MessageSender, MessageSenderAndReceiver, MessageSenderMap, RequestAndReplySenderAndReceiver,
|
||||||
request::{
|
|
||||||
MessageSenderAndReceiver, MessageSenderMap, MessageSenderProvider,
|
|
||||||
MessageSenderStoreProvider, RequestAndReplySenderAndReceiver,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<S: MessageSenderProvider<ModeReply>> MessageSenderMap<ModeReply, S> {
|
impl<S: MessageSender<ModeReply>> MessageSenderMap<ModeReply, S> {
|
||||||
pub fn send_mode_reply(
|
pub fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(requestor_info, target_id, request)
|
self.send_message(requestor_info, target_id, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,13 +290,8 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<FROM, S: MessageSender<ModeReply>, R: MessageReceiver<FROM>> ModeReplySender
|
||||||
From,
|
for MessageSenderAndReceiver<ModeReply, FROM, S, R>
|
||||||
Sender: MessageSenderProvider<ModeReply>,
|
|
||||||
Receiver: MessageReceiverProvider<From>,
|
|
||||||
SenderStore: MessageSenderStoreProvider<ModeReply, Sender>,
|
|
||||||
> ModeReplySender
|
|
||||||
for MessageSenderAndReceiver<ModeReply, From, Sender, Receiver, SenderStore>
|
|
||||||
{
|
{
|
||||||
fn local_channel_id(&self) -> ComponentId {
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
self.local_channel_id_generic()
|
self.local_channel_id_generic()
|
||||||
@ -324,8 +301,8 @@ pub mod alloc_mod {
|
|||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
request: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_store.send_message(
|
self.message_sender_map.send_mode_reply(
|
||||||
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
||||||
requestor_info.sender_id(),
|
requestor_info.sender_id(),
|
||||||
request,
|
request,
|
||||||
@ -333,67 +310,37 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeReply>> ModeReplyReceiver
|
||||||
To,
|
for MessageSenderAndReceiver<TO, ModeReply, S, R>
|
||||||
Sender: MessageSenderProvider<To>,
|
|
||||||
Receiver: MessageReceiverProvider<ModeReply>,
|
|
||||||
SenderStore: MessageSenderStoreProvider<To, Sender>,
|
|
||||||
> ModeReplyReceiver
|
|
||||||
for MessageSenderAndReceiver<To, ModeReply, Sender, Receiver, SenderStore>
|
|
||||||
{
|
{
|
||||||
fn try_recv_mode_reply(
|
fn try_recv_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeReply>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
|
||||||
self.message_receiver.try_recv_message()
|
self.message_receiver.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
Request,
|
REQUEST,
|
||||||
ReqSender: MessageSenderProvider<Request>,
|
S0: MessageSender<REQUEST>,
|
||||||
ReqReceiver: MessageReceiverProvider<Request>,
|
R0: MessageReceiver<ModeReply>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<Request, ReqSender>,
|
S1: MessageSender<ModeReply>,
|
||||||
Reply,
|
R1: MessageReceiver<REQUEST>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
> RequestAndReplySenderAndReceiver<REQUEST, ModeReply, S0, R0, S1, R1>
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
>
|
|
||||||
RequestAndReplySenderAndReceiver<
|
|
||||||
Request,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
Reply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
pub fn add_reply_target(&mut self, target_id: ComponentId, reply_sender: ReplySender) {
|
pub fn add_reply_target(&mut self, target_id: ComponentId, reply_sender: S1) {
|
||||||
self.reply_sender_store
|
self.reply_sender_map
|
||||||
.add_message_target(target_id, reply_sender)
|
.add_message_target(target_id, reply_sender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
Request,
|
REQUEST,
|
||||||
ReqSender: MessageSenderProvider<Request>,
|
S0: MessageSender<REQUEST>,
|
||||||
ReqReceiver: MessageReceiverProvider<Request>,
|
R0: MessageReceiver<ModeReply>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<Request, ReqSender>,
|
S1: MessageSender<ModeReply>,
|
||||||
ReplySender: MessageSenderProvider<ModeReply>,
|
R1: MessageReceiver<REQUEST>,
|
||||||
ReplyReceiver: MessageReceiverProvider<ModeReply>,
|
> ModeReplySender for RequestAndReplySenderAndReceiver<REQUEST, ModeReply, S0, R0, S1, R1>
|
||||||
ReplySenderStore: MessageSenderStoreProvider<ModeReply, ReplySender>,
|
|
||||||
> ModeReplySender
|
|
||||||
for RequestAndReplySenderAndReceiver<
|
|
||||||
Request,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
ModeReply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
fn local_channel_id(&self) -> ComponentId {
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
self.local_channel_id_generic()
|
self.local_channel_id_generic()
|
||||||
@ -402,56 +349,42 @@ pub mod alloc_mod {
|
|||||||
fn send_mode_reply(
|
fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
reply: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.reply_sender_store.send_message(
|
self.reply_sender_map.send_mode_reply(
|
||||||
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
||||||
requestor_info.sender_id(),
|
requestor_info.sender_id(),
|
||||||
reply,
|
request,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
Request,
|
REQUEST,
|
||||||
ReqSender: MessageSenderProvider<Request>,
|
S0: MessageSender<REQUEST>,
|
||||||
ReqReceiver: MessageReceiverProvider<Request>,
|
R0: MessageReceiver<ModeReply>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<Request, ReqSender>,
|
S1: MessageSender<ModeReply>,
|
||||||
ReplySender: MessageSenderProvider<ModeReply>,
|
R1: MessageReceiver<REQUEST>,
|
||||||
ReplyReceiver: MessageReceiverProvider<ModeReply>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<ModeReply, ReplySender>,
|
|
||||||
> ModeReplyReceiver
|
> ModeReplyReceiver
|
||||||
for RequestAndReplySenderAndReceiver<
|
for RequestAndReplySenderAndReceiver<REQUEST, ModeReply, S0, R0, S1, R1>
|
||||||
Request,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
ModeReply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
fn try_recv_mode_reply(
|
fn try_recv_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeReply>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
|
||||||
self.reply_receiver.try_recv_message()
|
self.reply_receiver.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper type definition for a mode handler which can handle mode requests.
|
/// Helper type definition for a mode handler which can handle mode requests.
|
||||||
pub type ModeRequestHandlerInterface<Sender, Receiver, ReplySenderStore> =
|
pub type ModeRequestHandlerInterface<S, R> =
|
||||||
MessageSenderAndReceiver<ModeReply, ModeRequest, Sender, Receiver, ReplySenderStore>;
|
MessageSenderAndReceiver<ModeReply, ModeRequest, S, R>;
|
||||||
|
|
||||||
impl<
|
impl<S: MessageSender<ModeReply>, R: MessageReceiver<ModeRequest>>
|
||||||
Sender: MessageSenderProvider<ModeReply>,
|
ModeRequestHandlerInterface<S, R>
|
||||||
Receiver: MessageReceiverProvider<ModeRequest>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<ModeReply, Sender>,
|
|
||||||
> ModeRequestHandlerInterface<Sender, Receiver, ReplySenderStore>
|
|
||||||
{
|
{
|
||||||
pub fn try_recv_mode_request(
|
pub fn try_recv_mode_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeRequest>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +392,7 @@ pub mod alloc_mod {
|
|||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
reply: ModeReply,
|
reply: ModeReply,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(
|
self.send_message(
|
||||||
requestor_info.request_id(),
|
requestor_info.request_id(),
|
||||||
requestor_info.sender_id(),
|
requestor_info.sender_id(),
|
||||||
@ -470,18 +403,12 @@ pub mod alloc_mod {
|
|||||||
|
|
||||||
/// Helper type defintion for a mode handler object which can send mode requests and receive
|
/// Helper type defintion for a mode handler object which can send mode requests and receive
|
||||||
/// mode replies.
|
/// mode replies.
|
||||||
pub type ModeRequestorInterface<Sender, Receiver, RequestSenderStore> =
|
pub type ModeRequestorInterface<S, R> = MessageSenderAndReceiver<ModeRequest, ModeReply, S, R>;
|
||||||
MessageSenderAndReceiver<ModeRequest, ModeReply, Sender, Receiver, RequestSenderStore>;
|
|
||||||
|
|
||||||
impl<
|
impl<S: MessageSender<ModeRequest>, R: MessageReceiver<ModeReply>> ModeRequestorInterface<S, R> {
|
||||||
Sender: MessageSenderProvider<ModeRequest>,
|
|
||||||
Receiver: MessageReceiverProvider<ModeReply>,
|
|
||||||
RequestSenderStore: MessageSenderStoreProvider<ModeRequest, Sender>,
|
|
||||||
> ModeRequestorInterface<Sender, Receiver, RequestSenderStore>
|
|
||||||
{
|
|
||||||
pub fn try_recv_mode_reply(
|
pub fn try_recv_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeReply>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,38 +417,23 @@ pub mod alloc_mod {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
reply: ModeRequest,
|
reply: ModeRequest,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, target_id, reply)
|
self.send_message(request_id, target_id, reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper type defintion for a mode handler object which can both send mode requests and
|
/// Helper type defintion for a mode handler object which can both send mode requests and
|
||||||
/// process mode requests.
|
/// process mode requests.
|
||||||
pub type ModeInterface<
|
pub type ModeInterface<S0, R0, S1, R1> =
|
||||||
ReqSender,
|
RequestAndReplySenderAndReceiver<ModeRequest, ModeReply, S0, R0, S1, R1>;
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
> = RequestAndReplySenderAndReceiver<
|
|
||||||
ModeRequest,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
ModeReply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<S: MessageSenderProvider<ModeRequest>> MessageSenderMap<ModeRequest, S> {
|
impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
|
||||||
pub fn send_mode_request(
|
pub fn send_mode_request(
|
||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(requestor_info, target_id, request)
|
self.send_message(requestor_info, target_id, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,28 +442,35 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
/*
|
||||||
To,
|
impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
|
||||||
Sender: MessageSenderProvider<To>,
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
Receiver: MessageReceiverProvider<ModeRequest>,
|
self.local_channel_id
|
||||||
SenderStore: MessageSenderStoreProvider<To, Sender>,
|
}
|
||||||
> ModeRequestReceiver
|
|
||||||
for MessageSenderAndReceiver<To, ModeRequest, Sender, Receiver, SenderStore>
|
fn send_mode_request(
|
||||||
|
&self,
|
||||||
|
request_id: RequestId,
|
||||||
|
target_id: ComponentId,
|
||||||
|
request: ModeRequest,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
|
self.send_message(request_id, target_id, request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
|
||||||
|
for MessageSenderAndReceiver<TO, ModeRequest, S, R>
|
||||||
{
|
{
|
||||||
fn try_recv_mode_request(
|
fn try_recv_mode_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeRequest>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
|
||||||
self.message_receiver.try_recv_message()
|
self.message_receiver.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<FROM, S: MessageSender<ModeRequest>, R: MessageReceiver<FROM>> ModeRequestSender
|
||||||
From,
|
for MessageSenderAndReceiver<ModeRequest, FROM, S, R>
|
||||||
Sender: MessageSenderProvider<ModeRequest>,
|
|
||||||
Receiver: MessageReceiverProvider<From>,
|
|
||||||
SenderStore: MessageSenderStoreProvider<ModeRequest, Sender>,
|
|
||||||
> ModeRequestSender
|
|
||||||
for MessageSenderAndReceiver<ModeRequest, From, Sender, Receiver, SenderStore>
|
|
||||||
{
|
{
|
||||||
fn local_channel_id(&self) -> ComponentId {
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
self.local_channel_id_generic()
|
self.local_channel_id_generic()
|
||||||
@ -562,8 +481,8 @@ pub mod alloc_mod {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_store.send_message(
|
self.message_sender_map.send_mode_request(
|
||||||
MessageMetadata::new(request_id, self.local_channel_id()),
|
MessageMetadata::new(request_id, self.local_channel_id()),
|
||||||
target_id,
|
target_id,
|
||||||
request,
|
request,
|
||||||
@ -572,50 +491,27 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
ReqSender: MessageSenderProvider<ModeRequest>,
|
REPLY,
|
||||||
ReqReceiver: MessageReceiverProvider<ModeRequest>,
|
S0: MessageSender<ModeRequest>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<ModeRequest, ReqSender>,
|
R0: MessageReceiver<REPLY>,
|
||||||
Reply,
|
S1: MessageSender<REPLY>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
R1: MessageReceiver<ModeRequest>,
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
> RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
>
|
|
||||||
RequestAndReplySenderAndReceiver<
|
|
||||||
ModeRequest,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
Reply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: ReqSender) {
|
pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S0) {
|
||||||
self.request_sender_store
|
self.request_sender_map
|
||||||
.add_message_target(target_id, request_sender)
|
.add_message_target(target_id, request_sender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
ReqSender: MessageSenderProvider<ModeRequest>,
|
REPLY,
|
||||||
ReqReceiver: MessageReceiverProvider<ModeRequest>,
|
S0: MessageSender<ModeRequest>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<ModeRequest, ReqSender>,
|
R0: MessageReceiver<REPLY>,
|
||||||
Reply,
|
S1: MessageSender<REPLY>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
R1: MessageReceiver<ModeRequest>,
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
> ModeRequestSender
|
> ModeRequestSender
|
||||||
for RequestAndReplySenderAndReceiver<
|
for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
|
||||||
ModeRequest,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
Reply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
fn local_channel_id(&self) -> ComponentId {
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
self.local_channel_id_generic()
|
self.local_channel_id_generic()
|
||||||
@ -626,8 +522,8 @@ pub mod alloc_mod {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.request_sender_store.send_message(
|
self.request_sender_map.send_mode_request(
|
||||||
MessageMetadata::new(request_id, self.local_channel_id()),
|
MessageMetadata::new(request_id, self.local_channel_id()),
|
||||||
target_id,
|
target_id,
|
||||||
request,
|
request,
|
||||||
@ -636,28 +532,17 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
ReqSender: MessageSenderProvider<ModeRequest>,
|
REPLY,
|
||||||
ReqReceiver: MessageReceiverProvider<ModeRequest>,
|
S0: MessageSender<ModeRequest>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<ModeRequest, ReqSender>,
|
R0: MessageReceiver<REPLY>,
|
||||||
Reply,
|
S1: MessageSender<REPLY>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
R1: MessageReceiver<ModeRequest>,
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
> ModeRequestReceiver
|
> ModeRequestReceiver
|
||||||
for RequestAndReplySenderAndReceiver<
|
for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
|
||||||
ModeRequest,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
Reply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
fn try_recv_mode_request(
|
fn try_recv_mode_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ModeRequest>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
|
||||||
self.request_receiver.try_recv_message()
|
self.request_receiver.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,97 +552,39 @@ pub mod alloc_mod {
|
|||||||
pub mod std_mod {
|
pub mod std_mod {
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use crate::request::{MessageSenderList, OneMessageSender};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface<
|
pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface<
|
||||||
mpsc::Sender<GenericMessage<ModeReply>>,
|
mpsc::Sender<GenericMessage<ModeReply>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
MessageSenderList<ModeReply, mpsc::Sender<GenericMessage<ModeReply>>>,
|
|
||||||
>;
|
>;
|
||||||
pub type ModeRequestHandlerMpscBounded = ModeRequestHandlerInterface<
|
pub type ModeRequestHandlerMpscBounded = ModeRequestHandlerInterface<
|
||||||
mpsc::SyncSender<GenericMessage<ModeReply>>,
|
mpsc::SyncSender<GenericMessage<ModeReply>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
MessageSenderList<ModeReply, mpsc::SyncSender<GenericMessage<ModeReply>>>,
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub type ModeRequestorOneChildMpsc = ModeRequestorInterface<
|
pub type ModeRequestorMpsc = ModeRequestorInterface<
|
||||||
mpsc::Sender<GenericMessage<ModeRequest>>,
|
mpsc::Sender<GenericMessage<ModeRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
OneMessageSender<ModeRequest, mpsc::Sender<GenericMessage<ModeRequest>>>,
|
|
||||||
>;
|
>;
|
||||||
pub type ModeRequestorOneChildBoundedMpsc = ModeRequestorInterface<
|
pub type ModeRequestorBoundedMpsc = ModeRequestorInterface<
|
||||||
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
OneMessageSender<ModeRequest, mpsc::SyncSender<GenericMessage<ModeRequest>>>,
|
|
||||||
>;
|
|
||||||
pub type ModeRequestorChildListMpsc = ModeRequestorInterface<
|
|
||||||
mpsc::Sender<GenericMessage<ModeRequest>>,
|
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
|
||||||
MessageSenderList<ModeRequest, mpsc::Sender<GenericMessage<ModeRequest>>>,
|
|
||||||
>;
|
|
||||||
pub type ModeRequestorChildListBoundedMpsc = ModeRequestorInterface<
|
|
||||||
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
|
||||||
MessageSenderList<ModeRequest, mpsc::SyncSender<GenericMessage<ModeRequest>>>,
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub type ModeRequestorAndHandlerMpsc = ModeInterface<
|
pub type ModeRequestorAndHandlerMpsc = ModeInterface<
|
||||||
mpsc::Sender<GenericMessage<ModeRequest>>,
|
mpsc::Sender<GenericMessage<ModeRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
|
||||||
MessageSenderList<ModeRequest, mpsc::Sender<GenericMessage<ModeRequest>>>,
|
|
||||||
mpsc::Sender<GenericMessage<ModeReply>>,
|
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
MessageSenderList<ModeReply, mpsc::Sender<GenericMessage<ModeReply>>>,
|
mpsc::Sender<GenericMessage<ModeReply>>,
|
||||||
|
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
>;
|
>;
|
||||||
pub type ModeRequestorAndHandlerMpscBounded = ModeInterface<
|
pub type ModeRequestorAndHandlerMpscBounded = ModeInterface<
|
||||||
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
|
||||||
MessageSenderList<ModeRequest, mpsc::SyncSender<GenericMessage<ModeRequest>>>,
|
|
||||||
mpsc::SyncSender<GenericMessage<ModeReply>>,
|
|
||||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
MessageSenderList<ModeReply, mpsc::SyncSender<GenericMessage<ModeReply>>>,
|
mpsc::SyncSender<GenericMessage<ModeReply>>,
|
||||||
|
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod tests {
|
mod tests {}
|
||||||
use core::cell::RefCell;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
use crate::{request::RequestId, ComponentId};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub struct ModeReqWrapper {
|
|
||||||
pub request_id: RequestId,
|
|
||||||
pub target_id: ComponentId,
|
|
||||||
pub request: ModeRequest,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ModeReqSenderMock {
|
|
||||||
pub requests: RefCell<VecDeque<ModeReqWrapper>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeRequestSender for ModeReqSenderMock {
|
|
||||||
fn local_channel_id(&self) -> crate::ComponentId {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_mode_request(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
target_id: ComponentId,
|
|
||||||
request: ModeRequest,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
self.requests.borrow_mut().push_back(ModeReqWrapper {
|
|
||||||
request_id,
|
|
||||||
target_id,
|
|
||||||
request,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,57 +2,10 @@ use alloc::vec::Vec;
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode},
|
mode::{Mode, ModeAndSubmode, Submode},
|
||||||
request::MessageSenderProvider,
|
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub use alloc_mod::*;
|
|
||||||
|
|
||||||
/// Common trait for node modes which can have mode parents or mode children.
|
|
||||||
pub trait ModeNode {
|
|
||||||
fn id(&self) -> ComponentId;
|
|
||||||
}
|
|
||||||
/// Trait which denotes that an object is a parent in a mode tree.
|
|
||||||
///
|
|
||||||
/// A mode parent is capable of sending mode requests to child objects and has a unique component
|
|
||||||
/// ID.
|
|
||||||
pub trait ModeParent: ModeNode {
|
|
||||||
type Sender: MessageSenderProvider<ModeRequest>;
|
|
||||||
|
|
||||||
fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait which denotes that an object is a child in a mode tree.
|
|
||||||
///
|
|
||||||
/// A child is capable of sending mode replies to parent objects and has a unique component ID.
|
|
||||||
pub trait ModeChild: ModeNode {
|
|
||||||
type Sender: MessageSenderProvider<ModeReply>;
|
|
||||||
|
|
||||||
fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Utility method which connects a mode tree parent object to a child object by calling
|
|
||||||
/// [ModeParent::add_mode_child] on the [parent][ModeParent] and calling
|
|
||||||
/// [ModeChild::add_mode_parent] on the [child][ModeChild].
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `parent` - The parent object which implements [ModeParent].
|
|
||||||
/// * `request_sender` - Sender object to send mode requests to the child.
|
|
||||||
/// * `child` - The child object which implements [ModeChild].
|
|
||||||
/// * `reply_sender` - Sender object to send mode replies to the parent.
|
|
||||||
pub fn connect_mode_nodes<ReqSender, ReplySender>(
|
|
||||||
parent: &mut impl ModeParent<Sender = ReqSender>,
|
|
||||||
request_sender: ReqSender,
|
|
||||||
child: &mut impl ModeChild<Sender = ReplySender>,
|
|
||||||
reply_sender: ReplySender,
|
|
||||||
) {
|
|
||||||
parent.add_mode_child(child.id(), request_sender);
|
|
||||||
child.add_mode_parent(parent.id(), reply_sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum TableEntryType {
|
pub enum TableEntryType {
|
||||||
/// Target table containing information of the expected children modes for given mode.
|
/// Target table containing information of the expected children modes for given mode.
|
||||||
@ -62,553 +15,23 @@ pub enum TableEntryType {
|
|||||||
Sequence,
|
Sequence,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common fields required for both target and sequence table entries.
|
pub struct ModeTableEntry {
|
||||||
///
|
|
||||||
/// The most important parameters here are the target ID which this entry belongs to, and the mode
|
|
||||||
/// and submode the entry either will be commanded to for sequence table entries or which will be
|
|
||||||
/// monitored for target table entries.
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct ModeTableEntryCommon {
|
|
||||||
/// Name of respective table entry.
|
/// Name of respective table entry.
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
/// Target component ID.
|
/// Target channel ID.
|
||||||
pub target_id: ComponentId,
|
pub channel_id: ComponentId,
|
||||||
/// Has a different meaning depending on whether this is a sequence table or a target table.
|
|
||||||
///
|
|
||||||
/// - For sequence tables, this denotes the mode which will be commanded
|
|
||||||
/// - For target tables, this is the mode which the target children should have and which
|
|
||||||
/// might be monitored depending on configuration.
|
|
||||||
pub mode_submode: ModeAndSubmode,
|
pub mode_submode: ModeAndSubmode,
|
||||||
/// This mask allows to specify multiple allowed submodes for a given mode.
|
|
||||||
pub allowed_submode_mask: Option<Submode>,
|
pub allowed_submode_mask: Option<Submode>,
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeTableEntryCommon {
|
|
||||||
pub fn set_allowed_submode_mask(&mut self, mask: Submode) {
|
|
||||||
self.allowed_submode_mask = Some(mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allowed_submode_mask(&self) -> Option<Submode> {
|
|
||||||
self.allowed_submode_mask
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An entry for the target tables.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TargetTableEntry {
|
|
||||||
pub common: ModeTableEntryCommon,
|
|
||||||
pub monitor_state: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TargetTableEntry {
|
|
||||||
pub fn new(
|
|
||||||
name: &'static str,
|
|
||||||
target_id: ComponentId,
|
|
||||||
mode_submode: ModeAndSubmode,
|
|
||||||
allowed_submode_mask: Option<Submode>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
common: ModeTableEntryCommon {
|
|
||||||
name,
|
|
||||||
target_id,
|
|
||||||
mode_submode,
|
|
||||||
allowed_submode_mask,
|
|
||||||
},
|
|
||||||
monitor_state: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_with_precise_submode(
|
|
||||||
name: &'static str,
|
|
||||||
target_id: ComponentId,
|
|
||||||
mode_submode: ModeAndSubmode,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
common: ModeTableEntryCommon {
|
|
||||||
name,
|
|
||||||
target_id,
|
|
||||||
mode_submode,
|
|
||||||
allowed_submode_mask: None,
|
|
||||||
},
|
|
||||||
monitor_state: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate::delegate! {
|
|
||||||
to self.common {
|
|
||||||
pub fn set_allowed_submode_mask(&mut self, mask: Submode);
|
|
||||||
pub fn allowed_submode_mask(&self) -> Option<Submode>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An entry for the sequence tables.
|
|
||||||
///
|
|
||||||
/// The [Self::check_success] field specifies that a mode sequence executor should check that the
|
|
||||||
/// target mode was actually reached before executing the next sequence.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SequenceTableEntry {
|
|
||||||
pub common: ModeTableEntryCommon,
|
|
||||||
pub check_success: bool,
|
pub check_success: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequenceTableEntry {
|
pub struct ModeTableMapValue {
|
||||||
pub fn new(
|
/// Name for a given mode table entry.
|
||||||
name: &'static str,
|
pub name: &'static str,
|
||||||
target_id: ComponentId,
|
pub entries: Vec<ModeTableEntry>,
|
||||||
mode_submode: ModeAndSubmode,
|
|
||||||
check_success: bool,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
common: ModeTableEntryCommon {
|
|
||||||
name,
|
|
||||||
target_id,
|
|
||||||
mode_submode,
|
|
||||||
allowed_submode_mask: None,
|
|
||||||
},
|
|
||||||
check_success,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate::delegate! {
|
|
||||||
to self.common {
|
|
||||||
pub fn set_allowed_submode_mask(&mut self, mask: Submode);
|
|
||||||
pub fn allowed_submode_mask(&self) -> Option<Submode>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
pub type ModeTable = HashMap<Mode, ModeTableMapValue>;
|
||||||
#[error("target {0} not in mode store")]
|
|
||||||
pub struct TargetNotInModeStoreError(pub ComponentId);
|
|
||||||
|
|
||||||
/// Mode store value type.
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct ModeStoreValue {
|
|
||||||
/// ID of the mode component.
|
|
||||||
id: ComponentId,
|
|
||||||
/// Current mode and submode of the component.
|
|
||||||
pub mode_and_submode: ModeAndSubmode,
|
|
||||||
/// State information to track whether a reply should be awaited for the mode component.
|
|
||||||
pub awaiting_reply: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeStoreValue {
|
|
||||||
pub fn new(id: ComponentId, mode_and_submode: ModeAndSubmode) -> Self {
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
mode_and_submode,
|
|
||||||
awaiting_reply: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> ComponentId {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mode_and_submode(&self) -> ModeAndSubmode {
|
|
||||||
self.mode_and_submode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ModeStoreProvider {
|
|
||||||
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode);
|
|
||||||
|
|
||||||
fn has_component(&self, target_id: ComponentId) -> bool;
|
|
||||||
|
|
||||||
fn get(&self, target_id: ComponentId) -> Option<&ModeStoreValue>;
|
|
||||||
|
|
||||||
fn get_mut(&mut self, target_id: ComponentId) -> Option<&mut ModeStoreValue>;
|
|
||||||
|
|
||||||
/// Generic handler for mode replies received from child components.
|
|
||||||
///
|
|
||||||
/// Implementation should clear the awaition flag if the `handle_reply_awaition` argument is
|
|
||||||
/// true and returns whether any children are still awaiting replies. If the flag is not set
|
|
||||||
fn mode_reply_handler_with_reply_awaition(
|
|
||||||
&mut self,
|
|
||||||
sender_id: ComponentId,
|
|
||||||
reported_mode_and_submode: Option<ModeAndSubmode>,
|
|
||||||
) -> bool {
|
|
||||||
self.mode_reply_handler(sender_id, reported_mode_and_submode, true)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode_reply_handler_without_reply_awaition(
|
|
||||||
&mut self,
|
|
||||||
sender_id: ComponentId,
|
|
||||||
reported_mode_and_submode: Option<ModeAndSubmode>,
|
|
||||||
) {
|
|
||||||
self.mode_reply_handler(sender_id, reported_mode_and_submode, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode_reply_handler(
|
|
||||||
&mut self,
|
|
||||||
sender_id: ComponentId,
|
|
||||||
reported_mode_and_submode: Option<ModeAndSubmode>,
|
|
||||||
with_reply_awaition: bool,
|
|
||||||
) -> Option<bool>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub mod alloc_mod {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TargetTablesMapValue {
|
|
||||||
/// Name for a given mode table entry.
|
|
||||||
pub name: &'static str,
|
|
||||||
/// Optional fallback mode if the target mode can not be kept.
|
|
||||||
pub fallback_mode: Option<Mode>,
|
|
||||||
/// These are the rows of the a target table.
|
|
||||||
pub entries: Vec<TargetTableEntry>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TargetTablesMapValue {
|
|
||||||
pub fn new(name: &'static str, fallback_mode: Option<Mode>) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
fallback_mode,
|
|
||||||
entries: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_entry(&mut self, entry: TargetTableEntry) {
|
|
||||||
self.entries.push(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// One sequence of a [SequenceTablesMapValue] in a [SequenceModeTables].
|
|
||||||
///
|
|
||||||
/// It contains all mode requests which need to be executed for a sequence step and it also
|
|
||||||
/// associates a [Self::name] with the sequence.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SequenceTableMapTable {
|
|
||||||
/// Name for a given mode sequence.
|
|
||||||
pub name: &'static str,
|
|
||||||
/// These are the rows of the a sequence table.
|
|
||||||
pub entries: Vec<SequenceTableEntry>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SequenceTableMapTable {
|
|
||||||
pub fn new(name: &'static str) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
entries: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_entry(&mut self, entry: SequenceTableEntry) {
|
|
||||||
self.entries.push(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A sequence table entry.
|
|
||||||
///
|
|
||||||
/// This is simply a list of [SequenceTableMapTable]s which also associates a [Self::name]
|
|
||||||
/// with the sequence. The order of sub-tables in the list also specifies the execution order
|
|
||||||
/// in the mode sequence.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SequenceTablesMapValue {
|
|
||||||
/// Name for a given mode sequence.
|
|
||||||
pub name: &'static str,
|
|
||||||
/// Each sequence can consists of multiple sequences that are executed consecutively.
|
|
||||||
pub entries: Vec<SequenceTableMapTable>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SequenceTablesMapValue {
|
|
||||||
pub fn new(name: &'static str) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
entries: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_sequence_table(&mut self, entry: SequenceTableMapTable) {
|
|
||||||
self.entries.push(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct TargetModeTables(pub HashMap<Mode, TargetTablesMapValue>);
|
|
||||||
|
|
||||||
impl TargetModeTables {
|
|
||||||
pub fn name(&self, mode: Mode) -> Option<&'static str> {
|
|
||||||
self.0.get(&mode).map(|value| value.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SequenceModeTables {
|
|
||||||
pub fn name(&self, mode: Mode) -> Option<&'static str> {
|
|
||||||
self.0.get(&mode).map(|value| value.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_of_sequence(&self, mode: Mode, seq_idx: usize) -> Option<&'static str> {
|
|
||||||
self.0
|
|
||||||
.get(&mode)
|
|
||||||
.map(|value| value.entries.get(seq_idx).map(|v| v.name))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is the core data structure used to store mode sequence tables.
|
|
||||||
///
|
|
||||||
/// A mode sequence table specifies which commands have to be sent in which order
|
|
||||||
/// to reach a certain [Mode]. Therefore, it simply maps a [Mode] to a [SequenceTablesMapValue].
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct SequenceModeTables(pub HashMap<Mode, SequenceTablesMapValue>);
|
|
||||||
|
|
||||||
/// Mode store which tracks the [mode information][ModeStoreValue] inside a [Vec]
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct ModeStoreVec(pub alloc::vec::Vec<ModeStoreValue>);
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a ModeStoreVec {
|
|
||||||
type Item = &'a ModeStoreValue;
|
|
||||||
type IntoIter = std::slice::Iter<'a, ModeStoreValue>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a mut ModeStoreVec {
|
|
||||||
type Item = &'a mut ModeStoreValue;
|
|
||||||
type IntoIter = std::slice::IterMut<'a, ModeStoreValue>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.iter_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mode store which tracks the mode information inside a [hashbrown::HashMap]
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeStoreValue>);
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a ModeStoreMap {
|
|
||||||
type Item = (&'a ComponentId, &'a ModeStoreValue);
|
|
||||||
type IntoIter = hashbrown::hash_map::Iter<'a, ComponentId, ModeStoreValue>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeStoreProvider for ModeStoreVec {
|
|
||||||
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
|
|
||||||
self.0.push(ModeStoreValue::new(target_id, mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_component(&self, target_id: ComponentId) -> bool {
|
|
||||||
self.0.iter().any(|val| val.id == target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self, target_id: ComponentId) -> Option<&ModeStoreValue> {
|
|
||||||
self.0.iter().find(|val| val.id == target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mut(&mut self, target_id: ComponentId) -> Option<&mut ModeStoreValue> {
|
|
||||||
self.0.iter_mut().find(|val| val.id == target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode_reply_handler(
|
|
||||||
&mut self,
|
|
||||||
sender_id: ComponentId,
|
|
||||||
reported_mode_and_submode: Option<ModeAndSubmode>,
|
|
||||||
handle_reply_awaition: bool,
|
|
||||||
) -> Option<bool> {
|
|
||||||
let mut still_awating_replies = None;
|
|
||||||
if handle_reply_awaition {
|
|
||||||
still_awating_replies = Some(false);
|
|
||||||
}
|
|
||||||
self.0.iter_mut().for_each(|val| {
|
|
||||||
if val.id() == sender_id {
|
|
||||||
if let Some(mode_and_submode) = reported_mode_and_submode {
|
|
||||||
val.mode_and_submode = mode_and_submode;
|
|
||||||
}
|
|
||||||
if handle_reply_awaition {
|
|
||||||
val.awaiting_reply = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if handle_reply_awaition && val.awaiting_reply {
|
|
||||||
still_awating_replies = Some(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
still_awating_replies
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeStoreProvider for ModeStoreMap {
|
|
||||||
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
|
|
||||||
self.0
|
|
||||||
.insert(target_id, ModeStoreValue::new(target_id, mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_component(&self, target_id: ComponentId) -> bool {
|
|
||||||
self.0.contains_key(&target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self, target_id: ComponentId) -> Option<&ModeStoreValue> {
|
|
||||||
self.0.get(&target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mut(&mut self, target_id: ComponentId) -> Option<&mut ModeStoreValue> {
|
|
||||||
self.0.get_mut(&target_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode_reply_handler(
|
|
||||||
&mut self,
|
|
||||||
sender_id: ComponentId,
|
|
||||||
reported_mode_and_submode: Option<ModeAndSubmode>,
|
|
||||||
handle_reply_awaition: bool,
|
|
||||||
) -> Option<bool> {
|
|
||||||
let mut still_awating_replies = None;
|
|
||||||
if handle_reply_awaition {
|
|
||||||
still_awating_replies = Some(false);
|
|
||||||
}
|
|
||||||
for val in self.0.values_mut() {
|
|
||||||
if val.id() == sender_id {
|
|
||||||
if let Some(mode_and_submode) = reported_mode_and_submode {
|
|
||||||
val.mode_and_submode = mode_and_submode;
|
|
||||||
}
|
|
||||||
if handle_reply_awaition {
|
|
||||||
val.awaiting_reply = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if handle_reply_awaition && val.awaiting_reply {
|
|
||||||
still_awating_replies = Some(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
still_awating_replies
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {}
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn generic_test(mode_store: &mut impl ModeStoreProvider) {
|
|
||||||
mode_store.add_component(1, ModeAndSubmode::new(0, 0));
|
|
||||||
mode_store.add_component(2, ModeAndSubmode::new(1, 0));
|
|
||||||
assert!(mode_store.has_component(1));
|
|
||||||
assert!(mode_store.has_component(2));
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(1).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(0, 0)
|
|
||||||
);
|
|
||||||
assert!(!mode_store.get(1).unwrap().awaiting_reply);
|
|
||||||
assert!(!mode_store.get(2).unwrap().awaiting_reply);
|
|
||||||
assert_eq!(mode_store.get(1).unwrap().id, 1);
|
|
||||||
assert_eq!(mode_store.get(2).unwrap().id, 2);
|
|
||||||
assert!(mode_store.get(3).is_none());
|
|
||||||
assert!(mode_store.get_mut(3).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_reply_handling_with_reply_awaition(mode_store: &mut impl ModeStoreProvider) {
|
|
||||||
mode_store.add_component(1, ModeAndSubmode::new(0, 0));
|
|
||||||
mode_store.add_component(2, ModeAndSubmode::new(1, 0));
|
|
||||||
mode_store.get_mut(1).unwrap().awaiting_reply = true;
|
|
||||||
mode_store.get_mut(2).unwrap().awaiting_reply = true;
|
|
||||||
let mut reply_awation_pending =
|
|
||||||
mode_store.mode_reply_handler_with_reply_awaition(1, Some(ModeAndSubmode::new(2, 0)));
|
|
||||||
assert!(reply_awation_pending);
|
|
||||||
reply_awation_pending = mode_store.mode_reply_handler_with_reply_awaition(2, None);
|
|
||||||
assert!(!reply_awation_pending);
|
|
||||||
assert!(!mode_store.get(1).unwrap().awaiting_reply);
|
|
||||||
assert!(!mode_store.get(2).unwrap().awaiting_reply);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(1).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(2, 0)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(2).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(1, 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_reply_handling_test_no_reply_awaition(mode_store: &mut impl ModeStoreProvider) {
|
|
||||||
mode_store.add_component(1, ModeAndSubmode::new(0, 0));
|
|
||||||
mode_store.add_component(2, ModeAndSubmode::new(1, 0));
|
|
||||||
mode_store.get_mut(1).unwrap().awaiting_reply = true;
|
|
||||||
mode_store.get_mut(2).unwrap().awaiting_reply = true;
|
|
||||||
mode_store.mode_reply_handler_without_reply_awaition(1, Some(ModeAndSubmode::new(2, 0)));
|
|
||||||
mode_store.mode_reply_handler_without_reply_awaition(2, None);
|
|
||||||
assert!(mode_store.get(1).unwrap().awaiting_reply);
|
|
||||||
assert!(mode_store.get(2).unwrap().awaiting_reply);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(1).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(2, 0)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(2).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(1, 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_reply_handling_with_reply_awaition_2(mode_store: &mut impl ModeStoreProvider) {
|
|
||||||
mode_store.add_component(1, ModeAndSubmode::new(0, 0));
|
|
||||||
mode_store.add_component(2, ModeAndSubmode::new(1, 0));
|
|
||||||
mode_store.get_mut(1).unwrap().awaiting_reply = true;
|
|
||||||
mode_store.get_mut(2).unwrap().awaiting_reply = true;
|
|
||||||
let mut reply_awation_pending =
|
|
||||||
mode_store.mode_reply_handler(1, Some(ModeAndSubmode::new(2, 0)), true);
|
|
||||||
assert!(reply_awation_pending.unwrap());
|
|
||||||
reply_awation_pending = mode_store.mode_reply_handler(2, None, true);
|
|
||||||
assert!(!reply_awation_pending.unwrap());
|
|
||||||
assert!(!mode_store.get(1).unwrap().awaiting_reply);
|
|
||||||
assert!(!mode_store.get(2).unwrap().awaiting_reply);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(1).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(2, 0)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
mode_store.get(2).unwrap().mode_and_submode(),
|
|
||||||
ModeAndSubmode::new(1, 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_vec_mode_store() {
|
|
||||||
let mut mode_store = ModeStoreVec::default();
|
|
||||||
generic_test(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_map_mode_store() {
|
|
||||||
let mut mode_store = ModeStoreMap::default();
|
|
||||||
generic_test(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_vec_with_reply_awaition() {
|
|
||||||
let mut mode_store = ModeStoreVec::default();
|
|
||||||
generic_reply_handling_with_reply_awaition(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_vec_with_reply_awaition_2() {
|
|
||||||
let mut mode_store = ModeStoreVec::default();
|
|
||||||
generic_reply_handling_with_reply_awaition_2(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_map_with_reply_awaition() {
|
|
||||||
let mut mode_store = ModeStoreMap::default();
|
|
||||||
generic_reply_handling_with_reply_awaition(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_map_with_reply_awaition_2() {
|
|
||||||
let mut mode_store = ModeStoreMap::default();
|
|
||||||
generic_reply_handling_with_reply_awaition_2(&mut mode_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_vec_no_reply_awaition() {
|
|
||||||
let mut mode_store = ModeStoreVec::default();
|
|
||||||
generic_reply_handling_test_no_reply_awaition(&mut mode_store);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_generic_reply_handler_map_no_reply_awaition() {
|
|
||||||
let mut mode_store = ModeStoreMap::default();
|
|
||||||
generic_reply_handling_test_no_reply_awaition(&mut mode_store);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -387,18 +387,18 @@ pub mod heapless_mod {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! static_subpool {
|
macro_rules! static_subpool {
|
||||||
($pool_name: ident, $sizes_list_name: ident, $num_blocks: expr, $block_size: expr) => {
|
($pool_name: ident, $sizes_list_name: ident, $num_blocks: expr, $block_size: expr) => {
|
||||||
static $pool_name: static_cell::ConstStaticCell<[u8; $num_blocks * $block_size]> =
|
static mut $pool_name: core::mem::MaybeUninit<[u8; $num_blocks * $block_size]> =
|
||||||
static_cell::ConstStaticCell::new([0; $num_blocks * $block_size]);
|
core::mem::MaybeUninit::new([0; $num_blocks * $block_size]);
|
||||||
static $sizes_list_name: static_cell::ConstStaticCell<[usize; $num_blocks]> =
|
static mut $sizes_list_name: core::mem::MaybeUninit<[usize; $num_blocks]> =
|
||||||
static_cell::ConstStaticCell::new([$crate::pool::STORE_FREE; $num_blocks]);
|
core::mem::MaybeUninit::new([$crate::pool::STORE_FREE; $num_blocks]);
|
||||||
};
|
};
|
||||||
($pool_name: ident, $sizes_list_name: ident, $num_blocks: expr, $block_size: expr, $meta_data: meta) => {
|
($pool_name: ident, $sizes_list_name: ident, $num_blocks: expr, $block_size: expr, $meta_data: meta) => {
|
||||||
#[$meta_data]
|
#[$meta_data]
|
||||||
static $pool_name: static_cell::ConstStaticCell<[u8; $num_blocks * $block_size]> =
|
static mut $pool_name: core::mem::MaybeUninit<[u8; $num_blocks * $block_size]> =
|
||||||
static_cell::ConstStaticCell::new([0; $num_blocks * $block_size]);
|
core::mem::MaybeUninit::new([0; $num_blocks * $block_size]);
|
||||||
#[$meta_data]
|
#[$meta_data]
|
||||||
static $sizes_list_name: static_cell::ConstStaticCell<[usize; $num_blocks]> =
|
static mut $sizes_list_name: core::mem::MaybeUninit<[usize; $num_blocks]> =
|
||||||
static_cell::ConstStaticCell::new([$crate::pool::STORE_FREE; $num_blocks]);
|
core::mem::MaybeUninit::new([$crate::pool::STORE_FREE; $num_blocks]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,17 +435,17 @@ pub mod heapless_mod {
|
|||||||
///
|
///
|
||||||
/// let mut mem_pool: StaticHeaplessMemoryPool<2> = StaticHeaplessMemoryPool::new(true);
|
/// let mut mem_pool: StaticHeaplessMemoryPool<2> = StaticHeaplessMemoryPool::new(true);
|
||||||
/// mem_pool.grow(
|
/// mem_pool.grow(
|
||||||
/// SUBPOOL_SMALL.take(),
|
/// unsafe { SUBPOOL_SMALL.assume_init_mut() },
|
||||||
/// SUBPOOL_SMALL_SIZES.take(),
|
/// unsafe { SUBPOOL_SMALL_SIZES.assume_init_mut() },
|
||||||
/// SUBPOOL_SMALL_NUM_BLOCKS,
|
/// SUBPOOL_SMALL_NUM_BLOCKS,
|
||||||
/// false
|
/// false
|
||||||
/// ).unwrap();
|
/// );
|
||||||
/// mem_pool.grow(
|
/// mem_pool.grow(
|
||||||
/// SUBPOOL_LARGE.take(),
|
/// unsafe { SUBPOOL_LARGE.assume_init_mut() },
|
||||||
/// SUBPOOL_LARGE_SIZES.take(),
|
/// unsafe { SUBPOOL_LARGE_SIZES.assume_init_mut() },
|
||||||
/// SUBPOOL_LARGE_NUM_BLOCKS,
|
/// SUBPOOL_LARGE_NUM_BLOCKS,
|
||||||
/// false
|
/// false
|
||||||
/// ).unwrap();
|
/// );
|
||||||
///
|
///
|
||||||
/// let mut read_buf: [u8; 16] = [0; 16];
|
/// let mut read_buf: [u8; 16] = [0; 16];
|
||||||
/// let mut addr;
|
/// let mut addr;
|
||||||
@ -522,14 +522,12 @@ pub mod heapless_mod {
|
|||||||
num_blocks: NumBlocks,
|
num_blocks: NumBlocks,
|
||||||
set_sizes_list_to_all_free: bool,
|
set_sizes_list_to_all_free: bool,
|
||||||
) -> Result<(), PoolIsFull> {
|
) -> Result<(), PoolIsFull> {
|
||||||
assert_eq!(
|
assert!(
|
||||||
(subpool_memory.len() % num_blocks as usize),
|
(subpool_memory.len() % num_blocks as usize) == 0,
|
||||||
0,
|
|
||||||
"pool slice length must be multiple of number of blocks"
|
"pool slice length must be multiple of number of blocks"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert!(
|
||||||
num_blocks as usize,
|
num_blocks as usize == sizes_list.len(),
|
||||||
sizes_list.len(),
|
|
||||||
"used block size list slice must be of same length as number of blocks"
|
"used block size list slice must be of same length as number of blocks"
|
||||||
);
|
);
|
||||||
let subpool_config = SubpoolConfig {
|
let subpool_config = SubpoolConfig {
|
||||||
@ -770,12 +768,12 @@ mod alloc_mod {
|
|||||||
/// # Parameters
|
/// # Parameters
|
||||||
///
|
///
|
||||||
/// * `cfg` - Vector of tuples which represent a subpool. The first entry in the tuple specifies
|
/// * `cfg` - Vector of tuples which represent a subpool. The first entry in the tuple specifies
|
||||||
/// the number of memory blocks in the subpool, the second entry the size of the blocks
|
/// the number of memory blocks in the subpool, the second entry the size of the blocks
|
||||||
/// * `spill_to_higher_subpools` - Specifies whether data will be spilled to higher subpools
|
/// * `spill_to_higher_subpools` - Specifies whether data will be spilled to higher subpools
|
||||||
/// if the next fitting subpool is full. This is useful to ensure the pool remains useful
|
/// if the next fitting subpool is full. This is useful to ensure the pool remains useful
|
||||||
/// for all data sizes as long as possible. However, an undesirable side-effect might be
|
/// for all data sizes as long as possible. However, an undesirable side-effect might be
|
||||||
/// the chocking of larger subpools by underdimensioned smaller subpools.
|
/// the chocking of larger subpools by underdimensioned smaller subpools.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct StaticPoolConfig {
|
pub struct StaticPoolConfig {
|
||||||
cfg: Vec<SubpoolConfig>,
|
cfg: Vec<SubpoolConfig>,
|
||||||
spill_to_higher_subpools: bool,
|
spill_to_higher_subpools: bool,
|
||||||
@ -834,7 +832,6 @@ mod alloc_mod {
|
|||||||
/// [address][PoolAddr] type. Adding any data to the pool will yield a store address.
|
/// [address][PoolAddr] type. Adding any data to the pool will yield a store address.
|
||||||
/// Modification and read operations are done using a reference to a store address. Deletion
|
/// Modification and read operations are done using a reference to a store address. Deletion
|
||||||
/// will consume the store address.
|
/// will consume the store address.
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StaticMemoryPool {
|
pub struct StaticMemoryPool {
|
||||||
pool_cfg: StaticPoolConfig,
|
pool_cfg: StaticPoolConfig,
|
||||||
pool: Vec<Vec<u8>>,
|
pool: Vec<Vec<u8>>,
|
||||||
@ -1587,33 +1584,21 @@ mod tests {
|
|||||||
mod heapless_tests {
|
mod heapless_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::static_subpool;
|
use crate::static_subpool;
|
||||||
use std::cell::UnsafeCell;
|
use core::ptr::addr_of_mut;
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
const SUBPOOL_1_BLOCK_SIZE: usize = 4;
|
const SUBPOOL_1_BLOCK_SIZE: usize = 4;
|
||||||
const SUBPOOL_1_NUM_ELEMENTS: u16 = 4;
|
const SUBPOOL_1_NUM_ELEMENTS: u16 = 4;
|
||||||
|
static mut SUBPOOL_1: [u8; SUBPOOL_1_NUM_ELEMENTS as usize * SUBPOOL_1_BLOCK_SIZE] =
|
||||||
static SUBPOOL_1: static_cell::ConstStaticCell<
|
[0; SUBPOOL_1_NUM_ELEMENTS as usize * SUBPOOL_1_BLOCK_SIZE];
|
||||||
[u8; SUBPOOL_1_NUM_ELEMENTS as usize * SUBPOOL_1_BLOCK_SIZE],
|
static mut SUBPOOL_1_SIZES: [usize; SUBPOOL_1_NUM_ELEMENTS as usize] =
|
||||||
> = static_cell::ConstStaticCell::new(
|
[STORE_FREE; SUBPOOL_1_NUM_ELEMENTS as usize];
|
||||||
[0; SUBPOOL_1_NUM_ELEMENTS as usize * SUBPOOL_1_BLOCK_SIZE],
|
|
||||||
);
|
|
||||||
|
|
||||||
static SUBPOOL_1_SIZES: Mutex<UnsafeCell<[usize; SUBPOOL_1_NUM_ELEMENTS as usize]>> =
|
|
||||||
Mutex::new(UnsafeCell::new(
|
|
||||||
[STORE_FREE; SUBPOOL_1_NUM_ELEMENTS as usize],
|
|
||||||
));
|
|
||||||
|
|
||||||
const SUBPOOL_2_NUM_ELEMENTS: u16 = 2;
|
const SUBPOOL_2_NUM_ELEMENTS: u16 = 2;
|
||||||
const SUBPOOL_2_BLOCK_SIZE: usize = 8;
|
const SUBPOOL_2_BLOCK_SIZE: usize = 8;
|
||||||
static SUBPOOL_2: static_cell::ConstStaticCell<
|
static mut SUBPOOL_2: [u8; SUBPOOL_2_NUM_ELEMENTS as usize * SUBPOOL_2_BLOCK_SIZE] =
|
||||||
[u8; SUBPOOL_2_NUM_ELEMENTS as usize * SUBPOOL_2_BLOCK_SIZE],
|
[0; SUBPOOL_2_NUM_ELEMENTS as usize * SUBPOOL_2_BLOCK_SIZE];
|
||||||
> = static_cell::ConstStaticCell::new(
|
static mut SUBPOOL_2_SIZES: [usize; SUBPOOL_2_NUM_ELEMENTS as usize] =
|
||||||
[0; SUBPOOL_2_NUM_ELEMENTS as usize * SUBPOOL_2_BLOCK_SIZE],
|
[STORE_FREE; SUBPOOL_2_NUM_ELEMENTS as usize];
|
||||||
);
|
|
||||||
static SUBPOOL_2_SIZES: static_cell::ConstStaticCell<
|
|
||||||
[usize; SUBPOOL_2_NUM_ELEMENTS as usize],
|
|
||||||
> = static_cell::ConstStaticCell::new([STORE_FREE; SUBPOOL_2_NUM_ELEMENTS as usize]);
|
|
||||||
|
|
||||||
const SUBPOOL_3_NUM_ELEMENTS: u16 = 1;
|
const SUBPOOL_3_NUM_ELEMENTS: u16 = 1;
|
||||||
const SUBPOOL_3_BLOCK_SIZE: usize = 16;
|
const SUBPOOL_3_BLOCK_SIZE: usize = 16;
|
||||||
@ -1656,24 +1641,24 @@ mod tests {
|
|||||||
StaticHeaplessMemoryPool::new(false);
|
StaticHeaplessMemoryPool::new(false);
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_1.take(),
|
unsafe { &mut *addr_of_mut!(SUBPOOL_1) },
|
||||||
unsafe { &mut *SUBPOOL_1_SIZES.lock().unwrap().get() },
|
unsafe { &mut *addr_of_mut!(SUBPOOL_1_SIZES) },
|
||||||
SUBPOOL_1_NUM_ELEMENTS,
|
SUBPOOL_1_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_2.take(),
|
unsafe { &mut *addr_of_mut!(SUBPOOL_2) },
|
||||||
SUBPOOL_2_SIZES.take(),
|
unsafe { &mut *addr_of_mut!(SUBPOOL_2_SIZES) },
|
||||||
SUBPOOL_2_NUM_ELEMENTS,
|
SUBPOOL_2_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_3.take(),
|
unsafe { SUBPOOL_3.assume_init_mut() },
|
||||||
SUBPOOL_3_SIZES.take(),
|
unsafe { SUBPOOL_3_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_3_NUM_ELEMENTS,
|
SUBPOOL_3_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -1795,16 +1780,16 @@ mod tests {
|
|||||||
StaticHeaplessMemoryPool::new(true);
|
StaticHeaplessMemoryPool::new(true);
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_2.take(),
|
unsafe { &mut *addr_of_mut!(SUBPOOL_2) },
|
||||||
SUBPOOL_2_SIZES.take(),
|
unsafe { &mut *addr_of_mut!(SUBPOOL_2_SIZES) },
|
||||||
SUBPOOL_2_NUM_ELEMENTS,
|
SUBPOOL_2_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_4.take(),
|
unsafe { SUBPOOL_4.assume_init_mut() },
|
||||||
SUBPOOL_4_SIZES.take(),
|
unsafe { SUBPOOL_4_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_4_NUM_ELEMENTS,
|
SUBPOOL_4_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -1818,16 +1803,16 @@ mod tests {
|
|||||||
StaticHeaplessMemoryPool::new(true);
|
StaticHeaplessMemoryPool::new(true);
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_5.take(),
|
unsafe { SUBPOOL_5.assume_init_mut() },
|
||||||
SUBPOOL_5_SIZES.take(),
|
unsafe { SUBPOOL_5_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_5_NUM_ELEMENTS,
|
SUBPOOL_5_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_3.take(),
|
unsafe { SUBPOOL_3.assume_init_mut() },
|
||||||
SUBPOOL_3_SIZES.take(),
|
unsafe { SUBPOOL_3_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_3_NUM_ELEMENTS,
|
SUBPOOL_3_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -1841,24 +1826,24 @@ mod tests {
|
|||||||
StaticHeaplessMemoryPool::new(true);
|
StaticHeaplessMemoryPool::new(true);
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_5.take(),
|
unsafe { SUBPOOL_5.assume_init_mut() },
|
||||||
SUBPOOL_5_SIZES.take(),
|
unsafe { SUBPOOL_5_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_5_NUM_ELEMENTS,
|
SUBPOOL_5_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_6.take(),
|
unsafe { SUBPOOL_6.assume_init_mut() },
|
||||||
SUBPOOL_6_SIZES.take(),
|
unsafe { SUBPOOL_6_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_6_NUM_ELEMENTS,
|
SUBPOOL_6_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_3.take(),
|
unsafe { SUBPOOL_3.assume_init_mut() },
|
||||||
SUBPOOL_3_SIZES.take(),
|
unsafe { SUBPOOL_3_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_3_NUM_ELEMENTS,
|
SUBPOOL_3_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -1872,24 +1857,24 @@ mod tests {
|
|||||||
StaticHeaplessMemoryPool::new(true);
|
StaticHeaplessMemoryPool::new(true);
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_5.take(),
|
unsafe { SUBPOOL_5.assume_init_mut() },
|
||||||
SUBPOOL_5_SIZES.take(),
|
unsafe { SUBPOOL_5_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_5_NUM_ELEMENTS,
|
SUBPOOL_5_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_6.take(),
|
unsafe { SUBPOOL_6.assume_init_mut() },
|
||||||
SUBPOOL_6_SIZES.take(),
|
unsafe { SUBPOOL_6_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_6_NUM_ELEMENTS,
|
SUBPOOL_6_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(heapless_pool
|
assert!(heapless_pool
|
||||||
.grow(
|
.grow(
|
||||||
SUBPOOL_3.take(),
|
unsafe { SUBPOOL_3.assume_init_mut() },
|
||||||
SUBPOOL_3_SIZES.take(),
|
unsafe { SUBPOOL_3_SIZES.assume_init_mut() },
|
||||||
SUBPOOL_3_NUM_ELEMENTS,
|
SUBPOOL_3_NUM_ELEMENTS,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
@ -66,10 +66,9 @@ impl GenericActionReplyPus {
|
|||||||
pub mod alloc_mod {
|
pub mod alloc_mod {
|
||||||
use crate::{
|
use crate::{
|
||||||
action::ActionRequest,
|
action::ActionRequest,
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
queue::GenericTargetedMessagingError,
|
||||||
request::{
|
request::{
|
||||||
GenericMessage, MessageReceiverProvider, MessageSenderAndReceiver,
|
GenericMessage, MessageReceiver, MessageSender, MessageSenderAndReceiver, RequestId,
|
||||||
MessageSenderProvider, MessageSenderStoreProvider, RequestId,
|
|
||||||
},
|
},
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
@ -77,18 +76,15 @@ pub mod alloc_mod {
|
|||||||
use super::ActionReplyPus;
|
use super::ActionReplyPus;
|
||||||
|
|
||||||
/// Helper type definition for a mode handler which can handle mode requests.
|
/// Helper type definition for a mode handler which can handle mode requests.
|
||||||
pub type ActionRequestHandlerInterface<Sender, Receiver, ReplySenderStore> =
|
pub type ActionRequestHandlerInterface<S, R> =
|
||||||
MessageSenderAndReceiver<ActionReplyPus, ActionRequest, Sender, Receiver, ReplySenderStore>;
|
MessageSenderAndReceiver<ActionReplyPus, ActionRequest, S, R>;
|
||||||
|
|
||||||
impl<
|
impl<S: MessageSender<ActionReplyPus>, R: MessageReceiver<ActionRequest>>
|
||||||
Sender: MessageSenderProvider<ActionReplyPus>,
|
ActionRequestHandlerInterface<S, R>
|
||||||
Receiver: MessageReceiverProvider<ActionRequest>,
|
|
||||||
ReplySender: MessageSenderStoreProvider<ActionReplyPus, Sender>,
|
|
||||||
> ActionRequestHandlerInterface<Sender, Receiver, ReplySender>
|
|
||||||
{
|
{
|
||||||
pub fn try_recv_action_request(
|
pub fn try_recv_action_request(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ActionRequest>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ActionRequest>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,31 +93,22 @@ pub mod alloc_mod {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
reply: ActionReplyPus,
|
reply: ActionReplyPus,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, target_id, reply)
|
self.send_message(request_id, target_id, reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper type defintion for a mode handler object which can send mode requests and receive
|
/// Helper type defintion for a mode handler object which can send mode requests and receive
|
||||||
/// mode replies.
|
/// mode replies.
|
||||||
pub type ActionRequestorInterface<Sender, Receiver, RequestSenderStore> =
|
pub type ActionRequestorInterface<S, R> =
|
||||||
MessageSenderAndReceiver<
|
MessageSenderAndReceiver<ActionRequest, ActionReplyPus, S, R>;
|
||||||
ActionRequest,
|
|
||||||
ActionReplyPus,
|
|
||||||
Sender,
|
|
||||||
Receiver,
|
|
||||||
RequestSenderStore,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<
|
impl<S: MessageSender<ActionRequest>, R: MessageReceiver<ActionReplyPus>>
|
||||||
Sender: MessageSenderProvider<ActionRequest>,
|
ActionRequestorInterface<S, R>
|
||||||
Receiver: MessageReceiverProvider<ActionReplyPus>,
|
|
||||||
RequestSenderStore: MessageSenderStoreProvider<ActionRequest, Sender>,
|
|
||||||
> ActionRequestorInterface<Sender, Receiver, RequestSenderStore>
|
|
||||||
{
|
{
|
||||||
pub fn try_recv_action_reply(
|
pub fn try_recv_action_reply(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<ActionReplyPus>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<ActionReplyPus>>, GenericTargetedMessagingError> {
|
||||||
self.try_recv_message()
|
self.try_recv_message()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +117,7 @@ pub mod alloc_mod {
|
|||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ActionRequest,
|
request: ActionRequest,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, target_id, request)
|
self.send_message(request_id, target_id, request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +132,6 @@ pub mod std_mod {
|
|||||||
verification::{self, TcStateToken},
|
verification::{self, TcStateToken},
|
||||||
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap,
|
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap,
|
||||||
},
|
},
|
||||||
request::{MessageSenderMap, OneMessageSender},
|
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -188,38 +174,22 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
pub type DefaultActiveActionRequestMap = DefaultActiveRequestMap<ActivePusActionRequestStd>;
|
pub type DefaultActiveActionRequestMap = DefaultActiveRequestMap<ActivePusActionRequestStd>;
|
||||||
|
|
||||||
pub type ActionRequestHandlerOneSenderMpsc = ActionRequestHandlerInterface<
|
pub type ActionRequestHandlerMpsc = ActionRequestHandlerInterface<
|
||||||
mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
||||||
mpsc::Receiver<GenericMessage<ActionRequest>>,
|
mpsc::Receiver<GenericMessage<ActionRequest>>,
|
||||||
OneMessageSender<
|
|
||||||
GenericMessage<ActionReplyPus>,
|
|
||||||
mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
|
||||||
>,
|
|
||||||
>;
|
>;
|
||||||
pub type ActionRequestHandlerOneSenderMpscBounded = ActionRequestHandlerInterface<
|
pub type ActionRequestHandlerMpscBounded = ActionRequestHandlerInterface<
|
||||||
mpsc::SyncSender<GenericMessage<ActionReplyPus>>,
|
mpsc::SyncSender<GenericMessage<ActionReplyPus>>,
|
||||||
mpsc::Receiver<GenericMessage<ActionRequest>>,
|
mpsc::Receiver<GenericMessage<ActionRequest>>,
|
||||||
OneMessageSender<
|
|
||||||
GenericMessage<ActionReplyPus>,
|
|
||||||
mpsc::SyncSender<GenericMessage<ActionReplyPus>>,
|
|
||||||
>,
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub type ActionRequestorWithSenderMapMpsc = ActionRequestorInterface<
|
pub type ActionRequestorMpsc = ActionRequestorInterface<
|
||||||
mpsc::Sender<GenericMessage<ActionRequest>>,
|
mpsc::Sender<GenericMessage<ActionRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||||
MessageSenderMap<
|
|
||||||
GenericMessage<ActionRequest>,
|
|
||||||
mpsc::Sender<GenericMessage<ActionRequest>>,
|
|
||||||
>,
|
|
||||||
>;
|
>;
|
||||||
pub type ActionRequestorWithSenderMapBoundedMpsc = ActionRequestorInterface<
|
pub type ActionRequestorBoundedMpsc = ActionRequestorInterface<
|
||||||
mpsc::SyncSender<GenericMessage<ActionRequest>>,
|
mpsc::SyncSender<GenericMessage<ActionRequest>>,
|
||||||
mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||||
MessageSenderMap<
|
|
||||||
GenericMessage<ActionRequest>,
|
|
||||||
mpsc::SyncSender<GenericMessage<ActionRequest>>,
|
|
||||||
>,
|
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ mod tests {
|
|||||||
assert!(res.event_was_enabled);
|
assert!(res.event_was_enabled);
|
||||||
assert!(res.params_were_propagated);
|
assert!(res.params_were_propagated);
|
||||||
let event_tm = event_rx.try_recv().expect("no event received");
|
let event_tm = event_rx.try_recv().expect("no event received");
|
||||||
let tm = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
|
let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
|
||||||
assert_eq!(tm.service(), 5);
|
assert_eq!(tm.service(), 5);
|
||||||
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
|
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
|
||||||
assert_eq!(tm.user_data().len(), 4 + param_data.len());
|
assert_eq!(tm.user_data().len(), 4 + param_data.len());
|
||||||
@ -437,7 +437,7 @@ mod tests {
|
|||||||
assert!(res.event_was_enabled);
|
assert!(res.event_was_enabled);
|
||||||
assert!(res.params_were_propagated);
|
assert!(res.params_were_propagated);
|
||||||
let event_tm = event_rx.try_recv().expect("no event received");
|
let event_tm = event_rx.try_recv().expect("no event received");
|
||||||
let tm = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
|
let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
|
||||||
assert_eq!(tm.service(), 5);
|
assert_eq!(tm.service(), 5);
|
||||||
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
|
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
|
||||||
assert_eq!(tm.user_data().len(), 4 + param_data.len());
|
assert_eq!(tm.user_data().len(), 4 + param_data.len());
|
||||||
|
@ -9,14 +9,14 @@ use std::sync::mpsc::Sender;
|
|||||||
|
|
||||||
use super::verification::VerificationReportingProvider;
|
use super::verification::VerificationReportingProvider;
|
||||||
use super::{
|
use super::{
|
||||||
EcssTcInMemConversionProvider, EcssTcReceiver, EcssTmSender, GenericConversionError,
|
EcssTcInMemConverter, EcssTcReceiver, EcssTmSender, GenericConversionError,
|
||||||
GenericRoutingError, HandlingStatus, PusServiceHelper,
|
GenericRoutingError, HandlingStatus, PusServiceHelper,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PusEventServiceHandler<
|
pub struct PusEventServiceHandler<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> {
|
> {
|
||||||
pub service_helper:
|
pub service_helper:
|
||||||
@ -27,7 +27,7 @@ pub struct PusEventServiceHandler<
|
|||||||
impl<
|
impl<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||||
{
|
{
|
||||||
@ -170,7 +170,7 @@ mod tests {
|
|||||||
event_man::EventRequestWithToken,
|
event_man::EventRequestWithToken,
|
||||||
tests::PusServiceHandlerWithSharedStoreCommon,
|
tests::PusServiceHandlerWithSharedStoreCommon,
|
||||||
verification::{TcStateAccepted, VerificationToken},
|
verification::{TcStateAccepted, VerificationToken},
|
||||||
DirectPusPacketHandlerResult, EcssTcInSharedPoolConverter, PusPacketHandlingError,
|
DirectPusPacketHandlerResult, EcssTcInSharedStoreConverter, PusPacketHandlingError,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ mod tests {
|
|||||||
handler: PusEventServiceHandler<
|
handler: PusEventServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
@ -199,12 +199,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus5HandlerWithStoreTester {
|
impl PusTestHarness for Pus5HandlerWithStoreTester {
|
||||||
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
let init_token = self
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
.handler
|
|
||||||
.service_helper
|
|
||||||
.verif_reporter_mut()
|
|
||||||
.start_verification(tc);
|
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
@ -249,7 +245,7 @@ mod tests {
|
|||||||
.write_to_be_bytes(&mut app_data)
|
.write_to_be_bytes(&mut app_data)
|
||||||
.expect("writing test event failed");
|
.expect("writing test event failed");
|
||||||
let ping_tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
|
let ping_tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
test_harness.handle_one_tc().unwrap();
|
test_harness.handle_one_tc().unwrap();
|
||||||
@ -310,7 +306,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
|
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
@ -330,7 +326,7 @@ mod tests {
|
|||||||
let sec_header =
|
let sec_header =
|
||||||
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
|
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
|
||||||
let ping_tc = PusTcCreator::new(sp_header, sec_header, &[0, 1, 2], true);
|
let ping_tc = PusTcCreator::new(sp_header, sec_header, &[0, 1, 2], true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -947,7 +947,7 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EcssTcInMemConversionProvider {
|
pub trait EcssTcInMemConverter {
|
||||||
fn cache(&mut self, possible_packet: &TcInMemory) -> Result<(), PusTcFromMemError>;
|
fn cache(&mut self, possible_packet: &TcInMemory) -> Result<(), PusTcFromMemError>;
|
||||||
|
|
||||||
fn tc_slice_raw(&self) -> &[u8];
|
fn tc_slice_raw(&self) -> &[u8];
|
||||||
@ -959,11 +959,15 @@ pub mod std_mod {
|
|||||||
possible_packet: &TcInMemory,
|
possible_packet: &TcInMemory,
|
||||||
) -> Result<PusTcReader<'_>, PusTcFromMemError> {
|
) -> Result<PusTcReader<'_>, PusTcFromMemError> {
|
||||||
self.cache(possible_packet)?;
|
self.cache(possible_packet)?;
|
||||||
Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
|
Ok(PusTcReader::new(self.tc_slice_raw())
|
||||||
|
.map_err(EcssTmtcError::Pus)?
|
||||||
|
.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> {
|
fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> {
|
||||||
Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
|
Ok(PusTcReader::new(self.tc_slice_raw())
|
||||||
|
.map_err(EcssTmtcError::Pus)?
|
||||||
|
.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,7 +980,7 @@ pub mod std_mod {
|
|||||||
pub pus_tc_raw: Option<Vec<u8>>,
|
pub pus_tc_raw: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTcInMemConversionProvider for EcssTcInVecConverter {
|
impl EcssTcInMemConverter for EcssTcInVecConverter {
|
||||||
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
|
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
|
||||||
self.pus_tc_raw = None;
|
self.pus_tc_raw = None;
|
||||||
match tc_in_memory {
|
match tc_in_memory {
|
||||||
@ -1007,25 +1011,24 @@ pub mod std_mod {
|
|||||||
/// [SharedStaticMemoryPool] structure. This is useful if run-time allocation for these
|
/// [SharedStaticMemoryPool] structure. This is useful if run-time allocation for these
|
||||||
/// packets should be avoided. Please note that this structure is not able to convert TCs which
|
/// packets should be avoided. Please note that this structure is not able to convert TCs which
|
||||||
/// are stored as a `Vec<u8>`.
|
/// are stored as a `Vec<u8>`.
|
||||||
#[derive(Clone)]
|
pub struct EcssTcInSharedStoreConverter {
|
||||||
pub struct EcssTcInSharedPoolConverter {
|
|
||||||
sender_id: Option<ComponentId>,
|
sender_id: Option<ComponentId>,
|
||||||
shared_tc_pool: SharedStaticMemoryPool,
|
shared_tc_store: SharedStaticMemoryPool,
|
||||||
pus_buf: Vec<u8>,
|
pus_buf: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTcInSharedPoolConverter {
|
impl EcssTcInSharedStoreConverter {
|
||||||
pub fn new(shared_tc_store: SharedStaticMemoryPool, max_expected_tc_size: usize) -> Self {
|
pub fn new(shared_tc_store: SharedStaticMemoryPool, max_expected_tc_size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sender_id: None,
|
sender_id: None,
|
||||||
shared_tc_pool: shared_tc_store,
|
shared_tc_store,
|
||||||
pus_buf: alloc::vec![0; max_expected_tc_size],
|
pus_buf: alloc::vec![0; max_expected_tc_size],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_tc_to_buf(&mut self, addr: PoolAddr) -> Result<(), PusTcFromMemError> {
|
pub fn copy_tc_to_buf(&mut self, addr: PoolAddr) -> Result<(), PusTcFromMemError> {
|
||||||
// Keep locked section as short as possible.
|
// Keep locked section as short as possible.
|
||||||
let mut tc_pool = self.shared_tc_pool.write().map_err(|_| {
|
let mut tc_pool = self.shared_tc_store.write().map_err(|_| {
|
||||||
PusTcFromMemError::EcssTmtc(EcssTmtcError::Store(PoolError::LockError))
|
PusTcFromMemError::EcssTmtc(EcssTmtcError::Store(PoolError::LockError))
|
||||||
})?;
|
})?;
|
||||||
let tc_size = tc_pool.len_of_data(&addr).map_err(EcssTmtcError::Store)?;
|
let tc_size = tc_pool.len_of_data(&addr).map_err(EcssTmtcError::Store)?;
|
||||||
@ -1045,7 +1048,7 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTcInMemConversionProvider for EcssTcInSharedPoolConverter {
|
impl EcssTcInMemConverter for EcssTcInSharedStoreConverter {
|
||||||
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
|
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
|
||||||
match tc_in_memory {
|
match tc_in_memory {
|
||||||
super::TcInMemory::Pool(packet_in_pool) => {
|
super::TcInMemory::Pool(packet_in_pool) => {
|
||||||
@ -1068,44 +1071,6 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: alloc feature flag?
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum EcssTcInMemConverter {
|
|
||||||
Static(EcssTcInSharedPoolConverter),
|
|
||||||
Heap(EcssTcInVecConverter),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssTcInMemConverter {
|
|
||||||
pub fn new_static(static_store_converter: EcssTcInSharedPoolConverter) -> Self {
|
|
||||||
EcssTcInMemConverter::Static(static_store_converter)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_heap(heap_converter: EcssTcInVecConverter) -> Self {
|
|
||||||
EcssTcInMemConverter::Heap(heap_converter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssTcInMemConversionProvider for EcssTcInMemConverter {
|
|
||||||
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
|
|
||||||
match self {
|
|
||||||
EcssTcInMemConverter::Static(converter) => converter.cache(tc_in_memory),
|
|
||||||
EcssTcInMemConverter::Heap(converter) => converter.cache(tc_in_memory),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn tc_slice_raw(&self) -> &[u8] {
|
|
||||||
match self {
|
|
||||||
EcssTcInMemConverter::Static(converter) => converter.tc_slice_raw(),
|
|
||||||
EcssTcInMemConverter::Heap(converter) => converter.tc_slice_raw(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn sender_id(&self) -> Option<ComponentId> {
|
|
||||||
match self {
|
|
||||||
EcssTcInMemConverter::Static(converter) => converter.sender_id(),
|
|
||||||
EcssTcInMemConverter::Heap(converter) => converter.sender_id(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PusServiceBase<
|
pub struct PusServiceBase<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
@ -1129,7 +1094,7 @@ pub mod std_mod {
|
|||||||
pub struct PusServiceHelper<
|
pub struct PusServiceHelper<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> {
|
> {
|
||||||
pub common: PusServiceBase<TcReceiver, TmSender, VerificationReporter>,
|
pub common: PusServiceBase<TcReceiver, TmSender, VerificationReporter>,
|
||||||
@ -1139,7 +1104,7 @@ pub mod std_mod {
|
|||||||
impl<
|
impl<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||||
{
|
{
|
||||||
@ -1256,9 +1221,8 @@ pub(crate) fn source_buffer_large_enough(
|
|||||||
|
|
||||||
#[cfg(any(feature = "test_util", test))]
|
#[cfg(any(feature = "test_util", test))]
|
||||||
pub mod test_util {
|
pub mod test_util {
|
||||||
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
|
||||||
|
|
||||||
use crate::request::UniqueApidTargetId;
|
use crate::request::UniqueApidTargetId;
|
||||||
|
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
verification::{self, TcStateAccepted, VerificationToken},
|
verification::{self, TcStateAccepted, VerificationToken},
|
||||||
@ -1268,14 +1232,13 @@ pub mod test_util {
|
|||||||
pub const TEST_APID: u16 = 0x101;
|
pub const TEST_APID: u16 = 0x101;
|
||||||
pub const TEST_UNIQUE_ID_0: u32 = 0x05;
|
pub const TEST_UNIQUE_ID_0: u32 = 0x05;
|
||||||
pub const TEST_UNIQUE_ID_1: u32 = 0x06;
|
pub const TEST_UNIQUE_ID_1: u32 = 0x06;
|
||||||
|
|
||||||
pub const TEST_COMPONENT_ID_0: UniqueApidTargetId =
|
pub const TEST_COMPONENT_ID_0: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_0);
|
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_0);
|
||||||
pub const TEST_COMPONENT_ID_1: UniqueApidTargetId =
|
pub const TEST_COMPONENT_ID_1: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_1);
|
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_1);
|
||||||
|
|
||||||
pub trait PusTestHarness {
|
pub trait PusTestHarness {
|
||||||
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
||||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
@ -1305,13 +1268,14 @@ pub mod tests {
|
|||||||
use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator, PusTmReader};
|
use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator, PusTmReader};
|
||||||
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
||||||
use spacepackets::CcsdsPacket;
|
use spacepackets::CcsdsPacket;
|
||||||
use test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
|
||||||
|
|
||||||
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
||||||
use crate::pus::verification::{RequestId, VerificationReporter};
|
use crate::pus::verification::{RequestId, VerificationReporter};
|
||||||
use crate::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool, SharedPacketPool};
|
use crate::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool, SharedPacketPool};
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
|
|
||||||
|
use super::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||||
|
|
||||||
use super::verification::test_util::TestVerificationReporter;
|
use super::verification::test_util::TestVerificationReporter;
|
||||||
use super::verification::{
|
use super::verification::{
|
||||||
TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
||||||
@ -1382,7 +1346,7 @@ pub mod tests {
|
|||||||
pub type PusServiceHelperStatic = PusServiceHelper<
|
pub type PusServiceHelperStatic = PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -1409,7 +1373,8 @@ pub mod tests {
|
|||||||
VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &verif_cfg);
|
VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &verif_cfg);
|
||||||
let test_srv_tm_sender =
|
let test_srv_tm_sender =
|
||||||
PacketSenderWithSharedPool::new(tm_tx, shared_tm_pool_wrapper.clone());
|
PacketSenderWithSharedPool::new(tm_tx, shared_tm_pool_wrapper.clone());
|
||||||
let in_store_converter = EcssTcInSharedPoolConverter::new(shared_tc_pool.clone(), 2048);
|
let in_store_converter =
|
||||||
|
EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
pus_buf: RefCell::new([0; 2048]),
|
pus_buf: RefCell::new([0; 2048]),
|
||||||
@ -1455,7 +1420,7 @@ pub mod tests {
|
|||||||
let tm_pool = self.tm_pool.0.read().unwrap();
|
let tm_pool = self.tm_pool.0.read().unwrap();
|
||||||
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
||||||
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
|
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
|
||||||
PusTmReader::new(&self.tm_buf, 7).unwrap()
|
PusTmReader::new(&self.tm_buf, 7).unwrap().0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_no_tm_available(&self) -> bool {
|
pub fn check_no_tm_available(&self) -> bool {
|
||||||
@ -1472,7 +1437,7 @@ pub mod tests {
|
|||||||
let tm_in_pool = next_msg.unwrap();
|
let tm_in_pool = next_msg.unwrap();
|
||||||
let tm_pool = self.tm_pool.0.read().unwrap();
|
let tm_pool = self.tm_pool.0.read().unwrap();
|
||||||
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
||||||
let tm = PusTmReader::new(&tm_raw, 7).unwrap();
|
let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
|
||||||
assert_eq!(PusPacket::service(&tm), 1);
|
assert_eq!(PusPacket::service(&tm), 1);
|
||||||
assert_eq!(PusPacket::subservice(&tm), subservice);
|
assert_eq!(PusPacket::subservice(&tm), subservice);
|
||||||
assert_eq!(tm.apid(), TEST_APID);
|
assert_eq!(tm.apid(), TEST_APID);
|
||||||
@ -1580,7 +1545,9 @@ pub mod tests {
|
|||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
self.current_tm = Some(next_msg.unwrap().packet);
|
self.current_tm = Some(next_msg.unwrap().packet);
|
||||||
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7).unwrap()
|
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_no_tm_available(&self) -> bool {
|
pub fn check_no_tm_available(&self) -> bool {
|
||||||
@ -1595,7 +1562,7 @@ pub mod tests {
|
|||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
let next_msg = next_msg.unwrap();
|
let next_msg = next_msg.unwrap();
|
||||||
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap();
|
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0;
|
||||||
assert_eq!(PusPacket::service(&tm), 1);
|
assert_eq!(PusPacket::service(&tm), 1);
|
||||||
assert_eq!(PusPacket::subservice(&tm), subservice);
|
assert_eq!(PusPacket::subservice(&tm), subservice);
|
||||||
assert_eq!(tm.apid(), TEST_APID);
|
assert_eq!(tm.apid(), TEST_APID);
|
||||||
|
@ -39,7 +39,7 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
mode::{
|
mode::{
|
||||||
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
||||||
ModeRequestorAndHandlerMpsc, ModeRequestorOneChildMpsc,
|
ModeRequestorAndHandlerMpsc, ModeRequestorMpsc,
|
||||||
},
|
},
|
||||||
request::{GenericMessage, MessageMetadata},
|
request::{GenericMessage, MessageMetadata},
|
||||||
};
|
};
|
||||||
@ -52,8 +52,7 @@ mod tests {
|
|||||||
fn test_simple_mode_requestor() {
|
fn test_simple_mode_requestor() {
|
||||||
let (reply_sender, reply_receiver) = mpsc::channel();
|
let (reply_sender, reply_receiver) = mpsc::channel();
|
||||||
let (request_sender, request_receiver) = mpsc::channel();
|
let (request_sender, request_receiver) = mpsc::channel();
|
||||||
let mut mode_requestor =
|
let mut mode_requestor = ModeRequestorMpsc::new(TEST_COMPONENT_ID_0, reply_receiver);
|
||||||
ModeRequestorOneChildMpsc::new(TEST_COMPONENT_ID_0, reply_receiver);
|
|
||||||
mode_requestor.add_message_target(TEST_COMPONENT_ID_1, request_sender);
|
mode_requestor.add_message_target(TEST_COMPONENT_ID_1, request_sender);
|
||||||
|
|
||||||
// Send a request and verify it arrives at the receiver.
|
// Send a request and verify it arrives at the receiver.
|
||||||
|
@ -292,10 +292,10 @@ pub trait PusSchedulerProvider {
|
|||||||
pool: &mut (impl PoolProvider + ?Sized),
|
pool: &mut (impl PoolProvider + ?Sized),
|
||||||
) -> Result<TcInfo, ScheduleError> {
|
) -> Result<TcInfo, ScheduleError> {
|
||||||
let check_tc = PusTcReader::new(tc)?;
|
let check_tc = PusTcReader::new(tc)?;
|
||||||
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
|
if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
|
||||||
return Err(ScheduleError::NestedScheduledTc);
|
return Err(ScheduleError::NestedScheduledTc);
|
||||||
}
|
}
|
||||||
let req_id = RequestId::from_tc(&check_tc);
|
let req_id = RequestId::from_tc(&check_tc.0);
|
||||||
|
|
||||||
match pool.add(tc) {
|
match pool.add(tc) {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
@ -411,10 +411,10 @@ pub mod alloc_mod {
|
|||||||
///
|
///
|
||||||
/// * `init_current_time` - The time to initialize the scheduler with.
|
/// * `init_current_time` - The time to initialize the scheduler with.
|
||||||
/// * `time_margin` - This time margin is used when inserting new telecommands into the
|
/// * `time_margin` - This time margin is used when inserting new telecommands into the
|
||||||
/// schedule. If the release time of a new telecommand is earlier than the time margin
|
/// schedule. If the release time of a new telecommand is earlier than the time margin
|
||||||
/// added to the current time, it will not be inserted into the schedule.
|
/// added to the current time, it will not be inserted into the schedule.
|
||||||
/// * `tc_buf_size` - Buffer for temporary storage of telecommand packets. This buffer
|
/// * `tc_buf_size` - Buffer for temporary storage of telecommand packets. This buffer
|
||||||
/// should be large enough to accomodate the largest expected TC packets.
|
/// should be large enough to accomodate the largest expected TC packets.
|
||||||
pub fn new(init_current_time: UnixTime, time_margin: Duration) -> Self {
|
pub fn new(init_current_time: UnixTime, time_margin: Duration) -> Self {
|
||||||
PusScheduler {
|
PusScheduler {
|
||||||
tc_map: Default::default(),
|
tc_map: Default::default(),
|
||||||
@ -480,10 +480,10 @@ pub mod alloc_mod {
|
|||||||
pool: &mut (impl PoolProvider + ?Sized),
|
pool: &mut (impl PoolProvider + ?Sized),
|
||||||
) -> Result<TcInfo, ScheduleError> {
|
) -> Result<TcInfo, ScheduleError> {
|
||||||
let check_tc = PusTcReader::new(tc)?;
|
let check_tc = PusTcReader::new(tc)?;
|
||||||
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
|
if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
|
||||||
return Err(ScheduleError::NestedScheduledTc);
|
return Err(ScheduleError::NestedScheduledTc);
|
||||||
}
|
}
|
||||||
let req_id = RequestId::from_tc(&check_tc);
|
let req_id = RequestId::from_tc(&check_tc.0);
|
||||||
|
|
||||||
match pool.add(tc) {
|
match pool.add(tc) {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
@ -683,10 +683,10 @@ pub mod alloc_mod {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `releaser` - Closure where the first argument is whether the scheduler is enabled and
|
/// * `releaser` - Closure where the first argument is whether the scheduler is enabled and
|
||||||
/// the second argument is the telecommand information also containing the store
|
/// the second argument is the telecommand information also containing the store
|
||||||
/// address. This closure should return whether the command should be deleted. Please
|
/// address. This closure should return whether the command should be deleted. Please
|
||||||
/// note that returning false might lead to memory leaks if the TC is not cleared from
|
/// note that returning false might lead to memory leaks if the TC is not cleared from
|
||||||
/// the store in some other way.
|
/// the store in some other way.
|
||||||
/// * `tc_store` - The holding store of the telecommands.
|
/// * `tc_store` - The holding store of the telecommands.
|
||||||
/// * `tc_buf` - Buffer to hold each telecommand being released.
|
/// * `tc_buf` - Buffer to hold each telecommand being released.
|
||||||
pub fn release_telecommands_with_buffer<R: FnMut(bool, &TcInfo, &[u8]) -> bool>(
|
pub fn release_telecommands_with_buffer<R: FnMut(bool, &TcInfo, &[u8]) -> bool>(
|
||||||
@ -1313,7 +1313,7 @@ mod tests {
|
|||||||
let mut read_buf: [u8; 64] = [0; 64];
|
let mut read_buf: [u8; 64] = [0; 64];
|
||||||
pool.read(&tc_info_0.addr(), &mut read_buf).unwrap();
|
pool.read(&tc_info_0.addr(), &mut read_buf).unwrap();
|
||||||
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
|
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
|
||||||
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
|
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
|
||||||
|
|
||||||
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
|
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
|
||||||
|
|
||||||
@ -1335,8 +1335,8 @@ mod tests {
|
|||||||
|
|
||||||
let read_len = pool.read(&addr_vec[0], &mut read_buf).unwrap();
|
let read_len = pool.read(&addr_vec[0], &mut read_buf).unwrap();
|
||||||
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
|
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
|
||||||
assert_eq!(read_len, check_tc.total_len());
|
assert_eq!(read_len, check_tc.1);
|
||||||
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
|
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1362,8 +1362,8 @@ mod tests {
|
|||||||
|
|
||||||
let read_len = pool.read(&info.addr, &mut buf).unwrap();
|
let read_len = pool.read(&info.addr, &mut buf).unwrap();
|
||||||
let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data");
|
let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data");
|
||||||
assert_eq!(read_len, check_tc.total_len());
|
assert_eq!(read_len, check_tc.1);
|
||||||
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
|
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
|
||||||
|
|
||||||
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
|
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
|
||||||
|
|
||||||
@ -1387,8 +1387,8 @@ mod tests {
|
|||||||
|
|
||||||
let read_len = pool.read(&addr_vec[0], &mut buf).unwrap();
|
let read_len = pool.read(&addr_vec[0], &mut buf).unwrap();
|
||||||
let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data");
|
let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data");
|
||||||
assert_eq!(read_len, check_tc.total_len());
|
assert_eq!(read_len, check_tc.1);
|
||||||
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
|
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2031,7 +2031,7 @@ mod tests {
|
|||||||
assert_eq!(n, 1);
|
assert_eq!(n, 1);
|
||||||
let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap();
|
let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap();
|
||||||
assert_eq!(time_reader, time_writer);
|
assert_eq!(time_reader, time_writer);
|
||||||
let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap();
|
let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap().0;
|
||||||
assert_eq!(pus_tc_reader, ping_tc);
|
assert_eq!(pus_tc_reader, ping_tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::scheduler::PusSchedulerProvider;
|
use super::scheduler::PusSchedulerProvider;
|
||||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||||
use super::{
|
use super::{
|
||||||
DirectPusPacketHandlerResult, EcssTcInMemConversionProvider, EcssTcInSharedPoolConverter,
|
DirectPusPacketHandlerResult, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
||||||
EcssTcInVecConverter, EcssTcReceiver, EcssTmSender, HandlingStatus, MpscTcReceiver,
|
EcssTcInVecConverter, EcssTcReceiver, EcssTmSender, HandlingStatus, MpscTcReceiver,
|
||||||
PartialPusHandlingError, PusServiceHelper,
|
PartialPusHandlingError, PusServiceHelper,
|
||||||
};
|
};
|
||||||
@ -24,7 +24,7 @@ use std::sync::mpsc;
|
|||||||
pub struct PusSchedServiceHandler<
|
pub struct PusSchedServiceHandler<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
PusScheduler: PusSchedulerProvider,
|
PusScheduler: PusSchedulerProvider,
|
||||||
> {
|
> {
|
||||||
@ -36,7 +36,7 @@ pub struct PusSchedServiceHandler<
|
|||||||
impl<
|
impl<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
Scheduler: PusSchedulerProvider,
|
Scheduler: PusSchedulerProvider,
|
||||||
>
|
>
|
||||||
@ -229,7 +229,7 @@ pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusSchedServ
|
|||||||
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
@ -238,7 +238,7 @@ pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceH
|
|||||||
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
@ -253,7 +253,7 @@ mod tests {
|
|||||||
scheduler::{self, PusSchedulerProvider, TcInfo},
|
scheduler::{self, PusSchedulerProvider, TcInfo},
|
||||||
tests::PusServiceHandlerWithSharedStoreCommon,
|
tests::PusServiceHandlerWithSharedStoreCommon,
|
||||||
verification::{RequestId, TcStateAccepted, VerificationToken},
|
verification::{RequestId, TcStateAccepted, VerificationToken},
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
};
|
};
|
||||||
use crate::pus::{DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError};
|
use crate::pus::{DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError};
|
||||||
use crate::tmtc::PacketSenderWithSharedPool;
|
use crate::tmtc::PacketSenderWithSharedPool;
|
||||||
@ -276,7 +276,7 @@ mod tests {
|
|||||||
handler: PusSchedServiceHandler<
|
handler: PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
TestScheduler,
|
TestScheduler,
|
||||||
>,
|
>,
|
||||||
@ -309,12 +309,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus11HandlerWithStoreTester {
|
impl PusTestHarness for Pus11HandlerWithStoreTester {
|
||||||
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
let init_token = self
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
.handler
|
|
||||||
.service_helper
|
|
||||||
.verif_reporter_mut()
|
|
||||||
.start_verification(tc);
|
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
@ -387,7 +383,7 @@ mod tests {
|
|||||||
let reply_header = SpHeader::new_for_unseg_tm(TEST_APID, 0, 0);
|
let reply_header = SpHeader::new_for_unseg_tm(TEST_APID, 0, 0);
|
||||||
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
|
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
|
||||||
let enable_scheduling = PusTcCreator::new(reply_header, tc_header, &[0; 7], true);
|
let enable_scheduling = PusTcCreator::new(reply_header, tc_header, &[0; 7], true);
|
||||||
let token = test_harness.start_verification(&enable_scheduling);
|
let token = test_harness.init_verification(&enable_scheduling);
|
||||||
test_harness.send_tc(&token, &enable_scheduling);
|
test_harness.send_tc(&token, &enable_scheduling);
|
||||||
|
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
@ -449,7 +445,7 @@ mod tests {
|
|||||||
&sched_app_data[..written_len],
|
&sched_app_data[..written_len],
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
let token = test_harness.start_verification(&enable_scheduling);
|
let token = test_harness.init_verification(&enable_scheduling);
|
||||||
test_harness.send_tc(&token, &enable_scheduling);
|
test_harness.send_tc(&token, &enable_scheduling);
|
||||||
|
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
|
@ -9,9 +9,8 @@ use std::sync::mpsc;
|
|||||||
|
|
||||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||||
use super::{
|
use super::{
|
||||||
EcssTcInMemConversionProvider, EcssTcInSharedPoolConverter, EcssTcInVecConverter,
|
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiver,
|
||||||
EcssTcReceiver, EcssTmSender, GenericConversionError, HandlingStatus, MpscTcReceiver,
|
EcssTmSender, GenericConversionError, HandlingStatus, MpscTcReceiver, PusServiceHelper,
|
||||||
PusServiceHelper,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
||||||
@ -19,7 +18,7 @@ use super::{
|
|||||||
pub struct PusService17TestHandler<
|
pub struct PusService17TestHandler<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> {
|
> {
|
||||||
pub service_helper:
|
pub service_helper:
|
||||||
@ -29,7 +28,7 @@ pub struct PusService17TestHandler<
|
|||||||
impl<
|
impl<
|
||||||
TcReceiver: EcssTcReceiver,
|
TcReceiver: EcssTcReceiver,
|
||||||
TmSender: EcssTmSender,
|
TmSender: EcssTmSender,
|
||||||
TcInMemConverter: EcssTcInMemConversionProvider,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> PusService17TestHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
> PusService17TestHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||||
{
|
{
|
||||||
@ -128,7 +127,7 @@ pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler<
|
|||||||
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -143,7 +142,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
DirectPusPacketHandlerResult, EcssTcInSharedPoolConverter, EcssTcInVecConverter,
|
DirectPusPacketHandlerResult, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
||||||
GenericConversionError, HandlingStatus, MpscTcReceiver, MpscTmAsVecSender,
|
GenericConversionError, HandlingStatus, MpscTcReceiver, MpscTmAsVecSender,
|
||||||
PartialPusHandlingError, PusPacketHandlingError,
|
PartialPusHandlingError, PusPacketHandlingError,
|
||||||
};
|
};
|
||||||
@ -163,7 +162,7 @@ mod tests {
|
|||||||
handler: PusService17TestHandler<
|
handler: PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
PacketSenderWithSharedPool,
|
PacketSenderWithSharedPool,
|
||||||
EcssTcInSharedPoolConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
@ -180,12 +179,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus17HandlerWithStoreTester {
|
impl PusTestHarness for Pus17HandlerWithStoreTester {
|
||||||
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
let init_token = self
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
.handler
|
|
||||||
.service_helper
|
|
||||||
.verif_reporter_mut()
|
|
||||||
.start_verification(tc);
|
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
@ -242,12 +237,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus17HandlerWithVecTester {
|
impl PusTestHarness for Pus17HandlerWithVecTester {
|
||||||
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
let init_token = self
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
.handler
|
|
||||||
.service_helper
|
|
||||||
.verif_reporter_mut()
|
|
||||||
.start_verification(tc);
|
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
@ -287,7 +278,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
@ -342,7 +333,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
|
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
@ -363,7 +354,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
|
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
||||||
let token = test_harness.start_verification(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
test_harness.send_tc(&token, &ping_tc);
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
//! tc_header,
|
//! tc_header,
|
||||||
//! true
|
//! true
|
||||||
//! );
|
//! );
|
||||||
//! let init_token = reporter.start_verification(&pus_tc_0);
|
//! let init_token = reporter.add_tc(&pus_tc_0);
|
||||||
//!
|
//!
|
||||||
//! // Complete success sequence for a telecommand
|
//! // Complete success sequence for a telecommand
|
||||||
//! let accepted_token = reporter.acceptance_success(&sender, init_token, &EMPTY_STAMP).unwrap();
|
//! let accepted_token = reporter.acceptance_success(&sender, init_token, &EMPTY_STAMP).unwrap();
|
||||||
@ -65,7 +65,8 @@
|
|||||||
//! let store_guard = rg.read_with_guard(tm_in_store.store_addr);
|
//! let store_guard = rg.read_with_guard(tm_in_store.store_addr);
|
||||||
//! tm_len = store_guard.read(&mut tm_buf).expect("Error reading TM slice");
|
//! tm_len = store_guard.read(&mut tm_buf).expect("Error reading TM slice");
|
||||||
//! }
|
//! }
|
||||||
//! let pus_tm = PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
|
//! let (pus_tm, _) = PusTmReader::new(&tm_buf[0..tm_len], 7)
|
||||||
|
//! .expect("Error reading verification TM");
|
||||||
//! if packet_idx == 0 {
|
//! if packet_idx == 0 {
|
||||||
//! assert_eq!(pus_tm.subservice(), 1);
|
//! assert_eq!(pus_tm.subservice(), 1);
|
||||||
//! } else if packet_idx == 1 {
|
//! } else if packet_idx == 1 {
|
||||||
@ -227,7 +228,7 @@ pub struct VerificationToken<STATE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<STATE> VerificationToken<STATE> {
|
impl<STATE> VerificationToken<STATE> {
|
||||||
pub fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
|
fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
|
||||||
VerificationToken {
|
VerificationToken {
|
||||||
state: PhantomData,
|
state: PhantomData,
|
||||||
request_id: req_id,
|
request_id: req_id,
|
||||||
@ -407,10 +408,14 @@ pub trait VerificationReportingProvider {
|
|||||||
fn set_apid(&mut self, apid: Apid);
|
fn set_apid(&mut self, apid: Apid);
|
||||||
fn apid(&self) -> Apid;
|
fn apid(&self) -> Apid;
|
||||||
|
|
||||||
fn start_verification(
|
fn add_tc(
|
||||||
&self,
|
&mut self,
|
||||||
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
||||||
) -> VerificationToken<TcStateNone>;
|
) -> VerificationToken<TcStateNone> {
|
||||||
|
self.add_tc_with_req_id(RequestId::new(pus_tc))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
|
||||||
|
|
||||||
fn acceptance_success(
|
fn acceptance_success(
|
||||||
&self,
|
&self,
|
||||||
@ -477,7 +482,7 @@ pub trait VerificationReportingProvider {
|
|||||||
/// the buffer passed to the API exposes by this struct will be used to serialize the source data.
|
/// the buffer passed to the API exposes by this struct will be used to serialize the source data.
|
||||||
/// This buffer may not be re-used to serialize the whole telemetry because that would overwrite
|
/// This buffer may not be re-used to serialize the whole telemetry because that would overwrite
|
||||||
/// the source data itself.
|
/// the source data itself.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct VerificationReportCreator {
|
pub struct VerificationReportCreator {
|
||||||
pub dest_id: u16,
|
pub dest_id: u16,
|
||||||
apid: u16,
|
apid: u16,
|
||||||
@ -513,15 +518,24 @@ impl VerificationReportCreator {
|
|||||||
|
|
||||||
/// Initialize verification handling by passing a TC reference. This returns a token required
|
/// Initialize verification handling by passing a TC reference. This returns a token required
|
||||||
/// to call the acceptance functions
|
/// to call the acceptance functions
|
||||||
pub fn read_request_id_from_tc(pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> RequestId {
|
pub fn add_tc(
|
||||||
RequestId::new(pus_tc)
|
&mut self,
|
||||||
|
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
||||||
|
) -> VerificationToken<TcStateNone> {
|
||||||
|
self.add_tc_with_req_id(RequestId::new(pus_tc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn success_verification_no_step<'time, 'src_data>(
|
/// Same as [Self::add_tc] but pass a request ID instead of the direct telecommand.
|
||||||
|
/// This can be useful if the executing thread does not have full access to the telecommand.
|
||||||
|
pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
|
||||||
|
VerificationToken::<TcStateNone>::new(req_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn success_verification_no_step<'time, 'src_data, State: Copy>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
request_id: &RequestId,
|
token: VerificationToken<State>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
@ -531,7 +545,7 @@ impl VerificationReportCreator {
|
|||||||
subservice,
|
subservice,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
request_id,
|
&token.request_id(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
)?;
|
)?;
|
||||||
@ -540,11 +554,11 @@ impl VerificationReportCreator {
|
|||||||
|
|
||||||
// Internal helper function, too many arguments is acceptable for this case.
|
// Internal helper function, too many arguments is acceptable for this case.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn failure_verification_no_step<'time, 'src_data>(
|
fn failure_verification_no_step<'time, 'src_data, State: Copy>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
request_id: &RequestId,
|
token: VerificationToken<State>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
step: Option<&(impl EcssEnumeration + ?Sized)>,
|
||||||
@ -555,7 +569,7 @@ impl VerificationReportCreator {
|
|||||||
subservice,
|
subservice,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
request_id,
|
&token.request_id(),
|
||||||
step,
|
step,
|
||||||
params,
|
params,
|
||||||
)?;
|
)?;
|
||||||
@ -566,27 +580,39 @@ impl VerificationReportCreator {
|
|||||||
pub fn acceptance_success<'time, 'src_data>(
|
pub fn acceptance_success<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcStateNone>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
PusTmCreator<'time, 'src_data>,
|
||||||
|
VerificationToken<TcStateAccepted>,
|
||||||
|
),
|
||||||
|
ByteConversionError,
|
||||||
|
> {
|
||||||
let tm_creator = self.success_verification_no_step(
|
let tm_creator = self.success_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmAcceptanceSuccess.into(),
|
Subservice::TmAcceptanceSuccess.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
)?;
|
)?;
|
||||||
Ok(tm_creator)
|
Ok((
|
||||||
|
tm_creator,
|
||||||
|
VerificationToken {
|
||||||
|
state: PhantomData,
|
||||||
|
request_id: token.request_id(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard.
|
/// Package a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard.
|
||||||
pub fn acceptance_failure<'time, 'src_data>(
|
pub fn acceptance_failure<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcStateNone>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
params: FailParams<'time, '_>,
|
params: FailParams<'time, '_>,
|
||||||
@ -594,7 +620,7 @@ impl VerificationReportCreator {
|
|||||||
self.failure_verification_no_step(
|
self.failure_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmAcceptanceFailure.into(),
|
Subservice::TmAcceptanceFailure.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -608,20 +634,32 @@ impl VerificationReportCreator {
|
|||||||
pub fn start_success<'time, 'src_data>(
|
pub fn start_success<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
PusTmCreator<'time, 'src_data>,
|
||||||
|
VerificationToken<TcStateStarted>,
|
||||||
|
),
|
||||||
|
ByteConversionError,
|
||||||
|
> {
|
||||||
let tm_creator = self.success_verification_no_step(
|
let tm_creator = self.success_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmStartSuccess.into(),
|
Subservice::TmStartSuccess.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
)?;
|
)?;
|
||||||
Ok(tm_creator)
|
Ok((
|
||||||
|
tm_creator,
|
||||||
|
VerificationToken {
|
||||||
|
state: PhantomData,
|
||||||
|
request_id: token.request_id(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
|
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
|
||||||
@ -631,7 +669,7 @@ impl VerificationReportCreator {
|
|||||||
pub fn start_failure<'time, 'src_data>(
|
pub fn start_failure<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
params: FailParams<'time, '_>,
|
params: FailParams<'time, '_>,
|
||||||
@ -639,7 +677,7 @@ impl VerificationReportCreator {
|
|||||||
self.failure_verification_no_step(
|
self.failure_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmStartFailure.into(),
|
Subservice::TmStartFailure.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -653,7 +691,7 @@ impl VerificationReportCreator {
|
|||||||
pub fn step_success<'time, 'src_data>(
|
pub fn step_success<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: &VerificationToken<TcStateStarted>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
@ -664,7 +702,7 @@ impl VerificationReportCreator {
|
|||||||
Subservice::TmStepSuccess.into(),
|
Subservice::TmStepSuccess.into(),
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
request_id,
|
&token.request_id(),
|
||||||
time_stamp,
|
time_stamp,
|
||||||
Some(&step),
|
Some(&step),
|
||||||
)
|
)
|
||||||
@ -697,10 +735,10 @@ impl VerificationReportCreator {
|
|||||||
///
|
///
|
||||||
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
|
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
|
||||||
/// token because verification handling is done.
|
/// token because verification handling is done.
|
||||||
pub fn completion_success<'time, 'src_data>(
|
pub fn completion_success<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcState>,
|
||||||
seq_counter: u16,
|
seq_counter: u16,
|
||||||
msg_counter: u16,
|
msg_counter: u16,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
@ -708,7 +746,7 @@ impl VerificationReportCreator {
|
|||||||
self.success_verification_no_step(
|
self.success_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmCompletionSuccess.into(),
|
Subservice::TmCompletionSuccess.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_counter,
|
seq_counter,
|
||||||
msg_counter,
|
msg_counter,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -719,10 +757,10 @@ impl VerificationReportCreator {
|
|||||||
///
|
///
|
||||||
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
|
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
|
||||||
/// token because verification handling is done.
|
/// token because verification handling is done.
|
||||||
pub fn completion_failure<'time, 'src_data>(
|
pub fn completion_failure<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
request_id: &RequestId,
|
token: VerificationToken<TcState>,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
msg_count: u16,
|
msg_count: u16,
|
||||||
params: FailParams<'time, '_>,
|
params: FailParams<'time, '_>,
|
||||||
@ -730,7 +768,7 @@ impl VerificationReportCreator {
|
|||||||
self.failure_verification_no_step(
|
self.failure_verification_no_step(
|
||||||
src_data_buf,
|
src_data_buf,
|
||||||
Subservice::TmCompletionFailure.into(),
|
Subservice::TmCompletionFailure.into(),
|
||||||
request_id,
|
token,
|
||||||
seq_count,
|
seq_count,
|
||||||
msg_count,
|
msg_count,
|
||||||
None::<&dyn EcssEnumeration>,
|
None::<&dyn EcssEnumeration>,
|
||||||
@ -948,26 +986,12 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_verification(
|
|
||||||
&self,
|
|
||||||
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
|
||||||
) -> VerificationToken<TcStateNone> {
|
|
||||||
VerificationToken::<TcStateNone>::new(
|
|
||||||
VerificationReportCreator::read_request_id_from_tc(pus_tc),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_verification_with_req_id(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
) -> VerificationToken<TcStateNone> {
|
|
||||||
VerificationToken::<TcStateNone>::new(request_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate!(
|
delegate!(
|
||||||
to self.reporter_creator {
|
to self.reporter_creator {
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool;
|
pub fn set_apid(&mut self, apid: u16) -> bool;
|
||||||
pub fn apid(&self) -> u16;
|
pub fn apid(&self) -> u16;
|
||||||
|
pub fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
|
||||||
|
pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
|
||||||
pub fn dest_id(&self) -> u16;
|
pub fn dest_id(&self) -> u16;
|
||||||
pub fn set_dest_id(&mut self, dest_id: u16);
|
pub fn set_dest_id(&mut self, dest_id: u16);
|
||||||
}
|
}
|
||||||
@ -985,16 +1009,11 @@ pub mod alloc_mod {
|
|||||||
to self.reporter_creator {
|
to self.reporter_creator {
|
||||||
fn set_apid(&mut self, apid: Apid);
|
fn set_apid(&mut self, apid: Apid);
|
||||||
fn apid(&self) -> Apid;
|
fn apid(&self) -> Apid;
|
||||||
|
fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
|
||||||
|
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
fn start_verification(
|
|
||||||
&self,
|
|
||||||
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
|
||||||
) -> VerificationToken<TcStateNone> {
|
|
||||||
VerificationToken::<TcStateNone>::new(RequestId::new(pus_tc))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn owner_id(&self) -> ComponentId {
|
fn owner_id(&self) -> ComponentId {
|
||||||
self.owner_id
|
self.owner_id
|
||||||
}
|
}
|
||||||
@ -1007,19 +1026,13 @@ pub mod alloc_mod {
|
|||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
|
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
|
||||||
let mut source_data_buf = self.source_data_buf.borrow_mut();
|
let mut source_data_buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let (mut tm_creator, token) = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.acceptance_success(
|
.acceptance_success(source_data_buf.as_mut_slice(), token, 0, 0, time_stamp)
|
||||||
source_data_buf.as_mut_slice(),
|
|
||||||
&token.request_id(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
time_stamp,
|
|
||||||
)
|
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
Ok(VerificationToken::new_accepted_state(token.request_id()))
|
Ok(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard
|
/// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard
|
||||||
@ -1032,7 +1045,7 @@ pub mod alloc_mod {
|
|||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let mut tm_creator = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.acceptance_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
|
.acceptance_failure(buf.as_mut_slice(), token, 0, 0, params)
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
@ -1049,13 +1062,13 @@ pub mod alloc_mod {
|
|||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
|
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
|
||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let (mut tm_creator, started_token) = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.start_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
|
.start_success(buf.as_mut_slice(), token, 0, 0, time_stamp)
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
Ok(VerificationToken::new_started_state(token.request_id()))
|
Ok(started_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
|
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
|
||||||
@ -1071,7 +1084,7 @@ pub mod alloc_mod {
|
|||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let mut tm_creator = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.start_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
|
.start_failure(buf.as_mut_slice(), token, 0, 0, params)
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
@ -1091,14 +1104,7 @@ pub mod alloc_mod {
|
|||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let mut tm_creator = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.step_success(
|
.step_success(buf.as_mut_slice(), token, 0, 0, time_stamp, step)
|
||||||
buf.as_mut_slice(),
|
|
||||||
&token.request_id(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
time_stamp,
|
|
||||||
step,
|
|
||||||
)
|
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
@ -1139,7 +1145,7 @@ pub mod alloc_mod {
|
|||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let mut tm_creator = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.completion_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
|
.completion_success(buf.as_mut_slice(), token, 0, 0, time_stamp)
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id, PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id, PusTmVariant::Direct(tm_creator))?;
|
||||||
@ -1159,7 +1165,7 @@ pub mod alloc_mod {
|
|||||||
let mut buf = self.source_data_buf.borrow_mut();
|
let mut buf = self.source_data_buf.borrow_mut();
|
||||||
let mut tm_creator = self
|
let mut tm_creator = self
|
||||||
.reporter_creator
|
.reporter_creator
|
||||||
.completion_failure(buf.as_mut_slice(), &token.request_id(), 0, 00, params)
|
.completion_failure(buf.as_mut_slice(), token, 0, 00, params)
|
||||||
.map_err(PusError::ByteConversion)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
self.tm_hook.modify_tm(&mut tm_creator);
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
|
||||||
@ -1356,23 +1362,22 @@ pub mod test_util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VerificationReportingProvider for TestVerificationReporter {
|
impl VerificationReportingProvider for TestVerificationReporter {
|
||||||
fn start_verification(
|
|
||||||
&self,
|
|
||||||
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
|
|
||||||
) -> VerificationToken<TcStateNone> {
|
|
||||||
let request_id = RequestId::new(pus_tc);
|
|
||||||
self.report_queue
|
|
||||||
.borrow_mut()
|
|
||||||
.push_back((request_id, VerificationReportInfo::Added));
|
|
||||||
VerificationToken::<TcStateNone>::new(RequestId::new(pus_tc))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_apid(&mut self, _apid: Apid) {}
|
fn set_apid(&mut self, _apid: Apid) {}
|
||||||
|
|
||||||
fn apid(&self) -> Apid {
|
fn apid(&self) -> Apid {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
|
||||||
|
self.report_queue
|
||||||
|
.borrow_mut()
|
||||||
|
.push_back((req_id, VerificationReportInfo::Added));
|
||||||
|
VerificationToken {
|
||||||
|
state: PhantomData,
|
||||||
|
request_id: req_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn acceptance_success(
|
fn acceptance_success(
|
||||||
&self,
|
&self,
|
||||||
_sender: &(impl EcssTmSender + ?Sized),
|
_sender: &(impl EcssTmSender + ?Sized),
|
||||||
@ -1829,16 +1834,15 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_verification(&self) -> VerificationToken<TcStateNone> {
|
|
||||||
let tc_reader = PusTcReader::new(&self.tc).unwrap();
|
|
||||||
self.reporter.start_verification(&tc_reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn set_dest_id(&mut self, dest_id: u16) {
|
fn set_dest_id(&mut self, dest_id: u16) {
|
||||||
self.reporter.set_dest_id(dest_id);
|
self.reporter.set_dest_id(dest_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init(&mut self) -> VerificationToken<TcStateNone> {
|
||||||
|
self.reporter.add_tc(&PusTcReader::new(&self.tc).unwrap().0)
|
||||||
|
}
|
||||||
|
|
||||||
fn acceptance_success(
|
fn acceptance_success(
|
||||||
&self,
|
&self,
|
||||||
token: VerificationToken<TcStateNone>,
|
token: VerificationToken<TcStateNone>,
|
||||||
@ -1916,7 +1920,7 @@ pub mod tests {
|
|||||||
additional_data: None,
|
additional_data: None,
|
||||||
};
|
};
|
||||||
let mut service_queue = self.sender.service_queue.borrow_mut();
|
let mut service_queue = self.sender.service_queue.borrow_mut();
|
||||||
assert!(!service_queue.is_empty());
|
assert!(service_queue.len() >= 1);
|
||||||
let info = service_queue.pop_front().unwrap();
|
let info = service_queue.pop_front().unwrap();
|
||||||
assert_eq!(info, cmp_info);
|
assert_eq!(info, cmp_info);
|
||||||
}
|
}
|
||||||
@ -2088,8 +2092,8 @@ pub mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_acceptance_success() {
|
fn test_basic_acceptance_success() {
|
||||||
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
testbench
|
testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("sending acceptance success failed");
|
.expect("sending acceptance success failed");
|
||||||
@ -2099,7 +2103,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_basic_acceptance_failure() {
|
fn test_basic_acceptance_failure() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let init_token = testbench.start_verification();
|
let init_token = testbench.init();
|
||||||
let timestamp = [1, 2, 3, 4, 5, 6, 7];
|
let timestamp = [1, 2, 3, 4, 5, 6, 7];
|
||||||
let fail_code = EcssEnumU16::new(2);
|
let fail_code = EcssEnumU16::new(2);
|
||||||
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
|
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
|
||||||
@ -2112,7 +2116,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_basic_acceptance_failure_with_helper() {
|
fn test_basic_acceptance_failure_with_helper() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let init_token = testbench.start_verification();
|
let init_token = testbench.init();
|
||||||
let timestamp = [1, 2, 3, 4, 5, 6, 7];
|
let timestamp = [1, 2, 3, 4, 5, 6, 7];
|
||||||
let fail_code = EcssEnumU16::new(2);
|
let fail_code = EcssEnumU16::new(2);
|
||||||
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
|
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
|
||||||
@ -2124,8 +2128,8 @@ pub mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_acceptance_fail_data_too_large() {
|
fn test_acceptance_fail_data_too_large() {
|
||||||
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8);
|
||||||
let init_token = testbench.start_verification();
|
let init_token = testbench.init();
|
||||||
let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
|
let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
|
||||||
let fail_code = EcssEnumU16::new(2);
|
let fail_code = EcssEnumU16::new(2);
|
||||||
let fail_data: [u8; 16] = [0; 16];
|
let fail_data: [u8; 16] = [0; 16];
|
||||||
@ -2156,13 +2160,13 @@ pub mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_acceptance_failure_with_fail_data() {
|
fn test_basic_acceptance_failure_with_fail_data() {
|
||||||
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let fail_code = EcssEnumU8::new(10);
|
let fail_code = EcssEnumU8::new(10);
|
||||||
let fail_data = EcssEnumU32::new(12);
|
let fail_data = EcssEnumU32::new(12);
|
||||||
let mut fail_data_raw = [0; 4];
|
let mut fail_data_raw = [0; 4];
|
||||||
fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap();
|
fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap();
|
||||||
let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice());
|
let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice());
|
||||||
let init_token = testbench.start_verification();
|
let init_token = testbench.init();
|
||||||
testbench
|
testbench
|
||||||
.acceptance_failure(init_token, fail_params)
|
.acceptance_failure(init_token, fail_params)
|
||||||
.expect("sending acceptance failure failed");
|
.expect("sending acceptance failure failed");
|
||||||
@ -2180,7 +2184,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_start_failure() {
|
fn test_start_failure() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let init_token = testbench.start_verification();
|
let init_token = testbench.init();
|
||||||
let fail_code = EcssEnumU8::new(22);
|
let fail_code = EcssEnumU8::new(22);
|
||||||
let fail_data: i32 = -12;
|
let fail_data: i32 = -12;
|
||||||
let mut fail_data_raw = [0; 4];
|
let mut fail_data_raw = [0; 4];
|
||||||
@ -2199,7 +2203,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_start_failure_with_helper() {
|
fn test_start_failure_with_helper() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let fail_code = EcssEnumU8::new(22);
|
let fail_code = EcssEnumU8::new(22);
|
||||||
let fail_data: i32 = -12;
|
let fail_data: i32 = -12;
|
||||||
let mut fail_data_raw = [0; 4];
|
let mut fail_data_raw = [0; 4];
|
||||||
@ -2218,7 +2222,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_steps_success() {
|
fn test_steps_success() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let accepted_token = testbench
|
let accepted_token = testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("acceptance failed");
|
.expect("acceptance failed");
|
||||||
@ -2241,7 +2245,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_step_failure() {
|
fn test_step_failure() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let fail_code = EcssEnumU32::new(0x1020);
|
let fail_code = EcssEnumU32::new(0x1020);
|
||||||
let fail_data: f32 = -22.3232;
|
let fail_data: f32 = -22.3232;
|
||||||
let mut fail_data_raw = [0; 4];
|
let mut fail_data_raw = [0; 4];
|
||||||
@ -2275,7 +2279,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_completion_failure() {
|
fn test_completion_failure() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let fail_code = EcssEnumU32::new(0x1020);
|
let fail_code = EcssEnumU32::new(0x1020);
|
||||||
let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code);
|
let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code);
|
||||||
|
|
||||||
@ -2298,7 +2302,7 @@ pub mod tests {
|
|||||||
fn test_complete_success_sequence() {
|
fn test_complete_success_sequence() {
|
||||||
let mut testbench =
|
let mut testbench =
|
||||||
VerificationReporterTestbench::new(TEST_COMPONENT_ID_0.id(), create_generic_ping(), 16);
|
VerificationReporterTestbench::new(TEST_COMPONENT_ID_0.id(), create_generic_ping(), 16);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let accepted_token = testbench
|
let accepted_token = testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("Sending acceptance success failed");
|
.expect("Sending acceptance success failed");
|
||||||
@ -2320,7 +2324,7 @@ pub mod tests {
|
|||||||
create_generic_ping(),
|
create_generic_ping(),
|
||||||
SequenceCounterHook::default(),
|
SequenceCounterHook::default(),
|
||||||
);
|
);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let accepted_token = testbench
|
let accepted_token = testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("Sending acceptance success failed");
|
.expect("Sending acceptance success failed");
|
||||||
@ -2338,7 +2342,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_completion_failure_helper_string_param() {
|
fn test_completion_failure_helper_string_param() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let accepted_token = testbench
|
let accepted_token = testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("Sending acceptance success failed");
|
.expect("Sending acceptance success failed");
|
||||||
@ -2365,7 +2369,7 @@ pub mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_step_failure_helper_string_param() {
|
fn test_step_failure_helper_string_param() {
|
||||||
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
|
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
|
||||||
let token = testbench.start_verification();
|
let token = testbench.init();
|
||||||
let accepted_token = testbench
|
let accepted_token = testbench
|
||||||
.acceptance_success(token, &EMPTY_STAMP)
|
.acceptance_success(token, &EMPTY_STAMP)
|
||||||
.expect("Sending acceptance success failed");
|
.expect("Sending acceptance success failed");
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
use core::fmt::{Display, Formatter};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::error::Error;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
@ -7,31 +10,89 @@ use crate::ComponentId;
|
|||||||
pub type ChannelId = u32;
|
pub type ChannelId = u32;
|
||||||
|
|
||||||
/// Generic error type for sending something via a message queue.
|
/// Generic error type for sending something via a message queue.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum GenericSendError {
|
pub enum GenericSendError {
|
||||||
#[error("rx side has disconnected")]
|
|
||||||
RxDisconnected,
|
RxDisconnected,
|
||||||
#[error("queue with max capacity of {0:?} is full")]
|
|
||||||
QueueFull(Option<u32>),
|
QueueFull(Option<u32>),
|
||||||
#[error("target queue with ID {0} does not exist")]
|
|
||||||
TargetDoesNotExist(ComponentId),
|
TargetDoesNotExist(ComponentId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for GenericSendError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
GenericSendError::RxDisconnected => {
|
||||||
|
write!(f, "rx side has disconnected")
|
||||||
|
}
|
||||||
|
GenericSendError::QueueFull(max_cap) => {
|
||||||
|
write!(f, "queue with max capacity of {max_cap:?} is full")
|
||||||
|
}
|
||||||
|
GenericSendError::TargetDoesNotExist(target) => {
|
||||||
|
write!(f, "target queue with ID {target} does not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for GenericSendError {}
|
||||||
|
|
||||||
/// Generic error type for sending something via a message queue.
|
/// Generic error type for sending something via a message queue.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum GenericReceiveError {
|
pub enum GenericReceiveError {
|
||||||
#[error("nothing to receive")]
|
|
||||||
Empty,
|
Empty,
|
||||||
#[error("tx side with id {0:?} has disconnected")]
|
|
||||||
TxDisconnected(Option<ComponentId>),
|
TxDisconnected(Option<ComponentId>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, thiserror::Error)]
|
impl Display for GenericReceiveError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::TxDisconnected(channel_id) => {
|
||||||
|
write!(f, "tx side with id {channel_id:?} has disconnected")
|
||||||
|
}
|
||||||
|
Self::Empty => {
|
||||||
|
write!(f, "nothing to receive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for GenericReceiveError {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub enum GenericTargetedMessagingError {
|
pub enum GenericTargetedMessagingError {
|
||||||
#[error("generic targeted messaging send error: {0}")]
|
Send(GenericSendError),
|
||||||
Send(#[from] GenericSendError),
|
Receive(GenericReceiveError),
|
||||||
#[error("generic targeted messaging receive error: {0}")]
|
}
|
||||||
Receive(#[from] GenericReceiveError),
|
impl From<GenericSendError> for GenericTargetedMessagingError {
|
||||||
|
fn from(value: GenericSendError) -> Self {
|
||||||
|
Self::Send(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GenericReceiveError> for GenericTargetedMessagingError {
|
||||||
|
fn from(value: GenericReceiveError) -> Self {
|
||||||
|
Self::Receive(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for GenericTargetedMessagingError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Send(err) => write!(f, "generic targeted messaging error: {}", err),
|
||||||
|
Self::Receive(err) => write!(f, "generic targeted messaging error: {}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for GenericTargetedMessagingError {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
GenericTargetedMessagingError::Send(send) => Some(send),
|
||||||
|
GenericTargetedMessagingError::Receive(receive) => Some(receive),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -13,10 +13,7 @@ use spacepackets::{
|
|||||||
ByteConversionError,
|
ByteConversionError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{queue::GenericTargetedMessagingError, ComponentId};
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
|
||||||
ComponentId,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Generic request ID type. Requests can be associated with an ID to have a unique identifier
|
/// Generic request ID type. Requests can be associated with an ID to have a unique identifier
|
||||||
/// for them. This can be useful for tasks like tracking their progress.
|
/// for them. This can be useful for tasks like tracking their progress.
|
||||||
@ -143,38 +140,37 @@ impl<Message> GenericMessage<Message> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for objects which can send targeted messages.
|
/// Generic trait for objects which can send targeted messages.
|
||||||
pub trait MessageSenderProvider<MSG>: Send {
|
pub trait MessageSender<MSG>: Send {
|
||||||
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericSendError>;
|
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic trait for objects which can receive targeted messages.
|
// Generic trait for objects which can receive targeted messages.
|
||||||
pub trait MessageReceiverProvider<MSG> {
|
pub trait MessageReceiver<MSG> {
|
||||||
fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericReceiveError>;
|
fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageWithSenderIdReceiver<Msg, Receiver: MessageReceiverProvider<Msg>>(
|
pub struct MessageWithSenderIdReceiver<MSG, R: MessageReceiver<MSG>>(pub R, PhantomData<MSG>);
|
||||||
pub Receiver,
|
|
||||||
PhantomData<Msg>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<MSG, R: MessageReceiverProvider<MSG>> From<R> for MessageWithSenderIdReceiver<MSG, R> {
|
impl<MSG, R: MessageReceiver<MSG>> From<R> for MessageWithSenderIdReceiver<MSG, R> {
|
||||||
fn from(receiver: R) -> Self {
|
fn from(receiver: R) -> Self {
|
||||||
MessageWithSenderIdReceiver(receiver, PhantomData)
|
MessageWithSenderIdReceiver(receiver, PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MSG, R: MessageReceiverProvider<MSG>> MessageWithSenderIdReceiver<MSG, R> {
|
impl<MSG, R: MessageReceiver<MSG>> MessageWithSenderIdReceiver<MSG, R> {
|
||||||
pub fn try_recv_message(&self) -> Result<Option<GenericMessage<MSG>>, GenericReceiveError> {
|
pub fn try_recv_message(
|
||||||
|
&self,
|
||||||
|
) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
|
||||||
self.0.try_recv()
|
self.0.try_recv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageReceiverWithId<MSG, R: MessageReceiverProvider<MSG>> {
|
pub struct MessageReceiverWithId<MSG, R: MessageReceiver<MSG>> {
|
||||||
local_channel_id: ComponentId,
|
local_channel_id: ComponentId,
|
||||||
reply_receiver: MessageWithSenderIdReceiver<MSG, R>,
|
reply_receiver: MessageWithSenderIdReceiver<MSG, R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MSG, R: MessageReceiverProvider<MSG>> MessageReceiverWithId<MSG, R> {
|
impl<MSG, R: MessageReceiver<MSG>> MessageReceiverWithId<MSG, R> {
|
||||||
pub fn new(local_channel_id: ComponentId, reply_receiver: R) -> Self {
|
pub fn new(local_channel_id: ComponentId, reply_receiver: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
local_channel_id,
|
local_channel_id,
|
||||||
@ -187,129 +183,43 @@ impl<MSG, R: MessageReceiverProvider<MSG>> MessageReceiverWithId<MSG, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MSG, R: MessageReceiverProvider<MSG>> MessageReceiverWithId<MSG, R> {
|
impl<MSG, R: MessageReceiver<MSG>> MessageReceiverWithId<MSG, R> {
|
||||||
pub fn try_recv_message(&self) -> Result<Option<GenericMessage<MSG>>, GenericReceiveError> {
|
pub fn try_recv_message(
|
||||||
|
&self,
|
||||||
|
) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
|
||||||
self.reply_receiver.0.try_recv()
|
self.reply_receiver.0.try_recv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MessageSenderStoreProvider<Message, Sender>: Default {
|
|
||||||
fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender);
|
|
||||||
|
|
||||||
fn send_message(
|
|
||||||
&self,
|
|
||||||
requestor_info: MessageMetadata,
|
|
||||||
target_channel_id: ComponentId,
|
|
||||||
message: Message,
|
|
||||||
) -> Result<(), GenericSendError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub mod alloc_mod {
|
pub mod alloc_mod {
|
||||||
use crate::queue::GenericSendError;
|
use crate::queue::GenericSendError;
|
||||||
use std::convert::From;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
pub struct OneMessageSender<Msg, S: MessageSenderProvider<Msg>> {
|
pub struct MessageSenderMap<MSG, S: MessageSender<MSG>>(
|
||||||
pub id_and_sender: Option<(ComponentId, S)>,
|
|
||||||
pub(crate) phantom: PhantomData<Msg>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Msg, S: MessageSenderProvider<Msg>> Default for OneMessageSender<Msg, S> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
id_and_sender: Default::default(),
|
|
||||||
phantom: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Msg, Sender: MessageSenderProvider<Msg>> MessageSenderStoreProvider<Msg, Sender>
|
|
||||||
for OneMessageSender<Msg, Sender>
|
|
||||||
{
|
|
||||||
fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) {
|
|
||||||
if self.id_and_sender.is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.id_and_sender = Some((target_id, message_sender));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_message(
|
|
||||||
&self,
|
|
||||||
requestor_info: MessageMetadata,
|
|
||||||
target_channel_id: ComponentId,
|
|
||||||
message: Msg,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
if let Some((current_id, sender)) = &self.id_and_sender {
|
|
||||||
if *current_id == target_channel_id {
|
|
||||||
sender.send(GenericMessage::new(requestor_info, message))?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(GenericSendError::TargetDoesNotExist(target_channel_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MessageSenderList<MSG, S: MessageSenderProvider<MSG>>(
|
|
||||||
pub alloc::vec::Vec<(ComponentId, S)>,
|
|
||||||
pub(crate) PhantomData<MSG>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<MSG, S: MessageSenderProvider<MSG>> Default for MessageSenderList<MSG, S> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self(Default::default(), PhantomData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Msg, Sender: MessageSenderProvider<Msg>> MessageSenderStoreProvider<Msg, Sender>
|
|
||||||
for MessageSenderList<Msg, Sender>
|
|
||||||
{
|
|
||||||
fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) {
|
|
||||||
self.0.push((target_id, message_sender));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_message(
|
|
||||||
&self,
|
|
||||||
requestor_info: MessageMetadata,
|
|
||||||
target_channel_id: ComponentId,
|
|
||||||
message: Msg,
|
|
||||||
) -> Result<(), GenericSendError> {
|
|
||||||
for (current_id, sender) in &self.0 {
|
|
||||||
if *current_id == target_channel_id {
|
|
||||||
sender.send(GenericMessage::new(requestor_info, message))?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(GenericSendError::TargetDoesNotExist(target_channel_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MessageSenderMap<MSG, S: MessageSenderProvider<MSG>>(
|
|
||||||
pub HashMap<ComponentId, S>,
|
pub HashMap<ComponentId, S>,
|
||||||
pub(crate) PhantomData<MSG>,
|
pub(crate) PhantomData<MSG>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<MSG, S: MessageSenderProvider<MSG>> Default for MessageSenderMap<MSG, S> {
|
impl<MSG, S: MessageSender<MSG>> Default for MessageSenderMap<MSG, S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(Default::default(), PhantomData)
|
Self(Default::default(), PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Msg, Sender: MessageSenderProvider<Msg>> MessageSenderStoreProvider<Msg, Sender>
|
impl<MSG, S: MessageSender<MSG>> MessageSenderMap<MSG, S> {
|
||||||
for MessageSenderMap<Msg, Sender>
|
pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
|
||||||
{
|
|
||||||
fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) {
|
|
||||||
self.0.insert(target_id, message_sender);
|
self.0.insert(target_id, message_sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_message(
|
pub fn send_message(
|
||||||
&self,
|
&self,
|
||||||
requestor_info: MessageMetadata,
|
requestor_info: MessageMetadata,
|
||||||
target_channel_id: ComponentId,
|
target_channel_id: ComponentId,
|
||||||
message: Msg,
|
message: MSG,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
if self.0.contains_key(&target_channel_id) {
|
if self.0.contains_key(&target_channel_id) {
|
||||||
return self
|
return self
|
||||||
.0
|
.0
|
||||||
@ -317,42 +227,29 @@ pub mod alloc_mod {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.send(GenericMessage::new(requestor_info, message));
|
.send(GenericMessage::new(requestor_info, message));
|
||||||
}
|
}
|
||||||
Err(GenericSendError::TargetDoesNotExist(target_channel_id))
|
Err(GenericSendError::TargetDoesNotExist(target_channel_id).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageSenderAndReceiver<
|
pub struct MessageSenderAndReceiver<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>> {
|
||||||
To,
|
|
||||||
From,
|
|
||||||
Sender: MessageSenderProvider<To>,
|
|
||||||
Receiver: MessageReceiverProvider<From>,
|
|
||||||
SenderStore: MessageSenderStoreProvider<To, Sender>,
|
|
||||||
> {
|
|
||||||
pub local_channel_id: ComponentId,
|
pub local_channel_id: ComponentId,
|
||||||
pub message_sender_store: SenderStore,
|
pub message_sender_map: MessageSenderMap<TO, S>,
|
||||||
pub message_receiver: MessageWithSenderIdReceiver<From, Receiver>,
|
pub message_receiver: MessageWithSenderIdReceiver<FROM, R>,
|
||||||
pub(crate) phantom: PhantomData<(To, Sender)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>>
|
||||||
To,
|
MessageSenderAndReceiver<TO, FROM, S, R>
|
||||||
From,
|
|
||||||
Sender: MessageSenderProvider<To>,
|
|
||||||
Receiver: MessageReceiverProvider<From>,
|
|
||||||
SenderStore: MessageSenderStoreProvider<To, Sender>,
|
|
||||||
> MessageSenderAndReceiver<To, From, Sender, Receiver, SenderStore>
|
|
||||||
{
|
{
|
||||||
pub fn new(local_channel_id: ComponentId, message_receiver: Receiver) -> Self {
|
pub fn new(local_channel_id: ComponentId, message_receiver: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
local_channel_id,
|
local_channel_id,
|
||||||
message_sender_store: Default::default(),
|
message_sender_map: Default::default(),
|
||||||
message_receiver: MessageWithSenderIdReceiver::from(message_receiver),
|
message_receiver: MessageWithSenderIdReceiver::from(message_receiver),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) {
|
pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
|
||||||
self.message_sender_store
|
self.message_sender_map
|
||||||
.add_message_target(target_id, message_sender)
|
.add_message_target(target_id, message_sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,9 +262,9 @@ pub mod alloc_mod {
|
|||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
message: To,
|
message: TO,
|
||||||
) -> Result<(), GenericSendError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_store.send_message(
|
self.message_sender_map.send_message(
|
||||||
MessageMetadata::new(request_id, self.local_channel_id_generic()),
|
MessageMetadata::new(request_id, self.local_channel_id_generic()),
|
||||||
target_id,
|
target_id,
|
||||||
message,
|
message,
|
||||||
@ -377,64 +274,48 @@ pub mod alloc_mod {
|
|||||||
/// Try to receive a message, which can be a reply or a request, depending on the generics.
|
/// Try to receive a message, which can be a reply or a request, depending on the generics.
|
||||||
pub fn try_recv_message(
|
pub fn try_recv_message(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<GenericMessage<From>>, GenericReceiveError> {
|
) -> Result<Option<GenericMessage<FROM>>, GenericTargetedMessagingError> {
|
||||||
self.message_receiver.try_recv_message()
|
self.message_receiver.try_recv_message()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RequestAndReplySenderAndReceiver<
|
pub struct RequestAndReplySenderAndReceiver<
|
||||||
Request,
|
REQUEST,
|
||||||
ReqSender: MessageSenderProvider<Request>,
|
REPLY,
|
||||||
ReqReceiver: MessageReceiverProvider<Request>,
|
S0: MessageSender<REQUEST>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<Request, ReqSender>,
|
R0: MessageReceiver<REPLY>,
|
||||||
Reply,
|
S1: MessageSender<REPLY>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
R1: MessageReceiver<REQUEST>,
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
> {
|
> {
|
||||||
pub local_channel_id: ComponentId,
|
pub local_channel_id: ComponentId,
|
||||||
// These 2 are a functional group.
|
// These 2 are a functional group.
|
||||||
pub request_sender_store: ReqSenderStore,
|
pub request_sender_map: MessageSenderMap<REQUEST, S0>,
|
||||||
pub reply_receiver: MessageWithSenderIdReceiver<Reply, ReplyReceiver>,
|
pub reply_receiver: MessageWithSenderIdReceiver<REPLY, R0>,
|
||||||
// These 2 are a functional group.
|
// These 2 are a functional group.
|
||||||
pub request_receiver: MessageWithSenderIdReceiver<Request, ReqReceiver>,
|
pub request_receiver: MessageWithSenderIdReceiver<REQUEST, R1>,
|
||||||
pub reply_sender_store: ReplySenderStore,
|
pub reply_sender_map: MessageSenderMap<REPLY, S1>,
|
||||||
phantom: PhantomData<(ReqSender, ReplySender)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
Request,
|
REQUEST,
|
||||||
ReqSender: MessageSenderProvider<Request>,
|
REPLY,
|
||||||
ReqReceiver: MessageReceiverProvider<Request>,
|
S0: MessageSender<REQUEST>,
|
||||||
ReqSenderStore: MessageSenderStoreProvider<Request, ReqSender>,
|
R0: MessageReceiver<REPLY>,
|
||||||
Reply,
|
S1: MessageSender<REPLY>,
|
||||||
ReplySender: MessageSenderProvider<Reply>,
|
R1: MessageReceiver<REQUEST>,
|
||||||
ReplyReceiver: MessageReceiverProvider<Reply>,
|
> RequestAndReplySenderAndReceiver<REQUEST, REPLY, S0, R0, S1, R1>
|
||||||
ReplySenderStore: MessageSenderStoreProvider<Reply, ReplySender>,
|
|
||||||
>
|
|
||||||
RequestAndReplySenderAndReceiver<
|
|
||||||
Request,
|
|
||||||
ReqSender,
|
|
||||||
ReqReceiver,
|
|
||||||
ReqSenderStore,
|
|
||||||
Reply,
|
|
||||||
ReplySender,
|
|
||||||
ReplyReceiver,
|
|
||||||
ReplySenderStore,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
local_channel_id: ComponentId,
|
local_channel_id: ComponentId,
|
||||||
request_receiver: ReqReceiver,
|
request_receiver: R1,
|
||||||
reply_receiver: ReplyReceiver,
|
reply_receiver: R0,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
local_channel_id,
|
local_channel_id,
|
||||||
request_receiver: request_receiver.into(),
|
request_receiver: request_receiver.into(),
|
||||||
reply_receiver: reply_receiver.into(),
|
reply_receiver: reply_receiver.into(),
|
||||||
request_sender_store: Default::default(),
|
request_sender_map: Default::default(),
|
||||||
reply_sender_store: Default::default(),
|
reply_sender_map: Default::default(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,19 +333,21 @@ pub mod std_mod {
|
|||||||
|
|
||||||
use crate::queue::{GenericReceiveError, GenericSendError};
|
use crate::queue::{GenericReceiveError, GenericSendError};
|
||||||
|
|
||||||
impl<MSG: Send> MessageSenderProvider<MSG> for mpsc::Sender<GenericMessage<MSG>> {
|
impl<MSG: Send> MessageSender<MSG> for mpsc::Sender<GenericMessage<MSG>> {
|
||||||
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericSendError> {
|
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send(message)
|
self.send(message)
|
||||||
.map_err(|_| GenericSendError::RxDisconnected)?;
|
.map_err(|_| GenericSendError::RxDisconnected)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<MSG: Send> MessageSenderProvider<MSG> for mpsc::SyncSender<GenericMessage<MSG>> {
|
impl<MSG: Send> MessageSender<MSG> for mpsc::SyncSender<GenericMessage<MSG>> {
|
||||||
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericSendError> {
|
fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError> {
|
||||||
if let Err(e) = self.try_send(message) {
|
if let Err(e) = self.try_send(message) {
|
||||||
return match e {
|
return match e {
|
||||||
mpsc::TrySendError::Full(_) => Err(GenericSendError::QueueFull(None)),
|
mpsc::TrySendError::Full(_) => Err(GenericSendError::QueueFull(None).into()),
|
||||||
mpsc::TrySendError::Disconnected(_) => Err(GenericSendError::RxDisconnected),
|
mpsc::TrySendError::Disconnected(_) => {
|
||||||
|
Err(GenericSendError::RxDisconnected.into())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -474,14 +357,14 @@ pub mod std_mod {
|
|||||||
pub type MessageSenderMapMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::Sender<MSG>>;
|
pub type MessageSenderMapMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::Sender<MSG>>;
|
||||||
pub type MessageSenderMapBoundedMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::SyncSender<MSG>>;
|
pub type MessageSenderMapBoundedMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::SyncSender<MSG>>;
|
||||||
|
|
||||||
impl<MSG> MessageReceiverProvider<MSG> for mpsc::Receiver<GenericMessage<MSG>> {
|
impl<MSG> MessageReceiver<MSG> for mpsc::Receiver<GenericMessage<MSG>> {
|
||||||
fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericReceiveError> {
|
fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
|
||||||
match self.try_recv() {
|
match self.try_recv() {
|
||||||
Ok(msg) => Ok(Some(msg)),
|
Ok(msg) => Ok(Some(msg)),
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
mpsc::TryRecvError::Empty => Ok(None),
|
mpsc::TryRecvError::Empty => Ok(None),
|
||||||
mpsc::TryRecvError::Disconnected => {
|
mpsc::TryRecvError::Disconnected => {
|
||||||
Err(GenericReceiveError::TxDisconnected(None))
|
Err(GenericReceiveError::TxDisconnected(None).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -502,8 +385,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError},
|
||||||
request::{MessageMetadata, MessageSenderMap, MessageSenderStoreProvider},
|
request::{MessageMetadata, MessageSenderMap},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
|
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
|
||||||
@ -595,7 +478,9 @@ mod tests {
|
|||||||
let reply = receiver.try_recv_message();
|
let reply = receiver.try_recv_message();
|
||||||
assert!(reply.is_err());
|
assert!(reply.is_err());
|
||||||
let error = reply.unwrap_err();
|
let error = reply.unwrap_err();
|
||||||
if let GenericReceiveError::TxDisconnected(None) = error {
|
if let GenericTargetedMessagingError::Receive(GenericReceiveError::TxDisconnected(None)) =
|
||||||
|
error
|
||||||
|
{
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected error type");
|
panic!("unexpected error type");
|
||||||
}
|
}
|
||||||
@ -644,7 +529,9 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericSendError::TargetDoesNotExist(target) = error {
|
if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) =
|
||||||
|
error
|
||||||
|
{
|
||||||
assert_eq!(target, TEST_CHANNEL_ID_2);
|
assert_eq!(target, TEST_CHANNEL_ID_2);
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected error type");
|
panic!("Unexpected error type");
|
||||||
@ -669,7 +556,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericSendError::QueueFull(capacity) = error {
|
if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error {
|
||||||
assert!(capacity.is_none());
|
assert!(capacity.is_none());
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected error type {}", error);
|
panic!("Unexpected error type {}", error);
|
||||||
@ -689,7 +576,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericSendError::RxDisconnected = error {
|
if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error {
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected error type {}", error);
|
panic!("Unexpected error type {}", error);
|
||||||
}
|
}
|
||||||
|
@ -1,416 +0,0 @@
|
|||||||
use core::{convert::Infallible, fmt::Debug, time::Duration};
|
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::executable::Executable;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std_mod::*;
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct SchedulingTable {
|
|
||||||
execution_frequency: Duration,
|
|
||||||
pub table: alloc::vec::Vec<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum InvalidSlotError {
|
|
||||||
#[error("slot time is larger than the execution frequency")]
|
|
||||||
SlotTimeLargerThanFrequency,
|
|
||||||
#[error("slot time is smaller than previous slot")]
|
|
||||||
SmallerThanPreviousSlot {
|
|
||||||
slot_time_ms: u32,
|
|
||||||
prev_slot_time_ms: u32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SchedulingTable {
|
|
||||||
pub fn new(execution_frequency: Duration) -> Self {
|
|
||||||
Self {
|
|
||||||
execution_frequency,
|
|
||||||
table: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_slot(&mut self, relative_execution_time_ms: u32) -> Result<(), InvalidSlotError> {
|
|
||||||
if relative_execution_time_ms > self.execution_frequency.as_millis() as u32 {
|
|
||||||
return Err(InvalidSlotError::SlotTimeLargerThanFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.table.is_empty() {
|
|
||||||
let prev_slot_ms = *self.table.last().unwrap();
|
|
||||||
if relative_execution_time_ms < prev_slot_ms {
|
|
||||||
return Err(InvalidSlotError::SmallerThanPreviousSlot {
|
|
||||||
slot_time_ms: relative_execution_time_ms,
|
|
||||||
prev_slot_time_ms: *self.table.last().unwrap(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.table.push(relative_execution_time_ms);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum TaskWithSchedulingTableError {
|
|
||||||
#[error("scheudlig table error: {0}")]
|
|
||||||
InvalidSlot(#[from] InvalidSlotError),
|
|
||||||
#[error("task lock error")]
|
|
||||||
LockError,
|
|
||||||
#[error("task borrow error")]
|
|
||||||
BorrowError,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DeadlineMissedHandler {
|
|
||||||
fn deadline_missed_callback(&mut self, task_name: &'static str, op_code: i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait TaskExecutor {
|
|
||||||
fn with_task<F: FnOnce(&mut dyn Executable<Error = Infallible>)>(&self, f: F);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub mod std_mod {
|
|
||||||
use core::cell::RefCell;
|
|
||||||
use std::{
|
|
||||||
rc::Rc,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
impl TaskExecutor for Arc<Mutex<dyn Executable<Error = Infallible> + Send>> {
|
|
||||||
fn with_task<F: FnOnce(&mut dyn Executable<Error = Infallible>)>(&self, f: F) {
|
|
||||||
let mut task = self.lock().unwrap();
|
|
||||||
f(&mut *task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaskExecutor for Rc<RefCell<dyn Executable<Error = Infallible>>> {
|
|
||||||
fn with_task<F: FnOnce(&mut dyn Executable<Error = Infallible>)>(&self, f: F) {
|
|
||||||
let mut task = self.borrow_mut();
|
|
||||||
f(&mut *task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TaskWithOpCode<T: TaskExecutor> {
|
|
||||||
task: T,
|
|
||||||
op_code: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TaskWithSchedulingTable<T: TaskExecutor> {
|
|
||||||
start_of_slot: Instant,
|
|
||||||
end_of_slot: Instant,
|
|
||||||
deadline_missed_ms_count: u32,
|
|
||||||
table: SchedulingTable,
|
|
||||||
tasks: Vec<TaskWithOpCode<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaskWithSchedulingTable<Rc<RefCell<dyn Executable<Error = Infallible>>>> {
|
|
||||||
/// Add a new task to the scheduling table
|
|
||||||
///
|
|
||||||
/// The task needs to be wrapped inside [Rc] and [RefCell]. The task is not sendable and
|
|
||||||
/// needs to be created inside the target thread.
|
|
||||||
pub fn add_task(
|
|
||||||
&mut self,
|
|
||||||
relative_execution_time_ms: u32,
|
|
||||||
task: Rc<RefCell<dyn Executable<Error = Infallible>>>,
|
|
||||||
op_code: i32,
|
|
||||||
) -> Result<(), TaskWithSchedulingTableError> {
|
|
||||||
self.table.add_slot(relative_execution_time_ms)?;
|
|
||||||
self.tasks.push(TaskWithOpCode { task, op_code });
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaskWithSchedulingTable<Arc<Mutex<dyn Executable<Error = Infallible> + Send>>> {
|
|
||||||
/// Add a new task to the scheduling table
|
|
||||||
///
|
|
||||||
/// The task needs to be wrapped inside [Arc] and [Mutex], but the task can be sent to
|
|
||||||
/// a different thread.
|
|
||||||
pub fn add_task_sendable(
|
|
||||||
&mut self,
|
|
||||||
relative_execution_time_ms: u32,
|
|
||||||
task: Arc<Mutex<dyn Executable<Error = Infallible> + Send>>,
|
|
||||||
op_code: i32,
|
|
||||||
) -> Result<(), TaskWithSchedulingTableError> {
|
|
||||||
self.table.add_slot(relative_execution_time_ms)?;
|
|
||||||
self.tasks.push(TaskWithOpCode { task, op_code });
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: TaskExecutor> TaskWithSchedulingTable<T> {
|
|
||||||
pub fn new(execution_frequency: Duration) -> Self {
|
|
||||||
Self {
|
|
||||||
start_of_slot: Instant::now(),
|
|
||||||
end_of_slot: Instant::now(),
|
|
||||||
deadline_missed_ms_count: 10,
|
|
||||||
table: SchedulingTable::new(execution_frequency),
|
|
||||||
tasks: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to set the start of the slot to the current time. This is useful if a custom
|
|
||||||
/// runner implementation is used instead of the [Self::run_one_task_cycle] method.
|
|
||||||
pub fn init_start_of_slot(&mut self) {
|
|
||||||
self.start_of_slot = Instant::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_one_task_cycle(
|
|
||||||
&mut self,
|
|
||||||
deadline_missed_cb: &mut impl DeadlineMissedHandler,
|
|
||||||
) -> Result<(), TaskWithSchedulingTableError> {
|
|
||||||
self.end_of_slot = self.start_of_slot + self.table.execution_frequency;
|
|
||||||
|
|
||||||
for (&relative_execution_time_ms, task_with_op_code) in
|
|
||||||
self.table.table.iter().zip(self.tasks.iter_mut())
|
|
||||||
{
|
|
||||||
let scheduled_execution_time = self.start_of_slot
|
|
||||||
+ core::time::Duration::from_millis(relative_execution_time_ms as u64);
|
|
||||||
let now = Instant::now();
|
|
||||||
|
|
||||||
if now < scheduled_execution_time {
|
|
||||||
std::thread::sleep(scheduled_execution_time - now);
|
|
||||||
} else if (now - scheduled_execution_time).as_millis()
|
|
||||||
> self.deadline_missed_ms_count.into()
|
|
||||||
{
|
|
||||||
task_with_op_code.task.with_task(|task| {
|
|
||||||
deadline_missed_cb
|
|
||||||
.deadline_missed_callback(task.task_name(), task_with_op_code.op_code);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
task_with_op_code.task.with_task(|task| {
|
|
||||||
// Unwrapping is okay here because we constrain the tasks to be infallible.
|
|
||||||
task.periodic_op(task_with_op_code.op_code).unwrap();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let now = Instant::now();
|
|
||||||
if now <= self.end_of_slot {
|
|
||||||
let diff = self.end_of_slot - now;
|
|
||||||
std::thread::sleep(diff);
|
|
||||||
self.start_of_slot = self.end_of_slot;
|
|
||||||
} else if now > self.end_of_slot + self.table.execution_frequency {
|
|
||||||
// We're getting strongly out of sync. Set the new start timt to now.
|
|
||||||
self.start_of_slot = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use core::{cell::RefCell, convert::Infallible, time::Duration};
|
|
||||||
use std::{
|
|
||||||
println,
|
|
||||||
rc::Rc,
|
|
||||||
sync::{
|
|
||||||
mpsc::{self, TryRecvError},
|
|
||||||
Arc, Mutex,
|
|
||||||
},
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::executable::{Executable, OpResult};
|
|
||||||
|
|
||||||
use super::{DeadlineMissedHandler, TaskWithSchedulingTable};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CallInfo {
|
|
||||||
time: std::time::Instant,
|
|
||||||
op_code: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Task1 {
|
|
||||||
called_queue: mpsc::Sender<CallInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executable for Task1 {
|
|
||||||
type Error = Infallible;
|
|
||||||
fn task_name(&self) -> &'static str {
|
|
||||||
"Task1"
|
|
||||||
}
|
|
||||||
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error> {
|
|
||||||
self.called_queue
|
|
||||||
.send(CallInfo {
|
|
||||||
time: Instant::now(),
|
|
||||||
op_code,
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
Ok(OpResult::Ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Task2 {
|
|
||||||
called_queue: mpsc::Sender<CallInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executable for Task2 {
|
|
||||||
type Error = Infallible;
|
|
||||||
fn task_name(&self) -> &'static str {
|
|
||||||
"Task2"
|
|
||||||
}
|
|
||||||
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error> {
|
|
||||||
self.called_queue
|
|
||||||
.send(CallInfo {
|
|
||||||
time: Instant::now(),
|
|
||||||
op_code,
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
Ok(OpResult::Ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct DeadlineMissed {
|
|
||||||
call_count: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DeadlineMissedHandler for DeadlineMissed {
|
|
||||||
fn deadline_missed_callback(&mut self, task_name: &'static str, _op_code: i32) {
|
|
||||||
println!("task name {task_name} missed the deadline");
|
|
||||||
self.call_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn basic_test() {
|
|
||||||
let (tx_t1, rx_t1) = mpsc::channel();
|
|
||||||
let (tx_t2, rx_t2) = mpsc::channel();
|
|
||||||
let t1 = Task1 {
|
|
||||||
called_queue: tx_t1,
|
|
||||||
};
|
|
||||||
let t2 = Task2 {
|
|
||||||
called_queue: tx_t2,
|
|
||||||
};
|
|
||||||
let mut deadline_missed_cb = DeadlineMissed::default();
|
|
||||||
let mut exec_task = TaskWithSchedulingTable::new(Duration::from_millis(200));
|
|
||||||
let t1_first_slot = Rc::new(RefCell::new(t1));
|
|
||||||
let t1_second_slot = t1_first_slot.clone();
|
|
||||||
let t2_first_slot = Rc::new(RefCell::new(t2));
|
|
||||||
let t2_second_slot = t2_first_slot.clone();
|
|
||||||
|
|
||||||
exec_task.add_task(0, t1_first_slot, 0).unwrap();
|
|
||||||
exec_task.add_task(50, t1_second_slot, -1).unwrap();
|
|
||||||
exec_task.add_task(100, t2_first_slot, 1).unwrap();
|
|
||||||
exec_task.add_task(150, t2_second_slot, 2).unwrap();
|
|
||||||
let now = Instant::now();
|
|
||||||
exec_task.init_start_of_slot();
|
|
||||||
exec_task
|
|
||||||
.run_one_task_cycle(&mut deadline_missed_cb)
|
|
||||||
.unwrap();
|
|
||||||
let mut call_info = rx_t1.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 0);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 30);
|
|
||||||
call_info = rx_t1.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, -1);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 80);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 50);
|
|
||||||
matches!(rx_t1.try_recv().unwrap_err(), TryRecvError::Empty);
|
|
||||||
|
|
||||||
call_info = rx_t2.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 1);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 120);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 100);
|
|
||||||
call_info = rx_t2.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 2);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 180);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 150);
|
|
||||||
matches!(rx_t2.try_recv().unwrap_err(), TryRecvError::Empty);
|
|
||||||
assert_eq!(deadline_missed_cb.call_count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn basic_test_with_arc_mutex() {
|
|
||||||
let (tx_t1, rx_t1) = mpsc::channel();
|
|
||||||
let (tx_t2, rx_t2) = mpsc::channel();
|
|
||||||
let t1 = Task1 {
|
|
||||||
called_queue: tx_t1,
|
|
||||||
};
|
|
||||||
let t2 = Task2 {
|
|
||||||
called_queue: tx_t2,
|
|
||||||
};
|
|
||||||
let mut deadline_missed_cb = DeadlineMissed::default();
|
|
||||||
let mut exec_task = TaskWithSchedulingTable::new(Duration::from_millis(200));
|
|
||||||
let t1_first_slot = Arc::new(Mutex::new(t1));
|
|
||||||
let t1_second_slot = t1_first_slot.clone();
|
|
||||||
let t2_first_slot = Arc::new(Mutex::new(t2));
|
|
||||||
let t2_second_slot = t2_first_slot.clone();
|
|
||||||
|
|
||||||
exec_task.add_task_sendable(0, t1_first_slot, 0).unwrap();
|
|
||||||
exec_task.add_task_sendable(50, t1_second_slot, -1).unwrap();
|
|
||||||
exec_task.add_task_sendable(100, t2_first_slot, 1).unwrap();
|
|
||||||
exec_task.add_task_sendable(150, t2_second_slot, 2).unwrap();
|
|
||||||
let now = Instant::now();
|
|
||||||
exec_task.init_start_of_slot();
|
|
||||||
exec_task
|
|
||||||
.run_one_task_cycle(&mut deadline_missed_cb)
|
|
||||||
.unwrap();
|
|
||||||
let mut call_info = rx_t1.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 0);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 30);
|
|
||||||
call_info = rx_t1.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, -1);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 80);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 50);
|
|
||||||
matches!(rx_t1.try_recv().unwrap_err(), TryRecvError::Empty);
|
|
||||||
|
|
||||||
call_info = rx_t2.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 1);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 120);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 100);
|
|
||||||
call_info = rx_t2.try_recv().unwrap();
|
|
||||||
assert_eq!(call_info.op_code, 2);
|
|
||||||
let diff_call_to_start = call_info.time - now;
|
|
||||||
assert!(diff_call_to_start.as_millis() < 180);
|
|
||||||
assert!(diff_call_to_start.as_millis() >= 150);
|
|
||||||
matches!(rx_t2.try_recv().unwrap_err(), TryRecvError::Empty);
|
|
||||||
assert_eq!(deadline_missed_cb.call_count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn basic_test_in_thread() {
|
|
||||||
let mut deadline_missed_cb = DeadlineMissed::default();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
let (tx_t1, _rx_t1) = mpsc::channel();
|
|
||||||
let t1 = Task1 {
|
|
||||||
called_queue: tx_t1,
|
|
||||||
};
|
|
||||||
// Need to construct this in the thread, the task table in not [Send]
|
|
||||||
let mut exec_task = TaskWithSchedulingTable::new(Duration::from_millis(200));
|
|
||||||
let t1_wrapper = Rc::new(RefCell::new(t1));
|
|
||||||
exec_task.add_task(0, t1_wrapper, 0).unwrap();
|
|
||||||
exec_task
|
|
||||||
.run_one_task_cycle(&mut deadline_missed_cb)
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut deadline_missed_cb = DeadlineMissed::default();
|
|
||||||
let (tx_t1, _rx_t1) = mpsc::channel();
|
|
||||||
let t1 = Task1 {
|
|
||||||
called_queue: tx_t1,
|
|
||||||
};
|
|
||||||
let mut exec_task_sendable = TaskWithSchedulingTable::new(Duration::from_millis(200));
|
|
||||||
exec_task_sendable
|
|
||||||
.add_task_sendable(0, Arc::new(Mutex::new(t1)), 1)
|
|
||||||
.unwrap();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
exec_task_sendable
|
|
||||||
.run_one_task_cycle(&mut deadline_missed_cb)
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use alloc_mod::*;
|
pub use alloc_mod::*;
|
||||||
use core::fmt::Debug;
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
@ -171,7 +170,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper trait for any generic (static) store which allows storing raw or CCSDS packets.
|
/// Helper trait for any generic (static) store which allows storing raw or CCSDS packets.
|
||||||
pub trait CcsdsPacketPool: Debug {
|
pub trait CcsdsPacketPool {
|
||||||
fn add_ccsds_tc(&mut self, _: &SpHeader, tc_raw: &[u8]) -> Result<PoolAddr, PoolError> {
|
fn add_ccsds_tc(&mut self, _: &SpHeader, tc_raw: &[u8]) -> Result<PoolAddr, PoolError> {
|
||||||
self.add_raw_tc(tc_raw)
|
self.add_raw_tc(tc_raw)
|
||||||
}
|
}
|
||||||
@ -191,7 +190,7 @@ pub trait PusTmPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for any sender component able to send packets stored inside a pool structure.
|
/// Generic trait for any sender component able to send packets stored inside a pool structure.
|
||||||
pub trait PacketInPoolSender: Debug + Send {
|
pub trait PacketInPoolSender: Send {
|
||||||
fn send_packet(
|
fn send_packet(
|
||||||
&self,
|
&self,
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
@ -236,7 +235,7 @@ pub mod std_mod {
|
|||||||
|
|
||||||
/// Newtype wrapper around the [SharedStaticMemoryPool] to enable extension helper traits on
|
/// Newtype wrapper around the [SharedStaticMemoryPool] to enable extension helper traits on
|
||||||
/// top of the regular shared memory pool API.
|
/// top of the regular shared memory pool API.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SharedPacketPool(pub SharedStaticMemoryPool);
|
pub struct SharedPacketPool(pub SharedStaticMemoryPool);
|
||||||
|
|
||||||
impl SharedPacketPool {
|
impl SharedPacketPool {
|
||||||
@ -288,6 +287,7 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl PacketSenderRaw for mpsc::Sender<PacketAsVec> {
|
impl PacketSenderRaw for mpsc::Sender<PacketAsVec> {
|
||||||
type Error = GenericSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
@ -297,6 +297,7 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl PacketSenderRaw for mpsc::SyncSender<PacketAsVec> {
|
impl PacketSenderRaw for mpsc::SyncSender<PacketAsVec> {
|
||||||
type Error = GenericSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
@ -361,7 +362,7 @@ pub mod std_mod {
|
|||||||
|
|
||||||
/// This is the primary structure used to send packets stored in a dedicated memory pool
|
/// This is the primary structure used to send packets stored in a dedicated memory pool
|
||||||
/// structure.
|
/// structure.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PacketSenderWithSharedPool<
|
pub struct PacketSenderWithSharedPool<
|
||||||
Sender: PacketInPoolSender = mpsc::SyncSender<PacketInPool>,
|
Sender: PacketInPoolSender = mpsc::SyncSender<PacketInPool>,
|
||||||
PacketPool: CcsdsPacketPool = SharedPacketPool,
|
PacketPool: CcsdsPacketPool = SharedPacketPool,
|
||||||
|
@ -17,37 +17,37 @@ impl PusTmWithCdsShortHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn create_pus_tm_timestamp_now<'data>(
|
pub fn create_pus_tm_timestamp_now<'a>(
|
||||||
&mut self,
|
&'a mut self,
|
||||||
service: u8,
|
service: u8,
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
source_data: &'data [u8],
|
source_data: &'a [u8],
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
) -> PusTmCreator<'_, 'data> {
|
) -> PusTmCreator {
|
||||||
let time_stamp = CdsTime::now_with_u16_days().unwrap();
|
let time_stamp = CdsTime::now_with_u16_days().unwrap();
|
||||||
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
||||||
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_pus_tm_with_stamper<'data>(
|
pub fn create_pus_tm_with_stamper<'a>(
|
||||||
&mut self,
|
&'a mut self,
|
||||||
service: u8,
|
service: u8,
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
source_data: &'data [u8],
|
source_data: &'a [u8],
|
||||||
stamper: &CdsTime,
|
stamper: &CdsTime,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
) -> PusTmCreator<'_, 'data> {
|
) -> PusTmCreator {
|
||||||
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
||||||
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_pus_tm_common<'data>(
|
fn create_pus_tm_common<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
service: u8,
|
service: u8,
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
source_data: &'data [u8],
|
source_data: &'a [u8],
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
) -> PusTmCreator<'_, 'data> {
|
) -> PusTmCreator {
|
||||||
let reply_header = SpHeader::new_for_unseg_tm(self.apid, seq_count, 0);
|
let reply_header = SpHeader::new_for_unseg_tm(self.apid, seq_count, 0);
|
||||||
let tc_header = PusTmSecondaryHeader::new_simple(service, subservice, &self.cds_short_buf);
|
let tc_header = PusTmSecondaryHeader::new_simple(service, subservice, &self.cds_short_buf);
|
||||||
PusTmCreator::new(reply_header, tc_header, source_data, true)
|
PusTmCreator::new(reply_header, tc_header, source_data, true)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@ use satrs::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
|
|||||||
use satrs::params::U32Pair;
|
use satrs::params::U32Pair;
|
||||||
use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
|
use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
|
||||||
use satrs::pus::event_man::{DefaultPusEventReportingMap, EventReporter, PusEventTmCreatorWithMap};
|
use satrs::pus::event_man::{DefaultPusEventReportingMap, EventReporter, PusEventTmCreatorWithMap};
|
||||||
|
use satrs::pus::test_util::TEST_COMPONENT_ID_0;
|
||||||
use satrs::request::UniqueApidTargetId;
|
use satrs::request::UniqueApidTargetId;
|
||||||
use satrs::tmtc::PacketAsVec;
|
use satrs::tmtc::PacketAsVec;
|
||||||
use spacepackets::ecss::tm::PusTmReader;
|
use spacepackets::ecss::tm::PusTmReader;
|
||||||
@ -99,7 +100,10 @@ fn test_threaded_usage() {
|
|||||||
// Event sender and TM checker thread
|
// Event sender and TM checker thread
|
||||||
let jh1 = thread::spawn(move || {
|
let jh1 = thread::spawn(move || {
|
||||||
event_tx
|
event_tx
|
||||||
.send(EventMessage::new(TEST_ID.id(), INFO_EVENT.into()))
|
.send(EventMessage::new(
|
||||||
|
TEST_COMPONENT_ID_0.id(),
|
||||||
|
INFO_EVENT.into(),
|
||||||
|
))
|
||||||
.expect("Sending info event failed");
|
.expect("Sending info event failed");
|
||||||
loop {
|
loop {
|
||||||
match event_packet_rx.try_recv() {
|
match event_packet_rx.try_recv() {
|
||||||
@ -107,9 +111,9 @@ fn test_threaded_usage() {
|
|||||||
Ok(event_tm) => {
|
Ok(event_tm) => {
|
||||||
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
||||||
.expect("Deserializing TM failed");
|
.expect("Deserializing TM failed");
|
||||||
assert_eq!(tm.service(), 5);
|
assert_eq!(tm.0.service(), 5);
|
||||||
assert_eq!(tm.subservice(), 1);
|
assert_eq!(tm.0.subservice(), 1);
|
||||||
let src_data = tm.source_data();
|
let src_data = tm.0.source_data();
|
||||||
assert!(!src_data.is_empty());
|
assert!(!src_data.is_empty());
|
||||||
assert_eq!(src_data.len(), 4);
|
assert_eq!(src_data.len(), 4);
|
||||||
let event =
|
let event =
|
||||||
@ -126,7 +130,7 @@ fn test_threaded_usage() {
|
|||||||
}
|
}
|
||||||
event_tx
|
event_tx
|
||||||
.send(EventMessage::new_with_params(
|
.send(EventMessage::new_with_params(
|
||||||
TEST_ID.id(),
|
TEST_COMPONENT_ID_0.id(),
|
||||||
LOW_SEV_EVENT,
|
LOW_SEV_EVENT,
|
||||||
&Params::Heapless((2_u32, 3_u32).into()),
|
&Params::Heapless((2_u32, 3_u32).into()),
|
||||||
))
|
))
|
||||||
@ -137,9 +141,9 @@ fn test_threaded_usage() {
|
|||||||
Ok(event_tm) => {
|
Ok(event_tm) => {
|
||||||
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
||||||
.expect("Deserializing TM failed");
|
.expect("Deserializing TM failed");
|
||||||
assert_eq!(tm.service(), 5);
|
assert_eq!(tm.0.service(), 5);
|
||||||
assert_eq!(tm.subservice(), 2);
|
assert_eq!(tm.0.subservice(), 2);
|
||||||
let src_data = tm.source_data();
|
let src_data = tm.0.source_data();
|
||||||
assert!(!src_data.is_empty());
|
assert!(!src_data.is_empty());
|
||||||
assert_eq!(src_data.len(), 12);
|
assert_eq!(src_data.len(), 12);
|
||||||
let event =
|
let event =
|
||||||
|
@ -89,9 +89,9 @@ pub mod crossbeam_test {
|
|||||||
let pg = tc_guard.read_with_guard(tc_addr);
|
let pg = tc_guard.read_with_guard(tc_addr);
|
||||||
tc_len = pg.read(&mut tc_buf).unwrap();
|
tc_len = pg.read(&mut tc_buf).unwrap();
|
||||||
}
|
}
|
||||||
let _tc = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
let (_tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
||||||
|
|
||||||
let token = reporter_with_sender_0.start_verification_with_req_id(req_id_0);
|
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
|
||||||
let accepted_token = reporter_with_sender_0
|
let accepted_token = reporter_with_sender_0
|
||||||
.acceptance_success(&sender, token, &FIXED_STAMP)
|
.acceptance_success(&sender, token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
@ -125,8 +125,8 @@ pub mod crossbeam_test {
|
|||||||
let pg = tc_guard.read_with_guard(tc_addr);
|
let pg = tc_guard.read_with_guard(tc_addr);
|
||||||
tc_len = pg.read(&mut tc_buf).unwrap();
|
tc_len = pg.read(&mut tc_buf).unwrap();
|
||||||
}
|
}
|
||||||
let tc = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
||||||
let token = reporter_with_sender_1.start_verification(&tc);
|
let token = reporter_with_sender_1.add_tc(&tc);
|
||||||
let accepted_token = reporter_with_sender_1
|
let accepted_token = reporter_with_sender_1
|
||||||
.acceptance_success(&sender_1, token, &FIXED_STAMP)
|
.acceptance_success(&sender_1, token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
@ -156,7 +156,7 @@ pub mod crossbeam_test {
|
|||||||
.read(&mut tm_buf)
|
.read(&mut tm_buf)
|
||||||
.expect("Error reading TM slice");
|
.expect("Error reading TM slice");
|
||||||
}
|
}
|
||||||
let pus_tm =
|
let (pus_tm, _) =
|
||||||
PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
|
PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
|
||||||
let req_id =
|
let req_id =
|
||||||
RequestId::from_bytes(&pus_tm.source_data()[0..RequestId::SIZE_AS_BYTES])
|
RequestId::from_bytes(&pus_tm.source_data()[0..RequestId::SIZE_AS_BYTES])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user