Compare commits

..

2 Commits

Author SHA1 Message Date
Robin Mueller
45a99cabce bump spacepackets 2025-09-11 09:29:34 +02:00
Robin Mueller
ab44e3312c update all the code 2025-09-10 19:01:44 +02:00
42 changed files with 1424 additions and 1721 deletions

View File

@@ -3,21 +3,12 @@
version = 4
[[package]]
name = "aligned"
version = "0.4.2"
name = "accelerometer"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923"
checksum = "1a4586d95cb0695e748760c9a751141eebb68265b1b20392a0f14db608679f7a"
dependencies = [
"as-slice",
]
[[package]]
name = "as-slice"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"
dependencies = [
"stable_deref_trait",
"micromath",
]
[[package]]
@@ -32,7 +23,7 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [
"rustc_version",
"rustc_version 0.2.3",
]
[[package]]
@@ -41,12 +32,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
[[package]]
name = "bit_field"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
[[package]]
name = "bitfield"
version = "0.13.2"
@@ -60,18 +45,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.4"
name = "bxcan"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "block-device-driver"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e"
checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80"
dependencies = [
"aligned",
"bitflags",
"embedded-hal 0.2.7",
"nb 1.1.0",
"vcell",
]
[[package]]
@@ -80,6 +62,15 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cast"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
dependencies = [
"rustc_version 0.4.1",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -87,10 +78,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cobs"
version = "0.4.0"
name = "chrono"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea6d1b751c55bd9c0dda7d4ff752074e98f4765ae969664648bd193bb326d15"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"num-traits",
]
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror",
]
@@ -194,19 +200,29 @@ dependencies = [
[[package]]
name = "defmt"
version = "1.0.1"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78"
checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130"
dependencies = [
"bitflags 1.3.2",
"bitflags",
"defmt-macros",
]
[[package]]
name = "defmt-macros"
version = "1.0.1"
name = "defmt-brtt"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e"
checksum = "c2f0ac3635d0c89d12b8101fcb44a7625f5f030a1c0491124b74467eb5a58a78"
dependencies = [
"critical-section",
"defmt",
]
[[package]]
name = "defmt-macros"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6"
dependencies = [
"defmt-parser",
"proc-macro-error2",
@@ -217,28 +233,18 @@ dependencies = [
[[package]]
name = "defmt-parser"
version = "1.0.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3"
dependencies = [
"thiserror",
]
[[package]]
name = "defmt-rtt"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2cac3b8a5644a9e02b75085ebad3b6deafdbdbdec04bb25086523828aa4dfd1"
dependencies = [
"critical-section",
"defmt",
]
[[package]]
name = "defmt-test"
version = "0.4.0"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24076cc7203c365e7febfcec15d6667a9ef780bd2c5fd3b2a197400df78f299b"
checksum = "290966e8c38f94b11884877242de876280d0eab934900e9642d58868e77c5df1"
dependencies = [
"cortex-m-rt",
"cortex-m-semihosting",
@@ -248,9 +254,9 @@ dependencies = [
[[package]]
name = "defmt-test-macros"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe5520fd36862f281c026abeaab153ebbc001717c29a9b8e5ba9704d8f3a879d"
checksum = "984bc6eca246389726ac2826acc2488ca0fe5fcd6b8d9b48797021951d76a125"
dependencies = [
"proc-macro2",
"quote",
@@ -280,140 +286,12 @@ dependencies = [
]
[[package]]
name = "document-features"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
dependencies = [
"litrs",
]
[[package]]
name = "embassy-embedded-hal"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8"
dependencies = [
"embassy-futures",
"embassy-hal-internal",
"embassy-sync",
"embedded-hal 0.2.7",
"embedded-hal 1.0.0",
"embedded-hal-async",
"embedded-storage",
"embedded-storage-async",
"nb 1.1.0",
]
[[package]]
name = "embassy-futures"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01"
[[package]]
name = "embassy-hal-internal"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a"
dependencies = [
"cortex-m",
"critical-section",
"num-traits",
]
[[package]]
name = "embassy-net-driver"
name = "embedded-dma"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d"
[[package]]
name = "embassy-stm32"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d972eab325cc96afee98f80a91ca6b00249b6356dc0fdbff68b70c200df9fae"
checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446"
dependencies = [
"aligned",
"bit_field",
"bitflags 2.9.4",
"block-device-driver",
"cfg-if",
"cortex-m",
"cortex-m-rt",
"critical-section",
"document-features",
"embassy-embedded-hal",
"embassy-futures",
"embassy-hal-internal",
"embassy-net-driver",
"embassy-sync",
"embassy-usb-driver",
"embassy-usb-synopsys-otg",
"embedded-can",
"embedded-hal 0.2.7",
"embedded-hal 1.0.0",
"embedded-hal-async",
"embedded-hal-nb",
"embedded-io",
"embedded-io-async",
"embedded-storage",
"embedded-storage-async",
"futures-util",
"nb 1.1.0",
"proc-macro2",
"quote",
"rand_core 0.6.4",
"rand_core 0.9.3",
"sdio-host",
"static_assertions",
"stm32-fmc",
"stm32-metapac",
"vcell",
"volatile-register",
]
[[package]]
name = "embassy-sync"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b"
dependencies = [
"cfg-if",
"critical-section",
"embedded-io-async",
"futures-core",
"futures-sink",
"heapless 0.8.0",
]
[[package]]
name = "embassy-usb-driver"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a"
dependencies = [
"embedded-io-async",
]
[[package]]
name = "embassy-usb-synopsys-otg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "288751f8eaa44a5cf2613f13cee0ca8e06e6638cb96e897e6834702c79084b23"
dependencies = [
"critical-section",
"embassy-sync",
"embassy-usb-driver",
]
[[package]]
name = "embedded-can"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438"
dependencies = [
"nb 1.1.0",
"stable_deref_trait",
]
[[package]]
@@ -442,43 +320,12 @@ dependencies = [
]
[[package]]
name = "embedded-hal-nb"
version = "1.0.0"
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"embedded-hal 1.0.0",
"nb 1.1.0",
]
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "embedded-io-async"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f"
dependencies = [
"embedded-io",
]
[[package]]
name = "embedded-storage"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032"
[[package]]
name = "embedded-storage-async"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc"
dependencies = [
"embedded-storage",
"num",
]
[[package]]
@@ -529,12 +376,6 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
version = "0.3.31"
@@ -559,6 +400,25 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "generic-array"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "667f6ea017b297ec65b8a108c6e9ad6879460721fb3b6b23abf690970147fc28"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "hash32"
version = "0.3.1"
@@ -584,16 +444,6 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "heapless"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -611,10 +461,24 @@ dependencies = [
]
[[package]]
name = "litrs"
version = "0.4.2"
name = "lsm303dlhc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
checksum = "9e5d1a5c290951321d1b0d4a40edd828537de9889134a0e67c5146542ae57706"
dependencies = [
"cast",
"embedded-hal 0.2.7",
"generic-array 0.11.2",
]
[[package]]
name = "micromath"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "nb"
@@ -631,6 +495,59 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -662,9 +579,9 @@ dependencies = [
[[package]]
name = "panic-probe"
version = "1.0.0"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a"
checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0"
dependencies = [
"cortex-m",
"defmt",
@@ -735,16 +652,13 @@ dependencies = [
]
[[package]]
name = "rand_core"
version = "0.6.4"
name = "rtcc"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
checksum = "95973c3a0274adc4f3c5b70d2b5b85618d6de9559a6737d3293ecae9a2fc0839"
dependencies = [
"chrono",
]
[[package]]
name = "rtic"
@@ -821,27 +735,42 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
"semver 0.9.0",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver 1.0.25",
]
[[package]]
name = "satrs"
version = "0.3.0-alpha.2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "866fcae3b683ccc37b5ad77982483a0ee01d5dc408dea5aad2117ad404b60fe1"
dependencies = [
"cobs",
"cobs 0.2.3",
"crc",
"defmt",
"delegate",
"derive-new",
"num-traits",
"num_enum",
"paste",
"satrs-shared",
"smallvec",
"spacepackets",
"thiserror",
]
[[package]]
name = "satrs-shared"
version = "0.2.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6042477018c2d43fffccaaa5099bc299a58485139b4d31c5b276889311e474f1"
dependencies = [
"spacepackets",
]
@@ -850,31 +779,24 @@ dependencies = [
name = "satrs-stm32f3-disco-rtic"
version = "0.1.0"
dependencies = [
"cobs",
"cobs 0.3.0",
"cortex-m",
"cortex-m-rt",
"cortex-m-semihosting",
"defmt",
"defmt-rtt",
"defmt-brtt",
"defmt-test",
"embassy-stm32",
"embedded-hal 1.0.0",
"embedded-hal 0.2.7",
"enumset",
"heapless 0.9.1",
"heapless",
"panic-probe",
"rtic",
"rtic-monotonics",
"satrs",
"spacepackets",
"static_cell",
"stm32f3-discovery",
"stm32f3xx-hal",
]
[[package]]
name = "sdio-host"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b328e2cb950eeccd55b7f55c3a963691455dcd044cfb5354f0c5e68d2c2d6ee2"
[[package]]
name = "semver"
version = "0.9.0"
@@ -884,6 +806,12 @@ dependencies = [
"semver-parser",
]
[[package]]
name = "semver"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
[[package]]
name = "semver-parser"
version = "0.7.0"
@@ -891,18 +819,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "spacepackets"
version = "0.15.0"
name = "slice-group-by"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ca19d2a251259686f6fffb094a8e32824098f387cd613ae81bfe4216524d02"
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spacepackets"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e85574d113a06312010c0ba51aadccd4ba2806231ebe9a49fc6473d0534d8696"
dependencies = [
"crc",
"defmt",
"delegate",
"num-traits",
"num_enum",
"paste",
"thiserror",
"zerocopy",
]
@@ -913,37 +851,72 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
name = "stm32-usbd"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "static_cell"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
dependencies = [
"portable-atomic",
]
[[package]]
name = "stm32-fmc"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c"
dependencies = [
"embedded-hal 0.2.7",
]
[[package]]
name = "stm32-metapac"
version = "18.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fd8ec3a292a0d9fc4798416a61b21da5ae50341b2e7b8d12e662bf305366097"
checksum = "c6c94998f166d66b210a164648a0b7866428d8f1e0740bf8a4c5edd89d4750c1"
dependencies = [
"cortex-m",
"usb-device",
"vcell",
]
[[package]]
name = "stm32f3"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b28b37228ef3fa47956af38c6abd756e912f244c1657f14e66d42fc8d74ea96f"
dependencies = [
"bare-metal 1.0.0",
"cortex-m",
"cortex-m-rt",
"vcell",
]
[[package]]
name = "stm32f3-discovery"
version = "0.8.0-alpha.0"
source = "git+https://github.com/robamu/stm32f3-discovery?branch=complete-dma-update-hal#5ccacae07ceff02d7d3649df67a6a0ba2a144752"
dependencies = [
"accelerometer",
"cortex-m",
"cortex-m-rt",
"lsm303dlhc",
"stm32f3xx-hal",
"switch-hal",
]
[[package]]
name = "stm32f3xx-hal"
version = "0.11.0-alpha.0"
source = "git+https://github.com/robamu/stm32f3xx-hal?branch=complete-dma-update#04fc76b7912649c84b57bd0ab803ea3ccf2aadae"
dependencies = [
"bxcan",
"cfg-if",
"cortex-m",
"cortex-m-rt",
"critical-section",
"embedded-dma",
"embedded-hal 0.2.7",
"embedded-time",
"enumset",
"nb 1.1.0",
"num-traits",
"paste",
"rtcc",
"slice-group-by",
"stm32-usbd",
"stm32f3",
"void",
]
[[package]]
name = "switch-hal"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90a4adc8cbd1726249b161898e48e0f3f1ce74d34dc784cbbc98fba4ed283fbf"
dependencies = [
"embedded-hal 0.2.7",
]
[[package]]
@@ -988,18 +961,36 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]]
name = "usb-device"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "void"
version = "1.0.2"
@@ -1017,18 +1008,19 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.26"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.26"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -9,16 +9,13 @@ default-run = "satrs-stm32f3-disco-rtic"
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "1"
defmt-rtt = { version = "1" }
panic-probe = { version = "1", features = ["print-defmt"] }
embedded-hal = "1"
defmt = "0.3"
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
embedded-hal = "0.2.7"
cortex-m-semihosting = "0.5.0"
embassy-stm32 = { version = "0.4", features = ["stm32f303vc", "unstable-pac"] }
enumset = "1"
heapless = "0.9"
spacepackets = { version = "0.15", default-features = false, features = ["defmt"] }
static_cell = "2"
heapless = "0.8"
[dependencies.rtic]
version = "2"
@@ -29,32 +26,32 @@ version = "2"
features = ["cortex-m-systick"]
[dependencies.cobs]
version = "0.4"
version = "0.3"
default-features = false
# [dependencies.stm32f3xx-hal]
# git = "https://github.com/robamu/stm32f3xx-hal"
# version = "0.11.0-alpha.0"
# features = ["stm32f303xc", "rt", "enumset"]
# branch = "complete-dma-update"
[dependencies.stm32f3xx-hal]
git = "https://github.com/robamu/stm32f3xx-hal"
version = "0.11.0-alpha.0"
features = ["stm32f303xc", "rt", "enumset"]
branch = "complete-dma-update"
# Can be used in workspace to develop and update HAL
# path = "../stm32f3xx-hal"
# [dependencies.stm32f3-discovery]
# git = "https://github.com/robamu/stm32f3-discovery"
# version = "0.8.0-alpha.0"
# branch = "complete-dma-update-hal"
[dependencies.stm32f3-discovery]
git = "https://github.com/robamu/stm32f3-discovery"
version = "0.8.0-alpha.0"
branch = "complete-dma-update-hal"
# Can be used in workspace to develop and update BSP
# path = "../stm32f3-discovery"
[dependencies.satrs]
# version = "0.2"
path = "../../satrs"
# path = "satrs"
version = "0.2"
default-features = false
features = ["defmt"]
[dev-dependencies]
defmt-test = "0.4"
defmt-test = "0.3"
# cargo test
[profile.test]

View File

@@ -1,61 +1,76 @@
#![no_main]
#![no_std]
#![no_main]
use satrs_stm32f3_disco_rtic as _;
use panic_probe as _;
use rtic::app;
use stm32f3_discovery::leds::Leds;
use stm32f3_discovery::stm32f3xx_hal::delay::Delay;
use stm32f3_discovery::stm32f3xx_hal::{pac, prelude::*};
use stm32f3_discovery::switch_hal::{OutputSwitch, ToggleableOutputSwitch};
#[app(device = embassy_stm32)]
mod app {
use rtic_monotonics::fugit::ExtU32;
use rtic_monotonics::Monotonic as _;
use satrs_stm32f3_disco_rtic::{Direction, LedPinSet, Leds};
#[cortex_m_rt::entry]
fn main() -> ! {
defmt::println!("STM32F3 Discovery Blinky");
let dp = pac::Peripherals::take().unwrap();
let mut rcc = dp.RCC.constrain();
let cp = cortex_m::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut delay = Delay::new(cp.SYST, clocks);
rtic_monotonics::systick_monotonic!(Mono, 1000);
#[shared]
struct Shared {}
#[local]
struct Local {
leds: Leds,
current_dir: Direction,
}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
let p = embassy_stm32::init(Default::default());
defmt::info!("Starting sat-rs demo application for the STM32F3-Discovery using RTICv2");
let led_pin_set = LedPinSet {
pin_n: p.PE8,
pin_ne: p.PE9,
pin_e: p.PE10,
pin_se: p.PE11,
pin_s: p.PE12,
pin_sw: p.PE13,
pin_w: p.PE14,
pin_nw: p.PE15,
};
let leds = Leds::new(led_pin_set);
// Initialize the systick interrupt & obtain the token to prove that we did
Mono::start(cx.core.SYST, 8_000_000);
blinky::spawn().expect("failed to spawn blinky task");
(
Shared {},
Local {
leds,
current_dir: Direction::North,
},
)
}
#[task(local = [leds, current_dir])]
async fn blinky(cx: blinky::Context) {
let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);
let mut leds = Leds::new(
gpioe.pe8,
gpioe.pe9,
gpioe.pe10,
gpioe.pe11,
gpioe.pe12,
gpioe.pe13,
gpioe.pe14,
gpioe.pe15,
&mut gpioe.moder,
&mut gpioe.otyper,
);
let delay_ms = 200u16;
loop {
cx.local.leds.blink_next(cx.local.current_dir);
Mono::delay(200.millis()).await;
}
leds.ld3_n.toggle().ok();
delay.delay_ms(delay_ms);
leds.ld3_n.toggle().ok();
delay.delay_ms(delay_ms);
//explicit on/off
leds.ld4_nw.on().ok();
delay.delay_ms(delay_ms);
leds.ld4_nw.off().ok();
delay.delay_ms(delay_ms);
leds.ld5_ne.on().ok();
delay.delay_ms(delay_ms);
leds.ld5_ne.off().ok();
delay.delay_ms(delay_ms);
leds.ld6_w.on().ok();
delay.delay_ms(delay_ms);
leds.ld6_w.off().ok();
delay.delay_ms(delay_ms);
leds.ld7_e.on().ok();
delay.delay_ms(delay_ms);
leds.ld7_e.off().ok();
delay.delay_ms(delay_ms);
leds.ld8_sw.on().ok();
delay.delay_ms(delay_ms);
leds.ld8_sw.off().ok();
delay.delay_ms(delay_ms);
leds.ld9_se.on().ok();
delay.delay_ms(delay_ms);
leds.ld9_se.off().ok();
delay.delay_ms(delay_ms);
leds.ld10_s.on().ok();
delay.delay_ms(delay_ms);
leds.ld10_s.off().ok();
delay.delay_ms(delay_ms);
}
}

View File

@@ -3,147 +3,12 @@
use cortex_m_semihosting::debug;
use defmt_rtt as _; // global logger
use defmt_brtt as _; // global logger
use stm32f3xx_hal as _; // memory layout
use panic_probe as _;
use embassy_stm32::gpio::Output;
#[derive(defmt::Format, PartialEq, Eq, Clone, Copy)]
pub enum Direction {
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest,
}
impl Direction {
pub fn switch_to_next(&mut self) -> (Self, Self) {
let curr = *self;
*self = match self {
Direction::North => Direction::NorthEast,
Direction::NorthEast => Direction::East,
Direction::East => Direction::SouthEast,
Direction::SouthEast => Direction::South,
Direction::South => Direction::SouthWest,
Direction::SouthWest => Direction::West,
Direction::West => Direction::NorthWest,
Direction::NorthWest => Direction::North,
};
(curr, *self)
}
}
pub struct Leds {
pub north: Output<'static>,
pub north_east: Output<'static>,
pub east: Output<'static>,
pub south_east: Output<'static>,
pub south: Output<'static>,
pub south_west: Output<'static>,
pub west: Output<'static>,
pub north_west: Output<'static>,
}
impl Leds {
pub fn blink_next(&mut self, current_dir: &mut Direction) {
let (prev, curr) = current_dir.switch_to_next();
self.set_dir_low(prev);
self.set_dir_high(curr);
}
pub fn set_dir(&mut self, dir: Direction, level: embassy_stm32::gpio::Level) {
match dir {
Direction::North => self.north.set_level(level),
Direction::NorthEast => self.north_east.set_level(level),
Direction::East => self.east.set_level(level),
Direction::SouthEast => self.south_east.set_level(level),
Direction::South => self.south.set_level(level),
Direction::SouthWest => self.south_west.set_level(level),
Direction::West => self.west.set_level(level),
Direction::NorthWest => self.north_west.set_level(level),
}
}
pub fn set_dir_low(&mut self, dir: Direction) {
self.set_dir(dir, embassy_stm32::gpio::Level::Low);
}
pub fn set_dir_high(&mut self, dir: Direction) {
self.set_dir(dir, embassy_stm32::gpio::Level::High);
}
}
pub struct LedPinSet {
pub pin_n: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE8>,
pub pin_ne: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE9>,
pub pin_e: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE10>,
pub pin_se: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE11>,
pub pin_s: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE12>,
pub pin_sw: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE13>,
pub pin_w: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE14>,
pub pin_nw: embassy_stm32::Peri<'static, embassy_stm32::peripherals::PE15>,
}
impl Leds {
pub fn new(pin_set: LedPinSet) -> Self {
let led_n = Output::new(
pin_set.pin_n,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_ne = Output::new(
pin_set.pin_ne,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_e = Output::new(
pin_set.pin_e,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_se = Output::new(
pin_set.pin_se,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_s = Output::new(
pin_set.pin_s,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_sw = Output::new(
pin_set.pin_sw,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_w = Output::new(
pin_set.pin_w,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
let led_nw = Output::new(
pin_set.pin_nw,
embassy_stm32::gpio::Level::Low,
embassy_stm32::gpio::Speed::Medium,
);
Self {
north: led_n,
north_east: led_ne,
east: led_e,
south_east: led_se,
south: led_s,
south_west: led_sw,
west: led_w,
north_west: led_nw,
}
}
}
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
#[defmt::panic_handler]

View File

@@ -1,6 +1,8 @@
#![no_std]
#![no_main]
use satrs::pus::verification::{FailParams, VerificationReportCreator};
use satrs::pus::verification::{
FailParams, TcStateAccepted, VerificationReportCreator, VerificationToken,
};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use satrs::spacepackets::ecss::EcssEnumU16;
@@ -11,12 +13,16 @@ use satrs_stm32f3_disco_rtic as _;
use rtic::app;
use heapless::Vec;
use heapless::{mpmc::Q8, Vec};
#[allow(unused_imports)]
use rtic_monotonics::fugit::{MillisDurationU32, TimerInstantU32};
use rtic_monotonics::systick::prelude::*;
use satrs::seq_count::SequenceCountProviderCore;
use satrs::spacepackets::{ecss::PusPacket, ecss::WritablePusPacket};
use spacepackets::seq_count::SequenceCountProvider;
use stm32f3xx_hal::dma::dma1;
use stm32f3xx_hal::gpio::{PushPull, AF7, PA2, PA3};
use stm32f3xx_hal::pac::USART2;
use stm32f3xx_hal::serial::{Rx, RxEvent, Serial, SerialDmaRx, SerialDmaTx, Tx, TxEvent};
const UART_BAUD: u32 = 115200;
const DEFAULT_BLINK_FREQ_MS: u32 = 1000;
@@ -24,24 +30,33 @@ const TX_HANDLER_FREQ_MS: u32 = 20;
const MIN_DELAY_BETWEEN_TX_PACKETS_MS: u32 = 5;
const MAX_TC_LEN: usize = 128;
const MAX_TM_LEN: usize = 128;
pub const PUS_APID: u16 = 0x02;
type TxType = Tx<USART2, PA2<AF7<PushPull>>>;
type RxType = Rx<USART2, PA3<AF7<PushPull>>>;
type InstantFugit = TimerInstantU32<1000>;
type TxDmaTransferType = SerialDmaTx<&'static [u8], dma1::C7, TxType>;
type RxDmaTransferType = SerialDmaRx<&'static mut [u8], dma1::C6, RxType>;
// This is the predictable maximum overhead of the COBS encoding scheme.
// It is simply the maximum packet lenght dividied by 254 rounded up.
const COBS_TC_OVERHEAD: usize = cobs::max_encoding_overhead(MAX_TC_LEN);
const COBS_TM_OVERHEAD: usize = cobs::max_encoding_overhead(MAX_TM_LEN);
const COBS_TC_OVERHEAD: usize = (MAX_TC_LEN + 254 - 1) / 254;
const COBS_TM_OVERHEAD: usize = (MAX_TM_LEN + 254 - 1) / 254;
const TC_BUF_LEN: usize = MAX_TC_LEN + COBS_TC_OVERHEAD;
const TM_BUF_LEN: usize = MAX_TC_LEN + COBS_TM_OVERHEAD;
const TC_DMA_BUF_LEN: usize = 512;
// This is a static buffer which should ONLY (!) be used as the TX DMA
// transfer buffer.
static mut DMA_TX_BUF: [u8; TM_BUF_LEN] = [0; TM_BUF_LEN];
// This is a static buffer which should ONLY (!) be used as the RX DMA
// transfer buffer.
static mut DMA_RX_BUF: [u8; TC_BUF_LEN] = [0; TC_BUF_LEN];
type TmPacket = heapless::Vec<u8, MAX_TM_LEN>;
type TcPacket = heapless::Vec<u8, MAX_TC_LEN>;
type TmPacket = Vec<u8, MAX_TM_LEN>;
type TcPacket = Vec<u8, MAX_TC_LEN>;
static TM_REQUESTS: static_cell::ConstStaticCell<heapless::spsc::Queue<TmPacket, 8>> =
static_cell::ConstStaticCell::new(heapless::spsc::Queue::new());
static TM_REQUESTS: Q8<TmPacket> = Q8::new();
use core::sync::atomic::{AtomicU16, Ordering};
@@ -59,10 +74,7 @@ impl SeqCountProviderAtomicRef {
}
}
impl SequenceCountProvider for SeqCountProviderAtomicRef {
type Raw = u16;
const MAX_BIT_WIDTH: usize = 16;
impl SequenceCountProviderCore<u16> for SeqCountProviderAtomicRef {
fn get(&self) -> u16 {
self.atomic.load(self.ordering)
}
@@ -80,8 +92,8 @@ static SEQ_COUNT_PROVIDER: SeqCountProviderAtomicRef =
SeqCountProviderAtomicRef::new(Ordering::Relaxed);
pub struct TxIdle {
//tx: TxType,
//dma_channel: dma1::C7,
tx: TxType,
dma_channel: dma1::C7,
}
#[derive(Debug, defmt::Format)]
@@ -96,8 +108,49 @@ impl From<ByteConversionError> for TmSendError {
}
}
fn send_tm(tm_creator: PusTmCreator) -> Result<(), TmSendError> {
if tm_creator.len_written() > MAX_TM_LEN {
return Err(ByteConversionError::ToSliceTooSmall {
expected: tm_creator.len_written(),
found: MAX_TM_LEN,
}
.into());
}
let mut tm_vec = TmPacket::new();
tm_vec
.resize(tm_creator.len_written(), 0)
.expect("vec resize failed");
tm_creator.write_to_bytes(tm_vec.as_mut_slice())?;
defmt::info!(
"Sending TM[{},{}] with size {}",
tm_creator.service(),
tm_creator.subservice(),
tm_creator.len_written()
);
TM_REQUESTS
.enqueue(tm_vec)
.map_err(|_| TmSendError::Queue)?;
Ok(())
}
fn handle_tm_send_error(error: TmSendError) {
defmt::warn!("sending tm failed with error {}", error);
}
pub enum UartTxState {
// Wrapped in an option because we need an owned type later.
Idle(Option<TxIdle>),
// Same as above
Transmitting(Option<TxDmaTransferType>),
}
pub struct UartTxShared {
last_completed: Option<InstantFugit>,
state: UartTxState,
}
pub struct RequestWithToken {
request_id: satrs::pus::verification::RequestId,
token: VerificationToken<TcStateAccepted>,
request: Request,
}
@@ -115,69 +168,147 @@ pub enum RequestError {
NotEnoughAppData = 4,
}
#[app(device = embassy_stm32)]
pub fn convert_pus_tc_to_request(
tc: &PusTcReader,
verif_reporter: &mut VerificationReportCreator,
src_data_buf: &mut [u8],
timestamp: &[u8],
) -> Result<RequestWithToken, RequestError> {
defmt::info!(
"Found PUS TC [{},{}] with length {}",
tc.service(),
tc.subservice(),
tc.len_packed()
);
let token = verif_reporter.add_tc(tc);
if tc.apid() != PUS_APID {
defmt::warn!("Received tc with unknown APID {}", tc.apid());
let result = send_tm(
verif_reporter
.acceptance_failure(
src_data_buf,
token,
SEQ_COUNT_PROVIDER.get_and_increment(),
0,
FailParams::new(timestamp, &EcssEnumU16::new(0), &[]),
)
.unwrap(),
);
if let Err(e) = result {
handle_tm_send_error(e);
}
return Err(RequestError::InvalidApid);
}
let (tm_creator, accepted_token) = verif_reporter
.acceptance_success(
src_data_buf,
token,
SEQ_COUNT_PROVIDER.get_and_increment(),
0,
timestamp,
)
.unwrap();
if let Err(e) = send_tm(tm_creator) {
handle_tm_send_error(e);
}
if tc.service() == 17 && tc.subservice() == 1 {
if tc.subservice() == 1 {
return Ok(RequestWithToken {
request: Request::Ping,
token: accepted_token,
});
} else {
return Err(RequestError::InvalidSubservice);
}
} else if tc.service() == 8 {
if tc.subservice() == 1 {
if tc.user_data().len() < 4 {
return Err(RequestError::NotEnoughAppData);
}
let new_freq_ms = u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap());
return Ok(RequestWithToken {
request: Request::ChangeBlinkFrequency(new_freq_ms),
token: accepted_token,
});
} else {
return Err(RequestError::InvalidSubservice);
}
} else {
return Err(RequestError::InvalidService);
}
}
#[app(device = stm32f3xx_hal::pac, peripherals = true)]
mod app {
use super::*;
use satrs::pus::verification::VerificationReportCreator;
use core::slice::Iter;
use satrs::pus::verification::{TcStateStarted, VerificationReportCreator};
use satrs::spacepackets::{ecss::tc::PusTcReader, time::cds::P_FIELD_BASE};
use satrs_stm32f3_disco_rtic::LedPinSet;
#[allow(unused_imports)]
use stm32f3_discovery::leds::Direction;
use stm32f3_discovery::leds::Leds;
use stm32f3xx_hal::prelude::*;
use stm32f3_discovery::switch_hal::OutputSwitch;
use stm32f3xx_hal::Switch;
#[allow(dead_code)]
type SerialType = Serial<USART2, (PA2<AF7<PushPull>>, PA3<AF7<PushPull>>)>;
systick_monotonic!(Mono, 1000);
embassy_stm32::bind_interrupts!(struct Irqs {
USART2 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART2>;
});
#[shared]
struct Shared {
blink_freq: MillisDurationU32,
tx_shared: UartTxShared,
rx_transfer: Option<RxDmaTransferType>,
}
#[local]
struct Local {
verif_reporter: VerificationReportCreator,
leds: satrs_stm32f3_disco_rtic::Leds,
current_dir: satrs_stm32f3_disco_rtic::Direction,
tm_prod: heapless::spsc::Producer<'static, TmPacket>,
tm_cons: heapless::spsc::Consumer<'static, TmPacket>,
tx: embassy_stm32::usart::UartTx<'static, embassy_stm32::mode::Async>,
rx: embassy_stm32::usart::RingBufferedUartRx<'static>,
leds: Leds,
last_dir: Direction,
curr_dir: Iter<'static, Direction>,
}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
static DMA_BUF: static_cell::ConstStaticCell<[u8; TC_DMA_BUF_LEN]> = static_cell::ConstStaticCell::new([0; TC_DMA_BUF_LEN]);
let p = embassy_stm32::init(Default::default());
let mut rcc = cx.device.RCC.constrain();
// Initialize the systick interrupt & obtain the token to prove that we did
Mono::start(cx.core.SYST, 8_000_000);
defmt::info!("Starting sat-rs demo application for the STM32F3-Discovery with RTICv2");
let led_pin_set = LedPinSet {
pin_n: p.PE8,
pin_ne: p.PE9,
pin_e: p.PE10,
pin_se: p.PE11,
pin_s: p.PE12,
pin_sw: p.PE13,
pin_w: p.PE14,
pin_nw: p.PE15,
};
let leds = satrs_stm32f3_disco_rtic::Leds::new(led_pin_set);
let mut flash = cx.device.FLASH.constrain();
let clocks = rcc
.cfgr
.use_hse(8.MHz())
.sysclk(8.MHz())
.pclk1(8.MHz())
.freeze(&mut flash.acr);
let config = embassy_stm32::usart::Config::default();
let uart = embassy_stm32::usart::Uart::new(
p.USART2, p.PA3, p.PA2, Irqs, p.DMA1_CH7, p.DMA1_CH6, config,
)
.unwrap();
// Set up monotonic timer.
//let mono_timer = MonoTimer::new(cx.core.DWT, clocks, &mut cx.core.DCB);
let (tx, rx) = uart.split();
let tm_queue = TM_REQUESTS.take();
let (tm_prod, tm_cons) = tm_queue.split();
//let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb);
defmt::info!("Starting sat-rs demo application for the STM32F3-Discovery");
let mut gpioe = cx.device.GPIOE.split(&mut rcc.ahb);
let leds = Leds::new(
gpioe.pe8,
gpioe.pe9,
gpioe.pe10,
gpioe.pe11,
gpioe.pe12,
gpioe.pe13,
gpioe.pe14,
gpioe.pe15,
&mut gpioe.moder,
&mut gpioe.otyper,
);
let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb);
// USART2 pins
/*
let mut pins = (
// TX pin: PA2
gpioa
@@ -188,9 +319,7 @@ mod app {
.pa3
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl),
);
*/
//pins.1.internal_pull_up(&mut gpioa.pupdr, true);
/*
pins.1.internal_pull_up(&mut gpioa.pupdr, true);
let mut usart2 = Serial::new(
cx.device.USART2,
pins,
@@ -201,19 +330,18 @@ mod app {
usart2.configure_rx_interrupt(RxEvent::Idle, Switch::On);
// This interrupt is enabled to re-schedule new transfers in the interrupt handler immediately.
usart2.configure_tx_interrupt(TxEvent::TransmissionComplete, Switch::On);
*/
//let dma1 = cx.device.DMA1.split(&mut rcc.ahb);
//let (mut tx_serial, mut rx_serial) = usart2.split();
let dma1 = cx.device.DMA1.split(&mut rcc.ahb);
let (mut tx_serial, mut rx_serial) = usart2.split();
// This interrupt is immediately triggered, clear it. It will only be reset
// by the hardware when data is received on RX (RXNE event)
//rx_serial.clear_event(RxEvent::Idle);
rx_serial.clear_event(RxEvent::Idle);
// For some reason, this is also immediately triggered..
//tx_serial.clear_event(TxEvent::TransmissionComplete);
//let rx_transfer = rx_serial.read_exact(unsafe { DMA_RX_BUF.as_mut_slice() }, dma1.ch6);
tx_serial.clear_event(TxEvent::TransmissionComplete);
let rx_transfer = rx_serial.read_exact(unsafe { DMA_RX_BUF.as_mut_slice() }, dma1.ch6);
defmt::info!("Spawning tasks");
blinky::spawn().unwrap();
blink::spawn().unwrap();
serial_tx_handler::spawn().unwrap();
let verif_reporter = VerificationReportCreator::new(PUS_APID).unwrap();
@@ -221,49 +349,118 @@ mod app {
(
Shared {
blink_freq: MillisDurationU32::from_ticks(DEFAULT_BLINK_FREQ_MS),
tx_shared: UartTxShared {
last_completed: None,
state: UartTxState::Idle(Some(TxIdle {
tx: tx_serial,
dma_channel: dma1.ch7,
})),
},
rx_transfer: Some(rx_transfer),
},
Local {
verif_reporter,
leds,
tm_prod,
tm_cons,
tx,
rx: rx.into_ring_buffered(DMA_BUF.take()),
current_dir: satrs_stm32f3_disco_rtic::Direction::North,
last_dir: Direction::North,
curr_dir: Direction::iter(),
},
)
}
#[task(local = [leds, current_dir], shared=[blink_freq])]
async fn blinky(mut cx: blinky::Context) {
#[task(local = [leds, curr_dir, last_dir], shared=[blink_freq])]
async fn blink(mut cx: blink::Context) {
let blink::LocalResources {
leds,
curr_dir,
last_dir,
..
} = cx.local;
let mut toggle_leds = |dir: &Direction| {
let last_led = leds.for_direction(*last_dir);
last_led.off().ok();
let led = leds.for_direction(*dir);
led.on().ok();
*last_dir = *dir;
};
loop {
cx.local.leds.blink_next(cx.local.current_dir);
match curr_dir.next() {
Some(dir) => {
toggle_leds(dir);
}
None => {
*curr_dir = Direction::iter();
toggle_leds(curr_dir.next().unwrap());
}
}
let current_blink_freq = cx.shared.blink_freq.lock(|current| *current);
Mono::delay(current_blink_freq).await;
}
}
#[task(
local = [
tm_cons,
tx,
dma_buf: [u8; TM_BUF_LEN] = [0; TM_BUF_LEN]
],
shared = [],
shared = [tx_shared],
)]
async fn serial_tx_handler(cx: serial_tx_handler::Context) {
async fn serial_tx_handler(mut cx: serial_tx_handler::Context) {
loop {
while let Some(vec) = cx.local.tm_cons.dequeue() {
cx.local.dma_buf[0] = 0;
let encoded_len = cobs::encode(&vec[0..vec.len()], &mut cx.local.dma_buf[1..]);
let is_idle = cx.shared.tx_shared.lock(|tx_shared| {
if let UartTxState::Idle(_) = tx_shared.state {
return true;
}
false
});
if is_idle {
let last_completed = cx.shared.tx_shared.lock(|shared| shared.last_completed);
if let Some(last_completed) = last_completed {
let elapsed_ms = (Mono::now() - last_completed).to_millis();
if elapsed_ms < MIN_DELAY_BETWEEN_TX_PACKETS_MS {
Mono::delay((MIN_DELAY_BETWEEN_TX_PACKETS_MS - elapsed_ms).millis()).await;
}
}
} else {
// Check for completion after 1 ms
Mono::delay(1.millis()).await;
continue;
}
if let Some(vec) = TM_REQUESTS.dequeue() {
cx.shared
.tx_shared
.lock(|tx_shared| match &mut tx_shared.state {
UartTxState::Idle(tx) => {
let encoded_len;
//debug!(target: "serial_tx_handler", "bytes: {:x?}", &buf[0..len]);
// Safety: We only copy the data into the TX DMA buffer in this task.
// If the DMA is active, another branch will be taken.
unsafe {
// 0 sentinel value as start marker
DMA_TX_BUF[0] = 0;
encoded_len =
cobs::encode(&vec[0..vec.len()], &mut DMA_TX_BUF[1..]);
// Should never panic, we accounted for the overhead.
// Write into transfer buffer directly, no need for intermediate
// encoding buffer.
// 0 end marker
cx.local.dma_buf[encoded_len + 1] = 0;
cx.local.tx.write(&vec[0..encoded_len + 2]).await.unwrap();
DMA_TX_BUF[encoded_len + 1] = 0;
}
//debug!(target: "serial_tx_handler", "Sending {} bytes", encoded_len + 2);
//debug!("sent: {:x?}", &mut_tx_dma_buf[0..encoded_len + 2]);
let tx_idle = tx.take().unwrap();
// Transfer completion and re-scheduling of new TX transfers will be done
// by the IRQ handler.
// SAFETY: The DMA is the exclusive writer to the DMA buffer now.
let transfer = tx_idle.tx.write_all(
unsafe { &DMA_TX_BUF[0..encoded_len + 2] },
tx_idle.dma_channel,
);
tx_shared.state = UartTxState::Transmitting(Some(transfer));
// The memory block is automatically returned to the pool when it is dropped.
}
UartTxState::Transmitting(_) => (),
});
// Check for completion after 1 ms
Mono::delay(1.millis()).await;
continue;
}
// Nothing to do, and we are idle.
Mono::delay(TX_HANDLER_FREQ_MS.millis()).await;
}
}
@@ -271,9 +468,6 @@ mod app {
#[task(
local = [
verif_reporter,
tm_prod,
rx,
read_buf: [u8; 128] = [0; 128],
decode_buf: [u8; MAX_TC_LEN] = [0; MAX_TC_LEN],
src_data_buf: [u8; MAX_TM_LEN] = [0; MAX_TM_LEN],
timestamp: [u8; 7] = [0; 7],
@@ -284,18 +478,6 @@ mod app {
mut cx: serial_rx_handler::Context,
received_packet: Vec<u8, MAX_TC_LEN>,
) {
let decoder = cobs::CobsDecoder::new(cx.local.decode_buf);
loop {
let read_bytes = cx.local.rx.read(cx.local.read_buf).await;
match decoder.push(&cx.local.read_buf[0..read_bytes]) {
Ok(None) => (),
Ok(Some(report)) => {
}
Err(_) => {},
}
}
cx.local.timestamp[0] = P_FIELD_BASE;
defmt::info!("Received packet with {} bytes", received_packet.len());
let decode_buf = cx.local.decode_buf;
@@ -312,24 +494,21 @@ mod app {
return;
}
let start_idx = start_idx.unwrap();
decoder.push(data)
match cobs::decode(&received_packet.as_slice()[start_idx..], decode_buf) {
Ok(decode_report) => {
defmt::info!("Decoded packet length: {}", decode_report.frame_size());
Ok(len) => {
defmt::info!("Decoded packet length: {}", len);
let pus_tc = PusTcReader::new(decode_buf);
match pus_tc {
Ok(tc) => {
Ok((tc, _tc_len)) => {
match convert_pus_tc_to_request(
&tc,
cx.local.verif_reporter,
cx.local.tm_prod,
cx.local.src_data_buf,
cx.local.timestamp,
) {
Ok(request_with_token) => {
handle_start_verification(
request_with_token.request_id,
cx.local.tm_prod,
let started_token = handle_start_verification(
request_with_token.token,
cx.local.verif_reporter,
cx.local.src_data_buf,
cx.local.timestamp,
@@ -337,7 +516,7 @@ mod app {
match request_with_token.request {
Request::Ping => {
handle_ping_request(cx.local.tm_prod, cx.local.timestamp);
handle_ping_request(cx.local.timestamp);
}
Request::ChangeBlinkFrequency(new_freq_ms) => {
defmt::info!("Received blink frequency change request with new frequncy {}", new_freq_ms);
@@ -348,8 +527,7 @@ mod app {
}
}
handle_completion_verification(
request_with_token.request_id,
cx.local.tm_prod,
started_token,
cx.local.verif_reporter,
cx.local.src_data_buf,
cx.local.timestamp,
@@ -372,10 +550,7 @@ mod app {
}
}
fn handle_ping_request(
tm_prod: &mut heapless::spsc::Producer<'static, TmPacket>,
timestamp: &[u8],
) {
fn handle_ping_request(timestamp: &[u8]) {
defmt::info!("Received PUS ping telecommand, sending ping reply TM[17,2]");
let sp_header =
SpHeader::new_for_unseg_tc(PUS_APID, SEQ_COUNT_PROVIDER.get_and_increment(), 0);
@@ -386,36 +561,36 @@ mod app {
.resize(ping_reply.len_written(), 0)
.expect("vec resize failed");
ping_reply.write_to_bytes(&mut tm_packet).unwrap();
if tm_prod.enqueue(tm_packet).is_err() {
if TM_REQUESTS.enqueue(tm_packet).is_err() {
defmt::warn!("TC queue full");
return;
}
}
fn handle_start_verification(
request_id: satrs::pus::verification::RequestId,
tm_prod: &mut heapless::spsc::Producer<TmPacket>,
accepted_token: VerificationToken<TcStateAccepted>,
verif_reporter: &mut VerificationReportCreator,
src_data_buf: &mut [u8],
timestamp: &[u8],
) {
let tm_creator = verif_reporter
) -> VerificationToken<TcStateStarted> {
let (tm_creator, started_token) = verif_reporter
.start_success(
src_data_buf,
&request_id,
accepted_token,
SEQ_COUNT_PROVIDER.get(),
0,
timestamp,
&timestamp,
)
.unwrap();
let result = send_tm(tm_creator, tm_prod);
let result = send_tm(tm_creator);
if let Err(e) = result {
handle_tm_send_error(e);
}
started_token
}
fn handle_completion_verification(
request_id: satrs::pus::verification::RequestId,
tm_prod: &mut heapless::spsc::Producer<TmPacket>,
started_token: VerificationToken<TcStateStarted>,
verif_reporter: &mut VerificationReportCreator,
src_data_buf: &mut [u8],
timestamp: &[u8],
@@ -424,23 +599,20 @@ mod app {
verif_reporter
.completion_success(
src_data_buf,
&request_id,
started_token,
SEQ_COUNT_PROVIDER.get(),
0,
timestamp,
)
.unwrap(),
tm_prod,
);
if let Err(e) = result {
handle_tm_send_error(e);
}
}
/*
#[task(binds = DMA1_CH6, shared = [])]
fn rx_dma_isr(cx: rx_dma_isr::Context) {
/*
#[task(binds = DMA1_CH6, shared = [rx_transfer])]
fn rx_dma_isr(mut cx: rx_dma_isr::Context) {
let mut tc_packet = TcPacket::new();
cx.shared.rx_transfer.lock(|rx_transfer| {
let rx_ref = rx_transfer.as_ref().unwrap();
@@ -466,14 +638,10 @@ mod app {
);
}
});
*/
}
*/
/*
#[task(binds = USART2_EXTI26, shared = [])]
#[task(binds = USART2_EXTI26, shared = [rx_transfer, tx_shared])]
fn serial_isr(mut cx: serial_isr::Context) {
/*
cx.shared
.tx_shared
.lock(|tx_shared| match &mut tx_shared.state {
@@ -510,112 +678,5 @@ mod app {
*rx_transfer = Some(rx.read_exact(buf, ch));
}
});
*/
}
*/
}
fn send_tm(
tm_creator: PusTmCreator,
tm_prod: &mut heapless::spsc::Producer<TmPacket>,
) -> Result<(), TmSendError> {
if tm_creator.len_written() > MAX_TM_LEN {
return Err(ByteConversionError::ToSliceTooSmall {
expected: tm_creator.len_written(),
found: MAX_TM_LEN,
}
.into());
}
let mut tm_vec = TmPacket::new();
tm_vec
.resize(tm_creator.len_written(), 0)
.expect("vec resize failed");
tm_creator.write_to_bytes(tm_vec.as_mut_slice())?;
defmt::info!(
"Sending TM[{},{}] with size {}",
tm_creator.service(),
tm_creator.subservice(),
tm_creator.len_written()
);
tm_prod.enqueue(tm_vec).map_err(|_| TmSendError::Queue)?;
Ok(())
}
fn handle_tm_send_error(error: TmSendError) {
defmt::warn!("sending tm failed with error {}", error);
}
pub fn convert_pus_tc_to_request(
tc: &PusTcReader,
verif_reporter: &mut VerificationReportCreator,
tm_prod: &mut heapless::spsc::Producer<'static, TmPacket>,
src_data_buf: &mut [u8],
timestamp: &[u8],
) -> Result<RequestWithToken, RequestError> {
defmt::info!(
"Found PUS TC [{},{}] with length {}",
tc.service(),
tc.subservice(),
tc.len_packed()
);
let request_id = verif_reporter.read_request_id(tc);
if tc.apid() != PUS_APID {
defmt::warn!("Received tc with unknown APID {}", tc.apid());
let result = send_tm(
verif_reporter
.acceptance_failure(
src_data_buf,
&request_id,
SEQ_COUNT_PROVIDER.get_and_increment(),
0,
FailParams::new(timestamp, &EcssEnumU16::new(0), &[]),
)
.unwrap(),
tm_prod,
);
if let Err(e) = result {
handle_tm_send_error(e);
}
return Err(RequestError::InvalidApid);
}
let tm_creator = verif_reporter
.acceptance_success(
src_data_buf,
&request_id,
SEQ_COUNT_PROVIDER.get_and_increment(),
0,
timestamp,
)
.unwrap();
if let Err(e) = send_tm(tm_creator, tm_prod) {
handle_tm_send_error(e);
}
if tc.service() == 17 && tc.subservice() == 1 {
if tc.subservice() == 1 {
Ok(RequestWithToken {
request_id,
request: Request::Ping,
})
} else {
Err(RequestError::InvalidSubservice)
}
} else if tc.service() == 8 {
if tc.subservice() == 1 {
if tc.user_data().len() < 4 {
return Err(RequestError::NotEnoughAppData);
}
let new_freq_ms = u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap());
Ok(RequestWithToken {
request_id,
request: Request::ChangeBlinkFrequency(new_freq_ms),
})
} else {
Err(RequestError::InvalidSubservice)
}
} else {
Err(RequestError::InvalidService)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,17 +16,16 @@ harness = false
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "1"
defmt = "0.3"
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "1", features = ["print-defmt"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
cortex-m-semihosting = "0.5.0"
# TODO: Replace with embassy-hal.
stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] }
embedded-alloc = "0.6"
rtic-sync = { version = "1", features = ["defmt-03"] }
[dependencies.smoltcp]
version = "0.12"
version = "0.11"
default-features = false
features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4", "socket-udp", "defmt"]
@@ -40,12 +39,12 @@ features = ["cortex-m-systick"]
[dependencies.satrs]
path = "../../satrs"
# version = "0.2"
version = "0.2"
default-features = false
features = ["defmt", "heapless"]
[dev-dependencies]
defmt-test = "0.4"
defmt-test = "0.3"
# cargo build/run
[profile.dev]

View File

@@ -11,6 +11,8 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/sat-rs"
fern = "0.7"
chrono = "0.4"
log = "0.4"
arbitrary-int = "2"
bitbybit = "1.4"
crossbeam-channel = "0.5"
delegate = "0.13"
zerocopy = "0.8"

View File

@@ -574,7 +574,7 @@ mod tests {
let (request_tx, request_rx) = mpsc::sync_channel(5);
let (reply_tx_to_pus, reply_rx_to_pus) = 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 id = UniqueApidTargetId::new(Apid::Acs.raw_value(), 1);
let mode_node = ModeRequestHandlerMpscBounded::new(id.into(), request_rx);
let (composite_request_tx, composite_request_rx) = mpsc::channel();
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);

View File

@@ -1,7 +1,9 @@
use arbitrary_int::u11;
use satrs::pus::verification::RequestId;
use satrs::spacepackets::ecss::tc::PusTcCreator;
use satrs::spacepackets::ecss::tm::PusTmReader;
use satrs::{spacepackets::ecss::PusPacket, spacepackets::SpHeader};
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::spacepackets::SpHeader;
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
use std::net::{IpAddr, SocketAddr, UdpSocket};
use std::time::Duration;
@@ -9,7 +11,13 @@ use std::time::Duration;
fn main() {
let mut buf = [0; 32];
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
let pus_tc = PusTcCreator::new_simple(SpHeader::new_from_apid(0x02), 17, 1, &[], true);
let pus_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(u11::new(0x02)),
17,
1,
&[],
CreatorConfig::default(),
);
let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed");
let tc_req_id = RequestId::new(&pus_tc);
println!("Packing and sending PUS ping command TC[17,1] with request ID {tc_req_id}");

View File

@@ -44,7 +44,7 @@ lazy_static! {
pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = {
let mut set = HashSet::new();
for id in crate::ids::Apid::iter() {
set.insert(PacketId::new(PacketType::Tc, true, id as u16));
set.insert(PacketId::new(PacketType::Tc, true, id.raw_value()));
}
set
};

View File

@@ -572,7 +572,7 @@ mod tests {
let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
let mut handler = PcduHandler::new(
UniqueApidTargetId::new(Apid::Eps as u16, 0),
UniqueApidTargetId::new(Apid::Eps.raw_value(), 0),
"TEST_PCDU",
mode_node,
composite_request_rx,

View File

@@ -1,6 +1,7 @@
use std::sync::mpsc::{self};
use crate::pus::create_verification_reporter;
use arbitrary_int::u11;
use satrs::event_man::{EventMessageU32, EventRoutingError};
use satrs::pus::event::EventTmHook;
use satrs::pus::verification::VerificationReporter;
@@ -23,7 +24,7 @@ use crate::update_time;
// This helper sets the APID of the event sender for the PUS telemetry.
#[derive(Default)]
pub struct EventApidSetter {
pub next_apid: u16,
pub next_apid: u11,
}
impl EventTmHook for EventApidSetter {
@@ -59,7 +60,7 @@ impl<TmSender: EcssTmSender> PusEventHandler<TmSender> {
// telemetry for each event.
let event_reporter = EventReporter::new_with_hook(
PUS_EVENT_MANAGEMENT.raw(),
0,
u11::new(0),
0,
128,
EventApidSetter::default(),
@@ -220,16 +221,13 @@ mod tests {
use satrs::{
events::EventU32,
pus::verification::VerificationReporterConfig,
spacepackets::{
ecss::{tm::PusTmReader, PusPacket},
CcsdsPacket,
},
spacepackets::ecss::{tm::PusTmReader, PusPacket},
tmtc::PacketAsVec,
};
use super::*;
const TEST_CREATOR_ID: UniqueApidTargetId = UniqueApidTargetId::new(1, 2);
const TEST_CREATOR_ID: UniqueApidTargetId = UniqueApidTargetId::new(u11::new(1), 2);
const TEST_EVENT: EventU32 = EventU32::new(satrs::events::Severity::Info, 1, 1);
pub struct EventManagementTestbench {
@@ -244,7 +242,8 @@ mod tests {
let (event_tx, event_rx) = mpsc::sync_channel(10);
let (_event_req_tx, event_req_rx) = mpsc::sync_channel(10);
let (tm_sender, tm_receiver) = mpsc::channel();
let verif_reporter_cfg = VerificationReporterConfig::new(0x05, 2, 2, 128).unwrap();
let verif_reporter_cfg =
VerificationReporterConfig::new(u11::new(0x05), 2, 2, 128).unwrap();
let verif_reporter =
VerificationReporter::new(PUS_EVENT_MANAGEMENT.id(), &verif_reporter_cfg);
let mut event_manager = EventManagerWithBoundedMpsc::new(event_rx);

View File

@@ -1,8 +1,8 @@
use derive_new::new;
use satrs::hk::UniqueId;
use satrs::request::UniqueApidTargetId;
use satrs::spacepackets::ecss::hk;
use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use satrs::spacepackets::ecss::{hk, CreatorConfig};
use satrs::spacepackets::{ByteConversionError, SpHeader};
#[derive(Debug, new, Copy, Clone)]
@@ -63,7 +63,7 @@ impl PusHkHelper {
SpHeader::new_from_apid(self.component_id.apid),
sec_header,
&buf[0..8 + hk_data_len],
true,
CreatorConfig::default(),
))
}
}

View File

@@ -1,7 +1,8 @@
//! This is an auto-generated configuration module.
use satrs::request::UniqueApidTargetId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::EnumIter)]
#[derive(Debug, PartialEq, Eq, strum::EnumIter)]
#[bitbybit::bitenum(u11, exhaustive = false)]
pub enum Apid {
Sched = 1,
GenericPus = 2,
@@ -21,13 +22,13 @@ pub mod acs {
}
pub const SUBSYSTEM: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Subsystem as u32);
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Subsystem as u32);
pub const ASSEMBLY: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Assembly as u32);
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Assembly as u32);
pub const MGM0: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Mgm0 as u32);
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm0 as u32);
pub const MGM1: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Mgm1 as u32);
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm1 as u32);
}
pub mod eps {
@@ -38,9 +39,9 @@ pub mod eps {
}
pub const PCDU: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Eps as u16, Id::Pcdu as u32);
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Pcdu as u32);
pub const SUBSYSTEM: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Eps as u16, Id::Subsystem as u32);
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Subsystem as u32);
}
pub mod generic_pus {
@@ -55,19 +56,19 @@ pub mod generic_pus {
}
pub const PUS_EVENT_MANAGEMENT: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
super::Apid::GenericPus as u16,
super::Apid::GenericPus.raw_value(),
Id::PusEventManagement as u32,
);
pub const PUS_ROUTING: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusRouting as u32);
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusRouting as u32);
pub const PUS_TEST: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusTest as u32);
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusTest as u32);
pub const PUS_ACTION: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusAction as u32);
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusAction as u32);
pub const PUS_MODE: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusMode as u32);
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusMode as u32);
pub const PUS_HK: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusHk as u32);
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusHk as u32);
}
pub mod sched {
@@ -77,7 +78,7 @@ pub mod sched {
}
pub const PUS_SCHED: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Sched as u16, Id::PusSched as u32);
super::UniqueApidTargetId::new(super::Apid::Sched.raw_value(), Id::PusSched as u32);
}
pub mod tmtc {
@@ -88,7 +89,7 @@ pub mod tmtc {
}
pub const UDP_SERVER: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Tmtc as u16, Id::UdpServer as u32);
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::UdpServer as u32);
pub const TCP_SERVER: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Tmtc as u16, Id::TcpServer as u32);
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::TcpServer as u32);
}

View File

@@ -113,6 +113,9 @@ mod tests {
sync::{Arc, Mutex},
};
use arbitrary_int::traits::Integer as _;
use arbitrary_int::u14;
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::{
spacepackets::{
ecss::{tc::PusTcCreator, WritablePusPacket},
@@ -177,8 +180,8 @@ mod tests {
udp_tc_server,
tm_handler,
};
let sph = SpHeader::new_for_unseg_tc(ids::Apid::GenericPus as u16, 0, 0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true)
let sph = SpHeader::new_for_unseg_tc(ids::Apid::GenericPus.raw_value(), u14::ZERO, 0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default())
.to_vec()
.unwrap();
let client = UdpSocket::bind("127.0.0.1:0").expect("Connecting to UDP server failed");

View File

@@ -1,4 +1,4 @@
use satrs::spacepackets::time::{cds::CdsTime, TimeWriter};
use satrs::spacepackets::time::cds::CdsTime;
pub mod config;
pub mod ids;

View File

@@ -35,7 +35,7 @@ use satrs::{
mode_tree::connect_mode_nodes,
pus::{event_man::EventRequestWithToken, EcssTcCacher, HandlingStatus},
request::{GenericMessage, MessageMetadata},
spacepackets::time::{cds::CdsTime, TimeWriter},
spacepackets::time::cds::CdsTime,
};
use satrs_example::{
config::{

View File

@@ -276,6 +276,7 @@ mod tests {
use satrs::pus::verification::test_util::TestVerificationReporter;
use satrs::pus::{verification, EcssTcVecCacher};
use satrs::request::MessageMetadata;
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::tmtc::PacketAsVec;
use satrs::ComponentId;
use satrs::{
@@ -453,7 +454,9 @@ mod tests {
let mut app_data: [u8; 8] = [0; 8];
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_1.to_be_bytes());
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
let pus8_packet = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let pus8_packet =
PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
testbench.add_tc(&pus8_packet);
let time_stamp: [u8; 7] = [0; 7];
testbench.verify_next_tc_is_handled_properly(&time_stamp);
@@ -499,7 +502,7 @@ mod tests {
SpHeader::new_from_apid(TEST_APID),
sec_header,
&app_data,
true,
CreatorConfig::default(),
);
testbench.add_tc(&pus8_packet);
let time_stamp: [u8; 7] = [0; 7];
@@ -525,7 +528,7 @@ mod tests {
SpHeader::new_from_apid(TEST_APID),
sec_header,
&app_data,
true,
CreatorConfig::default(),
);
let token = testbench.add_tc(&pus8_packet);
let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0);
@@ -564,7 +567,7 @@ mod tests {
SpHeader::new_from_apid(TEST_APID),
sec_header,
&app_data,
true,
CreatorConfig::default(),
);
let token = testbench.add_tc(&pus8_packet);
let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0);

View File

@@ -302,10 +302,13 @@ impl TargetedPusService for HkServiceWrapper {
#[cfg(test)]
mod tests {
use arbitrary_int::traits::Integer;
use arbitrary_int::u14;
use satrs::pus::test_util::{
TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
};
use satrs::request::MessageMetadata;
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::{
hk::HkRequestVariant,
pus::test_util::TEST_APID,
@@ -324,11 +327,12 @@ mod tests {
use super::{HkReply, HkReplyHandler, HkRequestConverter};
pub const ZERO_SEQ: u14 = u14::ZERO;
#[test]
fn hk_converter_one_shot_req() {
let mut hk_bench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), HkRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, ZERO_SEQ, 0);
let target_id = TEST_UNIQUE_ID_0;
let unique_id = 5_u32;
let mut app_data: [u8; 8] = [0; 8];
@@ -340,7 +344,7 @@ mod tests {
3,
Subservice::TcGenerateOneShotHk as u8,
&app_data,
true,
CreatorConfig::default(),
);
let accepted_token = hk_bench.add_tc(&hk_req);
let (_active_req, req) = hk_bench
@@ -358,7 +362,7 @@ mod tests {
fn hk_converter_enable_periodic_generation() {
let mut hk_bench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), HkRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, ZERO_SEQ, 0);
let target_id = TEST_UNIQUE_ID_0;
let unique_id = 5_u32;
let mut app_data: [u8; 8] = [0; 8];
@@ -380,7 +384,7 @@ mod tests {
3,
Subservice::TcEnableHkGeneration as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc0);
let tc1 = PusTcCreator::new_simple(
@@ -388,7 +392,7 @@ mod tests {
3,
Subservice::TcEnableDiagGeneration as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc1);
}
@@ -397,7 +401,7 @@ mod tests {
fn hk_conversion_disable_periodic_generation() {
let mut hk_bench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), HkRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, ZERO_SEQ, 0);
let target_id = TEST_UNIQUE_ID_0;
let unique_id = 5_u32;
let mut app_data: [u8; 8] = [0; 8];
@@ -419,7 +423,7 @@ mod tests {
3,
Subservice::TcDisableHkGeneration as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc0);
let tc1 = PusTcCreator::new_simple(
@@ -427,7 +431,7 @@ mod tests {
3,
Subservice::TcDisableDiagGeneration as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc1);
}
@@ -436,7 +440,7 @@ mod tests {
fn hk_conversion_modify_interval() {
let mut hk_bench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), HkRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, ZERO_SEQ, 0);
let target_id = TEST_UNIQUE_ID_0;
let unique_id = 5_u32;
let mut app_data: [u8; 12] = [0; 12];
@@ -462,7 +466,7 @@ mod tests {
3,
Subservice::TcModifyHkCollectionInterval as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc0);
let tc1 = PusTcCreator::new_simple(
@@ -470,7 +474,7 @@ mod tests {
3,
Subservice::TcModifyDiagCollectionInterval as u8,
&app_data,
true,
CreatorConfig::default(),
);
generic_check(&tc1);
}

View File

@@ -531,9 +531,11 @@ pub fn generic_pus_request_timeout_handler(
pub(crate) mod tests {
use std::time::Duration;
use arbitrary_int::u11;
use satrs::pus::test_util::TEST_COMPONENT_ID_0;
use satrs::pus::{MpscTmAsVecSender, PusTmVariant};
use satrs::request::RequestId;
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::{
pus::{
verification::test_util::TestVerificationReporter, ActivePusRequestStd,
@@ -590,7 +592,7 @@ pub(crate) mod tests {
pub fn add_tc(
&mut self,
apid: u16,
apid: u11,
apid_target: u32,
time_stamp: &[u8],
) -> (verification::RequestId, ActivePusRequestStd) {
@@ -600,7 +602,7 @@ pub(crate) mod tests {
sp_header,
sec_header_dummy,
&[],
true,
CreatorConfig::default(),
));
let accepted = self
.verif_reporter
@@ -719,7 +721,7 @@ pub(crate) mod tests {
&mut self,
token: VerificationToken<TcStateAccepted>,
time_stamp: &[u8],
expected_apid: u16,
expected_apid: u11,
expected_apid_target: u32,
) -> Result<(ActiveRequestInfo, Request), Converter::Error> {
if self.current_packet.is_none() {

View File

@@ -1,5 +1,7 @@
use arbitrary_int::u14;
use derive_new::new;
use satrs::mode_tree::{ModeNode, ModeParent};
use satrs::spacepackets::ecss::CreatorConfig;
use satrs_example::ids;
use std::sync::mpsc;
use std::time::Duration;
@@ -77,10 +79,16 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
.write_to_be_bytes(&mut source_data)
.expect("writing mode reply failed");
let req_id = verification::RequestId::from(reply.request_id());
let sp_header = SpHeader::new_for_unseg_tm(req_id.packet_id().apid(), 0, 0);
let sp_header =
SpHeader::new_for_unseg_tm(req_id.packet_id().apid(), u14::new(0), 0);
let sec_header =
PusTmSecondaryHeader::new(200, Subservice::TmModeReply as u8, 0, 0, time_stamp);
let pus_tm = PusTmCreator::new(sp_header, sec_header, &source_data, true);
let pus_tm = PusTmCreator::new(
sp_header,
sec_header,
&source_data,
CreatorConfig::default(),
);
tm_sender.send_tm(self.owner_id, PusTmVariant::Direct(pus_tm))?;
verification_handler.completion_success(tm_sender, started_token, time_stamp)?;
}
@@ -290,8 +298,10 @@ impl TargetedPusService for ModeServiceWrapper {
#[cfg(test)]
mod tests {
use arbitrary_int::u14;
use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0, TEST_UNIQUE_ID_0};
use satrs::request::MessageMetadata;
use satrs::spacepackets::ecss::CreatorConfig;
use satrs::{
mode::{ModeAndSubmode, ModeReply, ModeRequest},
pus::mode::Subservice,
@@ -314,11 +324,11 @@ mod tests {
fn mode_converter_read_mode_request() {
let mut testbench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), ModeRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8);
let mut app_data: [u8; 4] = [0; 4];
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
let token = testbench.add_tc(&tc);
let (_active_req, req) = testbench
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)
@@ -330,7 +340,7 @@ mod tests {
fn mode_converter_set_mode_request() {
let mut testbench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), ModeRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8);
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
let mode_and_submode = ModeAndSubmode::new(2, 1);
@@ -338,7 +348,7 @@ mod tests {
mode_and_submode
.write_to_be_bytes(&mut app_data[4..])
.unwrap();
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
let token = testbench.add_tc(&tc);
let (_active_req, req) = testbench
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)
@@ -356,11 +366,11 @@ mod tests {
fn mode_converter_announce_mode() {
let mut testbench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), ModeRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8);
let mut app_data: [u8; 4] = [0; 4];
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
let token = testbench.add_tc(&tc);
let (_active_req, req) = testbench
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)
@@ -372,12 +382,12 @@ mod tests {
fn mode_converter_announce_mode_recursively() {
let mut testbench =
PusConverterTestbench::new(TEST_COMPONENT_ID_0.id(), ModeRequestConverter::default());
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
let sec_header =
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
let mut app_data: [u8; 4] = [0; 4];
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
let token = testbench.add_tc(&tc);
let (_active_req, req) = testbench
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID_0)

View File

@@ -3,18 +3,19 @@ use std::{
sync::mpsc::{self},
};
use arbitrary_int::{u11, u14};
use log::info;
use satrs::{
pool::PoolProvider,
spacepackets::{
ecss::{tm::PusTmZeroCopyWriter, PusPacket},
seq_count::CcsdsSimpleSeqCountProvider,
seq_count::SequenceCounterCcsdsSimple,
time::cds::MIN_CDS_FIELD_LEN,
CcsdsPacket,
},
};
use satrs::{
spacepackets::seq_count::SequenceCountProvider,
spacepackets::seq_count::SequenceCounter,
tmtc::{PacketAsVec, PacketInPool, SharedPacketPool},
};
@@ -22,14 +23,16 @@ use crate::interface::tcp::SyncTcpTmSource;
#[derive(Default)]
pub struct CcsdsSeqCounterMap {
apid_seq_counter_map: HashMap<u16, CcsdsSimpleSeqCountProvider>,
apid_seq_counter_map: HashMap<u11, SequenceCounterCcsdsSimple>,
}
impl CcsdsSeqCounterMap {
pub fn get_and_increment(&mut self, apid: u16) -> u16 {
pub fn get_and_increment(&mut self, apid: u11) -> u14 {
u14::new(
self.apid_seq_counter_map
.entry(apid)
.or_default()
.get_and_increment()
.get_and_increment(),
)
}
}
@@ -114,7 +117,7 @@ impl TmSinkStatic {
let mut tm_copy = Vec::new();
pool_guard
.modify(&pus_tm_in_pool.store_addr, |buf| {
let zero_copy_writer = PusTmZeroCopyWriter::new(buf, MIN_CDS_FIELD_LEN)
let zero_copy_writer = PusTmZeroCopyWriter::new(buf, MIN_CDS_FIELD_LEN, true)
.expect("Creating TM zero copy writer failed");
self.common.apply_packet_processing(zero_copy_writer);
tm_copy = buf.to_vec()
@@ -154,7 +157,8 @@ impl TmSinkDynamic {
if let Ok(mut tm) = self.tm_funnel_rx.recv() {
// Read the TM, set sequence counter and message counter, and finally update
// the CRC.
let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN)
let zero_copy_writer =
PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN, true)
.expect("Creating TM zero copy writer failed");
self.common.apply_packet_processing(zero_copy_writer);
self.common.sync_tm_tcp_source.add_tm(&tm.packet);

View File

@@ -11,7 +11,7 @@ license = "Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
spacepackets = { version = ">=0.14, <=0.15", default-features = false }
spacepackets = { git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", version = ">=0.14, <=0.16", default-features = false }
[dependencies.serde]
version = "1"

View File

@@ -14,8 +14,9 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup
[dependencies]
satrs-shared = { version = "0.2", path = "../satrs-shared" }
spacepackets = { version = ">=0.14, <=0.15", default-features = false }
spacepackets = { git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", version = "0.16", default-features = false }
arbitrary-int = "2"
delegate = ">0.7, <=0.13"
paste = "1"
derive-new = ">=0.6, <=0.7"

View File

@@ -63,7 +63,7 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
let sp_header = SpHeader::from_be_bytes(&buf[current_idx..]).unwrap().0;
match packet_validator.validate(&sp_header, &buf[current_idx..]) {
SpValidity::Valid => {
let packet_size = sp_header.total_len();
let packet_size = sp_header.packet_len();
if (current_idx + packet_size) <= buf_len {
packet_sender
.send_packet(sender_id, &buf[current_idx..current_idx + packet_size])?;
@@ -76,7 +76,7 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
continue;
}
SpValidity::Skip => {
current_idx += sp_header.total_len();
current_idx += sp_header.packet_len();
}
// We might have lost sync. Try to find the start of a new space packet header.
SpValidity::Invalid => {
@@ -89,9 +89,10 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
#[cfg(test)]
mod tests {
use arbitrary_int::{u11, u14};
use spacepackets::{
CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, SpHeader,
ecss::tc::PusTcCreator,
CcsdsPacket, PacketId, PacketSequenceControl, PacketType, SequenceFlags, SpHeader,
ecss::{CreatorConfig, tc::PusTcCreator},
};
use crate::{ComponentId, encoding::tests::TcCacher};
@@ -99,8 +100,8 @@ mod tests {
use super::{SpValidity, SpacePacketValidator, parse_buffer_for_ccsds_space_packets};
const PARSER_ID: ComponentId = 0x05;
const TEST_APID_0: u16 = 0x02;
const TEST_APID_1: u16 = 0x10;
const TEST_APID_0: u11 = u11::new(0x02);
const TEST_APID_1: u11 = u11::new(0x10);
const TEST_PACKET_ID_0: PacketId = PacketId::new_for_tc(true, TEST_APID_0);
const TEST_PACKET_ID_1: PacketId = PacketId::new_for_tc(true, TEST_APID_1);
@@ -131,7 +132,7 @@ mod tests {
#[test]
fn test_basic() {
let sph = SpHeader::new_from_apid(TEST_APID_0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default());
let mut buffer: [u8; 32] = [0; 32];
let packet_len = ping_tc
.write_to_bytes(&mut buffer)
@@ -156,8 +157,8 @@ mod tests {
#[test]
fn test_multi_packet() {
let sph = SpHeader::new_from_apid(TEST_APID_0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], true);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default());
let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], CreatorConfig::default());
let mut buffer: [u8; 32] = [0; 32];
let packet_len_ping = ping_tc
.write_to_bytes(&mut buffer)
@@ -191,9 +192,9 @@ mod tests {
#[test]
fn test_multi_apid() {
let sph = SpHeader::new_from_apid(TEST_APID_0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default());
let sph = SpHeader::new_from_apid(TEST_APID_1);
let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], true);
let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], CreatorConfig::default());
let mut buffer: [u8; 32] = [0; 32];
let packet_len_ping = ping_tc
.write_to_bytes(&mut buffer)
@@ -221,10 +222,20 @@ mod tests {
#[test]
fn test_split_packet_multi() {
let ping_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
let action_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_1), 8, 0, &[], true);
let ping_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_0),
17,
1,
&[],
CreatorConfig::default(),
);
let action_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_1),
8,
0,
&[],
CreatorConfig::default(),
);
let mut buffer: [u8; 32] = [0; 32];
let packet_len_ping = ping_tc
.write_to_bytes(&mut buffer)
@@ -255,8 +266,13 @@ mod tests {
#[test]
fn test_one_split_packet() {
let ping_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
let ping_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_0),
17,
1,
&[],
CreatorConfig::default(),
);
let mut buffer: [u8; 32] = [0; 32];
let packet_len_ping = ping_tc
.write_to_bytes(&mut buffer)
@@ -281,7 +297,7 @@ mod tests {
fn test_smallest_packet() {
let ccsds_header_only = SpHeader::new(
PacketId::new(PacketType::Tc, true, TEST_APID_0),
PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 0),
PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0)),
0,
);
let mut buf: [u8; 7] = [0; 7];

View File

@@ -183,10 +183,11 @@ mod tests {
};
use alloc::sync::Arc;
use arbitrary_int::u11;
use hashbrown::HashSet;
use spacepackets::{
CcsdsPacket, PacketId, SpHeader,
ecss::{WritablePusPacket, tc::PusTcCreator},
ecss::{CreatorConfig, WritablePusPacket, tc::PusTcCreator},
};
use crate::{
@@ -203,9 +204,9 @@ mod tests {
use super::TcpSpacepacketsServer;
const TCP_SERVER_ID: ComponentId = 0x05;
const TEST_APID_0: u16 = 0x02;
const TEST_APID_0: u11 = u11::new(0x02);
const TEST_PACKET_ID_0: PacketId = PacketId::new_for_tc(true, TEST_APID_0);
const TEST_APID_1: u16 = 0x10;
const TEST_APID_1: u11 = u11::new(0x10);
const TEST_PACKET_ID_1: PacketId = PacketId::new_for_tc(true, TEST_APID_1);
#[derive(Default)]
@@ -283,8 +284,13 @@ mod tests {
.check_no_connections_left();
set_if_done.store(true, Ordering::Relaxed);
});
let ping_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
let ping_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_0),
17,
1,
&[],
CreatorConfig::default(),
);
let tc_0 = ping_tc.to_vec().expect("packet generation failed");
let mut stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed");
stream
@@ -314,13 +320,23 @@ mod tests {
// Add telemetry
let mut total_tm_len = 0;
let verif_tm =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 1, 1, &[], true);
let verif_tm = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_0),
1,
1,
&[],
CreatorConfig::default(),
);
let tm_0 = verif_tm.to_vec().expect("writing packet failed");
total_tm_len += tm_0.len();
tm_source.add_tm(&tm_0);
let verif_tm =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_1), 1, 3, &[], true);
let verif_tm = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_1),
1,
3,
&[],
CreatorConfig::default(),
);
let tm_1 = verif_tm.to_vec().expect("writing packet failed");
total_tm_len += tm_1.len();
tm_source.add_tm(&tm_1);
@@ -366,14 +382,24 @@ mod tests {
.expect("setting reas timeout failed");
// Send telecommands
let ping_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
let ping_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_0),
17,
1,
&[],
CreatorConfig::default(),
);
let tc_0 = ping_tc.to_vec().expect("ping tc creation failed");
stream
.write_all(&tc_0)
.expect("writing to TCP server failed");
let action_tc =
PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_1), 8, 0, &[], true);
let action_tc = PusTcCreator::new_simple(
SpHeader::new_from_apid(TEST_APID_1),
8,
0,
&[],
CreatorConfig::default(),
);
let tc_1 = action_tc.to_vec().expect("action tc creation failed");
stream
.write_all(&tc_1)

View File

@@ -127,8 +127,10 @@ mod tests {
use crate::hal::std::udp_server::{ReceiveResult, UdpTcServer};
use crate::queue::GenericSendError;
use crate::tmtc::PacketSenderRaw;
use arbitrary_int::u11;
use core::cell::RefCell;
use spacepackets::SpHeader;
use spacepackets::ecss::CreatorConfig;
use spacepackets::ecss::tc::PusTcCreator;
use std::collections::VecDeque;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
@@ -165,8 +167,8 @@ mod tests {
let mut udp_tc_server = UdpTcServer::new(UDP_SERVER_ID, dest_addr, 2048, ping_receiver)
.expect("Creating UDP TMTC server failed");
is_send(&udp_tc_server);
let sph = SpHeader::new_from_apid(0x02);
let pus_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
let sph = SpHeader::new_from_apid(u11::new(0x02));
let pus_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default());
let len = pus_tc
.write_to_bytes(&mut buf)
.expect("Error writing PUS TC packet");

View File

@@ -1,9 +1,9 @@
use crate::pus::source_buffer_large_enough;
use arbitrary_int::u11;
use spacepackets::ByteConversionError;
use spacepackets::ecss::EcssEnumeration;
use spacepackets::ecss::tm::PusTmCreator;
use spacepackets::ecss::tm::PusTmSecondaryHeader;
use spacepackets::{MAX_APID, SpHeader};
use spacepackets::SpHeader;
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::ecss::{CreatorConfig, EcssEnumeration};
#[cfg(feature = "alloc")]
pub use alloc_mod::*;
@@ -11,16 +11,13 @@ pub use alloc_mod::*;
pub use spacepackets::ecss::event::*;
pub struct EventReportCreator {
apid: u16,
apid: u11,
pub dest_id: u16,
}
impl EventReportCreator {
pub fn new(apid: u16, dest_id: u16) -> Option<Self> {
if apid > MAX_APID {
return None;
}
Some(Self { dest_id, apid })
pub fn new(apid: u11, dest_id: u16) -> Self {
Self { dest_id, apid }
}
pub fn event_info<'time, 'src_data>(
@@ -124,7 +121,7 @@ impl EventReportCreator {
SpHeader::new_from_apid(self.apid),
sec_header,
&src_data_buf[0..current_idx],
true,
CreatorConfig::default(),
))
}
}
@@ -162,11 +159,11 @@ mod alloc_mod {
impl EventReporter<DummyEventHook> {
pub fn new(
id: ComponentId,
default_apid: u16,
default_apid: u11,
default_dest_id: u16,
max_event_id_and_aux_data_size: usize,
) -> Option<Self> {
let reporter = EventReportCreator::new(default_apid, default_dest_id)?;
let reporter = EventReportCreator::new(default_apid, default_dest_id);
Some(Self {
id,
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
@@ -178,12 +175,12 @@ mod alloc_mod {
impl<EventTmHookInstance: EventTmHook> EventReporter<EventTmHookInstance> {
pub fn new_with_hook(
id: ComponentId,
default_apid: u16,
default_apid: u11,
default_dest_id: u16,
max_event_id_and_aux_data_size: usize,
tm_hook: EventTmHookInstance,
) -> Option<Self> {
let reporter = EventReportCreator::new(default_apid, default_dest_id)?;
let reporter = EventReportCreator::new(default_apid, default_dest_id);
Some(Self {
id,
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
@@ -276,7 +273,7 @@ mod tests {
use std::collections::VecDeque;
use std::vec::Vec;
const EXAMPLE_APID: u16 = 0xee;
const EXAMPLE_APID: u11 = u11::new(0xee);
const EXAMPLE_GROUP_ID: u16 = 2;
const EXAMPLE_EVENT_ID_0: u16 = 1;
#[allow(dead_code)]

View File

@@ -311,6 +311,7 @@ pub mod alloc_mod {
mod tests {
use alloc::string::{String, ToString};
use alloc::vec;
use arbitrary_int::u11;
use spacepackets::ecss::PusPacket;
use spacepackets::ecss::event::Subservice;
use spacepackets::ecss::tm::PusTmReader;
@@ -323,7 +324,7 @@ mod tests {
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityInfo>::new(1, 0);
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
const EMPTY_STAMP: [u8; 7] = [0; 7];
const TEST_APID: u16 = 0x02;
const TEST_APID: u11 = u11::new(0x02);
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
fn create_basic_man_1() -> DefaultPusEventU32TmCreator {

View File

@@ -144,7 +144,10 @@ impl<
#[cfg(test)]
mod tests {
use arbitrary_int::traits::Integer as _;
use arbitrary_int::u14;
use delegate::delegate;
use spacepackets::ecss::CreatorConfig;
use spacepackets::ecss::event::Subservice;
use spacepackets::time::{TimeWriter, cds};
use spacepackets::util::UnsignedEnum;
@@ -242,13 +245,13 @@ mod tests {
expected_event_req: EventRequest,
event_req_receiver: mpsc::Receiver<EventRequestWithToken>,
) {
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
let sec_header = PusTcSecondaryHeader::new_simple(5, subservice as u8);
let mut app_data = [0; 4];
TEST_EVENT_0
.write_to_be_bytes(&mut app_data)
.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, CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
@@ -307,9 +310,10 @@ mod tests {
fn test_sending_custom_subservice() {
let (event_request_tx, _) = mpsc::channel();
let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
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, CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
@@ -326,10 +330,11 @@ mod tests {
fn test_sending_invalid_app_data() {
let (event_request_tx, _) = mpsc::channel();
let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
let sec_header =
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], CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();

View File

@@ -1258,6 +1258,7 @@ pub(crate) fn source_buffer_large_enough(
#[cfg(any(feature = "test_util", test))]
pub mod test_util {
use arbitrary_int::u11;
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
use crate::request::UniqueApidTargetId;
@@ -1267,7 +1268,7 @@ pub mod test_util {
verification::{self, TcStateAccepted, VerificationToken},
};
pub const TEST_APID: u16 = 0x101;
pub const TEST_APID: u11 = u11::new(0x101);
pub const TEST_UNIQUE_ID_0: u32 = 0x05;
pub const TEST_UNIQUE_ID_1: u32 = 0x06;
@@ -1302,6 +1303,7 @@ pub mod tests {
use alloc::collections::VecDeque;
use alloc::vec::Vec;
use arbitrary_int::{u11, u14};
use satrs_shared::res_code::ResultU16;
use spacepackets::CcsdsPacket;
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader};
@@ -1324,8 +1326,8 @@ pub mod tests {
#[derive(Debug, Eq, PartialEq, Clone)]
pub(crate) struct CommonTmInfo {
pub subservice: u8,
pub apid: u16,
pub seq_count: u16,
pub apid: u11,
pub seq_count: u14,
pub msg_counter: u16,
pub dest_id: u16,
pub timestamp: Vec<u8>,
@@ -1334,8 +1336,8 @@ pub mod tests {
impl CommonTmInfo {
pub fn new(
subservice: u8,
apid: u16,
seq_count: u16,
apid: u11,
seq_count: u14,
msg_counter: u16,
dest_id: u16,
timestamp: &[u8],
@@ -1351,11 +1353,11 @@ pub mod tests {
}
pub fn new_zero_seq_count(
subservice: u8,
apid: u16,
apid: u11,
dest_id: u16,
timestamp: &[u8],
) -> Self {
Self::new(subservice, apid, 0, 0, dest_id, timestamp)
Self::new(subservice, apid, u14::new(0), 0, dest_id, timestamp)
}
pub fn new_from_tm(tm: &PusTmCreator) -> Self {

View File

@@ -2,6 +2,7 @@
//!
//! The core data structure of this module is the [PusScheduler]. This structure can be used
//! to perform the scheduling of telecommands like specified in the ECSS standard.
use arbitrary_int::{u11, u14};
use core::fmt::{Debug, Display, Formatter};
use core::time::Duration;
#[cfg(feature = "serde")]
@@ -26,20 +27,23 @@ pub use alloc_mod::*;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RequestId {
pub(crate) source_id: u16,
pub(crate) apid: u16,
pub(crate) seq_count: u16,
pub(crate) apid: u11,
pub(crate) seq_count: u14,
}
impl RequestId {
pub fn source_id(&self) -> u16 {
#[inline]
pub const fn source_id(&self) -> u16 {
self.source_id
}
pub fn apid(&self) -> u16 {
#[inline]
pub const fn apid(&self) -> u11 {
self.apid
}
pub fn seq_count(&self) -> u16 {
#[inline]
pub const fn seq_count(&self) -> u14 {
self.seq_count
}
@@ -53,8 +57,11 @@ impl RequestId {
}
}
pub fn as_u64(&self) -> u64 {
((self.source_id as u64) << 32) | ((self.apid as u64) << 16) | self.seq_count as u64
#[inline]
pub const fn as_u64(&self) -> u64 {
((self.source_id as u64) << 32)
| ((self.apid.value() as u64) << 16)
| self.seq_count.value() as u64
}
}
@@ -855,42 +862,45 @@ mod tests {
PoolAddr, PoolError, PoolProvider, StaticMemoryPool, StaticPoolAddr, StaticPoolConfig,
};
use alloc::collections::btree_map::Range;
use spacepackets::ecss::WritablePusPacket;
use arbitrary_int::traits::Integer as _;
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
use spacepackets::ecss::{CreatorConfig, WritablePusPacket};
use spacepackets::time::{TimeWriter, UnixTime, cds};
use spacepackets::{PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, SpHeader};
use spacepackets::{PacketId, PacketSequenceControl, PacketType, SequenceFlags, SpHeader};
use std::time::Duration;
use std::vec::Vec;
#[allow(unused_imports)]
use std::{println, vec};
const ZERO_SEQ: u14 = u14::ZERO;
fn pus_tc_base(timestamp: UnixTime, buf: &mut [u8]) -> (SpHeader, usize) {
let cds_time =
cds::CdsTime::from_unix_time_with_u16_days(&timestamp, cds::SubmillisPrecision::Absent)
.unwrap();
let len_time_stamp = cds_time.write_to_bytes(buf).unwrap();
let len_packet = base_ping_tc_simple_ctor(0, &[])
let len_packet = base_ping_tc_simple_ctor(u14::new(0), &[])
.write_to_bytes(&mut buf[len_time_stamp..])
.unwrap();
(
SpHeader::new_for_unseg_tc(0x02, 0x34, len_packet as u16),
SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), len_packet as u16),
len_packet + len_time_stamp,
)
}
fn scheduled_tc(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator<'_> {
let (sph, len_app_data) = pus_tc_base(timestamp, buf);
PusTcCreator::new_simple(sph, 11, 4, &buf[..len_app_data], true)
PusTcCreator::new_simple(sph, 11, 4, &buf[..len_app_data], CreatorConfig::default())
}
fn wrong_tc_service(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator<'_> {
let (sph, len_app_data) = pus_tc_base(timestamp, buf);
PusTcCreator::new_simple(sph, 12, 4, &buf[..len_app_data], true)
PusTcCreator::new_simple(sph, 12, 4, &buf[..len_app_data], CreatorConfig::default())
}
fn wrong_tc_subservice(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator<'_> {
let (sph, len_app_data) = pus_tc_base(timestamp, buf);
PusTcCreator::new_simple(sph, 11, 5, &buf[..len_app_data], true)
PusTcCreator::new_simple(sph, 11, 5, &buf[..len_app_data], CreatorConfig::default())
}
fn double_wrapped_time_tagged_tc(timestamp: UnixTime, buf: &mut [u8]) -> PusTcCreator<'_> {
@@ -898,30 +908,37 @@ mod tests {
cds::CdsTime::from_unix_time_with_u16_days(&timestamp, cds::SubmillisPrecision::Absent)
.unwrap();
let len_time_stamp = cds_time.write_to_bytes(buf).unwrap();
let sph = SpHeader::new_for_unseg_tc(0x02, 0x34, 0);
let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0);
// app data should not matter, double wrapped time-tagged commands should be rejected right
// away
let inner_time_tagged_tc = PusTcCreator::new_simple(sph, 11, 4, &[], true);
let inner_time_tagged_tc =
PusTcCreator::new_simple(sph, 11, 4, &[], CreatorConfig::default());
let packet_len = inner_time_tagged_tc
.write_to_bytes(&mut buf[len_time_stamp..])
.expect("writing inner time tagged tc failed");
PusTcCreator::new_simple(sph, 11, 4, &buf[..len_time_stamp + packet_len], true)
PusTcCreator::new_simple(
sph,
11,
4,
&buf[..len_time_stamp + packet_len],
CreatorConfig::default(),
)
}
fn invalid_time_tagged_cmd() -> PusTcCreator<'static> {
let sph = SpHeader::new_for_unseg_tc(0x02, 0x34, 1);
PusTcCreator::new_simple(sph, 11, 4, &[], true)
let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 1);
PusTcCreator::new_simple(sph, 11, 4, &[], CreatorConfig::default())
}
fn base_ping_tc_simple_ctor(seq_count: u16, app_data: &'static [u8]) -> PusTcCreator<'static> {
let sph = SpHeader::new_for_unseg_tc(0x02, seq_count, 0);
PusTcCreator::new_simple(sph, 17, 1, app_data, true)
fn base_ping_tc_simple_ctor(seq_count: u14, app_data: &'static [u8]) -> PusTcCreator<'static> {
let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), seq_count, 0);
PusTcCreator::new_simple(sph, 17, 1, app_data, CreatorConfig::default())
}
fn ping_tc_to_store(
pool: &mut StaticMemoryPool,
buf: &mut [u8],
seq_count: u16,
seq_count: u14,
app_data: &'static [u8],
) -> TcInfo {
let ping_tc = base_ping_tc_simple_ctor(seq_count, app_data);
@@ -949,7 +966,7 @@ mod tests {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(
@@ -959,7 +976,7 @@ mod tests {
.unwrap();
let app_data = &[0, 1, 2];
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, app_data);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), app_data);
scheduler
.insert_unwrapped_and_stored_tc(
UnixTime::new_only_secs(200),
@@ -968,7 +985,7 @@ mod tests {
.unwrap();
let app_data = &[0, 1, 2];
let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, 2, app_data);
let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, u14::new(2), app_data);
scheduler
.insert_unwrapped_and_stored_tc(
UnixTime::new_only_secs(300),
@@ -999,8 +1016,8 @@ mod tests {
packet_idx: 1,
}),
RequestId {
seq_count: 1,
apid: 0,
seq_count: u14::new(1),
apid: u11::new(0),
source_id: 0,
},
),
@@ -1016,8 +1033,8 @@ mod tests {
packet_idx: 2,
}),
RequestId {
seq_count: 2,
apid: 1,
seq_count: u14::new(2),
apid: u11::new(1),
source_id: 5,
},
),
@@ -1035,8 +1052,8 @@ mod tests {
.into(),
RequestId {
source_id: 10,
seq_count: 20,
apid: 23,
seq_count: u14::new(20),
apid: u11::new(23),
},
),
)
@@ -1079,14 +1096,15 @@ mod tests {
let src_id_to_set = 12;
let apid_to_set = 0x22;
let seq_count = 105;
let sp_header = SpHeader::new_for_unseg_tc(apid_to_set, 105, 0);
let sp_header = SpHeader::new_for_unseg_tc(u11::new(apid_to_set), u14::new(105), 0);
let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1);
sec_header.source_id = src_id_to_set;
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, CreatorConfig::default());
let req_id = RequestId::from_tc(&ping_tc);
assert_eq!(req_id.source_id(), src_id_to_set);
assert_eq!(req_id.apid(), apid_to_set);
assert_eq!(req_id.seq_count(), seq_count);
assert_eq!(req_id.apid().value(), apid_to_set);
assert_eq!(req_id.seq_count().value(), seq_count);
assert_eq!(
req_id.as_u64(),
((src_id_to_set as u64) << 32) | (apid_to_set as u64) << 16 | seq_count as u64
@@ -1101,13 +1119,13 @@ mod tests {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, &[]);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1)
.expect("insertion failed");
@@ -1169,13 +1187,13 @@ mod tests {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, &[]);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_1)
.expect("insertion failed");
@@ -1231,13 +1249,13 @@ mod tests {
scheduler.disable();
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, &[]);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1)
.expect("insertion failed");
@@ -1298,7 +1316,7 @@ mod tests {
false,
));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
let info = scheduler
.insert_unwrapped_tc(
@@ -1313,7 +1331,7 @@ mod tests {
let mut read_buf: [u8; 64] = [0; 64];
pool.read(&tc_info_0.addr(), &mut read_buf).unwrap();
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, base_ping_tc_simple_ctor(u14::new(0), &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
@@ -1335,8 +1353,8 @@ mod tests {
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");
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.packet_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(u14::new(0), &[]));
}
#[test]
@@ -1362,8 +1380,8 @@ mod tests {
let read_len = pool.read(&info.addr, &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data");
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.packet_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(u14::new(0), &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
@@ -1387,8 +1405,8 @@ mod tests {
let read_len = pool.read(&addr_vec[0], &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data");
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.packet_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(u14::new(0), &[]));
}
#[test]
@@ -1531,7 +1549,7 @@ mod tests {
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
@@ -1568,7 +1586,7 @@ mod tests {
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
@@ -1594,7 +1612,7 @@ mod tests {
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("inserting tc failed");
@@ -1615,7 +1633,7 @@ mod tests {
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("inserting tc failed");
@@ -1636,15 +1654,15 @@ mod tests {
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("inserting tc failed");
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, &[]);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_1)
.expect("inserting tc failed");
let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, 2, &[]);
let tc_info_2 = ping_tc_to_store(&mut pool, &mut buf, u14::new(2), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_2)
.expect("inserting tc failed");
@@ -1703,7 +1721,7 @@ mod tests {
fn insert_command_with_release_time(
pool: &mut StaticMemoryPool,
scheduler: &mut PusScheduler,
seq_count: u16,
seq_count: u14,
release_secs: u64,
) -> TcInfo {
let mut buf: [u8; 32] = [0; 32];
@@ -1722,8 +1740,10 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let tc_info_0 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 50);
let tc_info_1 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2);
let check_range = |range: Range<UnixTime, Vec<TcInfo>>| {
let mut tcs_in_range = 0;
@@ -1754,9 +1774,11 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 50);
let tc_info_1 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 100);
let tc_info_2 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 150);
let start_stamp = cds::CdsTime::from_unix_time_with_u16_days(
&UnixTime::new_only_secs(100),
cds::SubmillisPrecision::Absent,
@@ -1789,9 +1811,11 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
let tc_info_0 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 50);
let tc_info_1 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 100);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::new(0), 150);
assert_eq!(scheduler.num_scheduled_telecommands(), 3);
let end_stamp = cds::CdsTime::from_unix_time_with_u16_days(
@@ -1824,10 +1848,10 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 200);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 150);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 200);
assert_eq!(scheduler.num_scheduled_telecommands(), 4);
let start_stamp = cds::CdsTime::from_unix_time_with_u16_days(
@@ -1865,8 +1889,8 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2);
let del_res = scheduler.delete_all(&mut pool);
assert!(del_res.is_ok());
@@ -1875,8 +1899,8 @@ mod tests {
// Contrary to reset, this does not disable the scheduler.
assert!(scheduler.is_enabled());
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2);
let del_res = scheduler
.delete_by_time_filter(TimeWindow::<cds::CdsTime>::new_select_all(), &mut pool);
@@ -1894,9 +1918,11 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
let cmd_0_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
let cmd_1_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 150);
assert_eq!(scheduler.num_scheduled_telecommands(), 3);
let start_stamp = cds::CdsTime::from_unix_time_with_u16_days(
&UnixTime::new_only_secs(100),
@@ -1919,9 +1945,11 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
let cmd_0_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
let cmd_1_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 150);
assert_eq!(scheduler.num_scheduled_telecommands(), 3);
let end_stamp = cds::CdsTime::from_unix_time_with_u16_days(
@@ -1945,11 +1973,14 @@ mod tests {
false,
));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let cmd_out_of_range_0 = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
let cmd_out_of_range_0 =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 50);
let cmd_0_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 100);
let cmd_1_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 150);
let cmd_out_of_range_1 =
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 200);
insert_command_with_release_time(&mut pool, &mut scheduler, ZERO_SEQ, 200);
assert_eq!(scheduler.num_scheduled_telecommands(), 4);
let start_stamp = cds::CdsTime::from_unix_time_with_u16_days(
@@ -1982,13 +2013,13 @@ mod tests {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, 0, &[]);
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(100), tc_info_0)
.expect("insertion failed");
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, 1, &[]);
let tc_info_1 = ping_tc_to_store(&mut pool, &mut buf, u14::new(1), &[]);
scheduler
.insert_unwrapped_and_stored_tc(UnixTime::new_only_secs(200), tc_info_1)
.expect("insertion failed");
@@ -2017,12 +2048,12 @@ mod tests {
fn test_generic_insert_app_data_test() {
let time_writer = cds::CdsTime::new_with_u16_days(1, 1);
let sph = SpHeader::new(
PacketId::new(PacketType::Tc, true, 0x002),
PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 5),
PacketId::new(PacketType::Tc, true, u11::new(0x002)),
PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(5)),
0,
);
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, true);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, CreatorConfig::default());
let mut buf: [u8; 64] = [0; 64];
let result = generate_insert_telecommand_app_data(&mut buf, &time_writer, &ping_tc);
assert!(result.is_ok());
@@ -2039,12 +2070,12 @@ mod tests {
fn test_generic_insert_app_data_test_byte_conv_error() {
let time_writer = cds::CdsTime::new_with_u16_days(1, 1);
let sph = SpHeader::new(
PacketId::new(PacketType::Tc, true, 0x002),
PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 5),
PacketId::new(PacketType::Tc, true, u11::new(0x002)),
PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(5)),
0,
);
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, true);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, CreatorConfig::default());
let mut buf: [u8; 16] = [0; 16];
let result = generate_insert_telecommand_app_data(&mut buf, &time_writer, &ping_tc);
assert!(result.is_err());
@@ -2068,12 +2099,12 @@ mod tests {
fn test_generic_insert_app_data_test_as_vec() {
let time_writer = cds::CdsTime::new_with_u16_days(1, 1);
let sph = SpHeader::new(
PacketId::new(PacketType::Tc, true, 0x002),
PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 5),
PacketId::new(PacketType::Tc, true, u11::new(0x002)),
PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(5)),
0,
);
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, true);
let ping_tc = PusTcCreator::new_no_app_data(sph, sec_header, CreatorConfig::default());
let mut buf: [u8; 64] = [0; 64];
generate_insert_telecommand_app_data(&mut buf, &time_writer, &ping_tc).unwrap();
let vec = generate_insert_telecommand_app_data_as_vec(&time_writer, &ping_tc)

View File

@@ -260,11 +260,13 @@ mod tests {
};
use crate::tmtc::PacketSenderWithSharedPool;
use alloc::collections::VecDeque;
use arbitrary_int::traits::Integer;
use arbitrary_int::u14;
use delegate::delegate;
use spacepackets::SpHeader;
use spacepackets::ecss::WritablePusPacket;
use spacepackets::ecss::scheduling::Subservice;
use spacepackets::ecss::tc::PusTcSecondaryHeader;
use spacepackets::ecss::{CreatorConfig, WritablePusPacket};
use spacepackets::time::TimeWriter;
use spacepackets::{
ecss::{tc::PusTcCreator, tm::PusTmReader},
@@ -386,9 +388,10 @@ mod tests {
test_harness: &mut Pus11HandlerWithStoreTester,
subservice: Subservice,
) {
let reply_header = SpHeader::new_for_unseg_tm(TEST_APID, 0, 0);
let reply_header = SpHeader::new_for_unseg_tm(TEST_APID, u14::ZERO, 0);
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], CreatorConfig::default());
let token = test_harness.start_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);
@@ -433,9 +436,9 @@ mod tests {
#[test]
fn test_insert_activity_tc() {
let mut test_harness = Pus11HandlerWithStoreTester::new();
let mut reply_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let mut reply_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new(reply_header, sec_header, &[], true);
let ping_tc = PusTcCreator::new(reply_header, sec_header, &[], CreatorConfig::default());
let req_id_ping_tc = scheduler::RequestId::from_tc(&ping_tc);
let stamper = cds::CdsTime::now_with_u16_days().expect("time provider failed");
let mut sched_app_data: [u8; 64] = [0; 64];
@@ -443,13 +446,13 @@ mod tests {
let ping_raw = ping_tc.to_vec().expect("generating raw tc failed");
sched_app_data[written_len..written_len + ping_raw.len()].copy_from_slice(&ping_raw);
written_len += ping_raw.len();
reply_header = SpHeader::new_for_unseg_tc(TEST_APID, 1, 0);
reply_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(1), 0);
sec_header = PusTcSecondaryHeader::new_simple(11, Subservice::TcInsertActivity as u8);
let enable_scheduling = PusTcCreator::new(
reply_header,
sec_header,
&sched_app_data[..written_len],
true,
CreatorConfig::default(),
);
let token = test_harness.start_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);

View File

@@ -2,9 +2,10 @@ use crate::pus::{
DirectPusPacketHandlerResult, PartialPusHandlingError, PusPacketHandlingError, PusTmVariant,
};
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
use arbitrary_int::u14;
use spacepackets::SpHeader;
use spacepackets::ecss::PusPacket;
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::ecss::{CreatorConfig, PusPacket};
use std::sync::mpsc;
use super::verification::{VerificationReporter, VerificationReportingProvider};
@@ -75,10 +76,14 @@ impl<
// Sequence count will be handled centrally in TM funnel.
// It is assumed that the verification reporter was built with a valid APID, so we use
// the unchecked API here.
let reply_header =
SpHeader::new_for_unseg_tm(self.service_helper.verif_reporter().apid(), 0, 0);
let reply_header = SpHeader::new_for_unseg_tm(
self.service_helper.verif_reporter().apid(),
u14::new(0),
0,
);
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, time_stamp);
let ping_reply = PusTmCreator::new(reply_header, tc_header, &[], true);
let ping_reply =
PusTmCreator::new(reply_header, tc_header, &[], CreatorConfig::default());
if let Err(e) = self
.service_helper
.common
@@ -148,11 +153,12 @@ mod tests {
PartialPusHandlingError, PusPacketHandlingError,
};
use crate::tmtc::PacketSenderWithSharedPool;
use arbitrary_int::u14;
use delegate::delegate;
use spacepackets::SpHeader;
use spacepackets::ecss::PusPacket;
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
use spacepackets::ecss::tm::PusTmReader;
use spacepackets::ecss::{CreatorConfig, PusPacket};
use spacepackets::time::{TimeWriter, cds};
use super::PusService17TestHandler;
@@ -283,9 +289,10 @@ mod tests {
fn ping_test(test_harness: &mut (impl PusTestHarness + SimplePusPacketHandler)) {
// Create a ping TC, verify acceptance.
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
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, CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
@@ -338,9 +345,10 @@ mod tests {
#[test]
fn test_sending_unsupported_service() {
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
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, CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
@@ -359,9 +367,10 @@ mod tests {
#[test]
fn test_sending_custom_subservice() {
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0), 0);
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, CreatorConfig::default());
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();

View File

@@ -82,6 +82,8 @@
//! context involving multiple threads
use crate::params::{Params, WritableToBeBytes};
use crate::pus::{EcssTmSender, EcssTmtcError, source_buffer_large_enough};
use arbitrary_int::traits::Integer as _;
use arbitrary_int::{u3, u11, u14};
use core::fmt::{Debug, Display, Formatter};
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
@@ -90,14 +92,13 @@ use core::mem::size_of;
use delegate::delegate;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use spacepackets::ecss::EcssEnumeration;
use spacepackets::ecss::tc::IsPusTelecommand;
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::{ByteConversionError, CcsdsPacket, PacketId, PacketSequenceCtrl};
use spacepackets::ecss::{CreatorConfig, EcssEnumeration};
use spacepackets::{ByteConversionError, CcsdsPacket, PacketId, PacketSequenceControl};
use spacepackets::{MAX_APID, SpHeader};
pub use spacepackets::ecss::verification::*;
pub use spacepackets::seq_count::SeqCountProviderSimple;
#[cfg(feature = "alloc")]
pub use alloc_mod::*;
@@ -113,9 +114,9 @@ use crate::request::Apid;
#[derive(Debug, Eq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RequestId {
version_number: u8,
version_number: u3,
packet_id: PacketId,
psc: PacketSequenceCtrl,
psc: PacketSequenceControl,
}
impl Display for RequestId {
@@ -157,7 +158,7 @@ impl RequestId {
}
pub fn raw(&self) -> u32 {
((self.version_number as u32) << 29)
((self.version_number.as_u32()) << 29)
| ((self.packet_id.raw() as u32) << 16)
| self.psc.raw() as u32
}
@@ -166,7 +167,7 @@ impl RequestId {
self.packet_id
}
pub fn packet_seq_ctrl(&self) -> PacketSequenceCtrl {
pub fn packet_sequence_control(&self) -> PacketSequenceControl {
self.psc
}
@@ -181,9 +182,9 @@ impl RequestId {
}
let raw = u32::from_be_bytes(buf[0..Self::SIZE_AS_BYTES].try_into().unwrap());
Some(Self {
version_number: ((raw >> 29) & 0b111) as u8,
version_number: u3::new(((raw >> 29) & 0b111) as u8),
packet_id: PacketId::from(((raw >> 16) & 0xffff) as u16),
psc: PacketSequenceCtrl::from((raw & 0xffff) as u16),
psc: PacketSequenceControl::from((raw & 0xffff) as u16),
})
}
}
@@ -191,9 +192,9 @@ impl RequestId {
impl From<u32> for RequestId {
fn from(value: u32) -> Self {
Self {
version_number: ((value >> 29) & 0b111) as u8,
version_number: u3::new(((value >> 29) & 0b111) as u8),
packet_id: PacketId::from(((value >> 16) & 0xffff) as u16),
psc: PacketSequenceCtrl::from((value & 0xffff) as u16),
psc: PacketSequenceControl::from((value & 0xffff) as u16),
}
}
}
@@ -480,26 +481,19 @@ pub trait VerificationReportingProvider {
#[derive(Debug, Clone)]
pub struct VerificationReportCreator {
pub dest_id: u16,
apid: u16,
apid: u11,
}
impl VerificationReportCreator {
pub fn new(apid: u16) -> Option<Self> {
if apid > MAX_APID {
return None;
}
Some(Self { apid, dest_id: 0 })
pub fn new(apid: u11) -> Self {
Self { apid, dest_id: 0 }
}
pub fn set_apid(&mut self, apid: u16) -> bool {
if apid > MAX_APID {
return false;
}
pub fn set_apid(&mut self, apid: u11) {
self.apid = apid;
true
}
pub fn apid(&self) -> u16 {
pub fn apid(&self) -> u11 {
self.apid
}
@@ -511,7 +505,9 @@ impl VerificationReportCreator {
self.dest_id = dest_id;
}
pub fn read_request_id(&self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> RequestId {
/// Initialize verification handling by passing a TC reference. This returns a token required
/// to call the acceptance functions
pub fn read_request_id_from_tc(pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> RequestId {
RequestId::new(pus_tc)
}
@@ -520,7 +516,7 @@ impl VerificationReportCreator {
src_data_buf: &'src_data mut [u8],
subservice: u8,
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
time_stamp: &'time [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -543,7 +539,7 @@ impl VerificationReportCreator {
src_data_buf: &'src_data mut [u8],
subservice: u8,
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
step: Option<&(impl EcssEnumeration + ?Sized)>,
params: &FailParams<'time, '_>,
@@ -565,7 +561,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
time_stamp: &'time [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -585,7 +581,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
params: FailParams<'time, '_>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -607,7 +603,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
time_stamp: &'time [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -630,7 +626,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
params: FailParams<'time, '_>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -652,7 +648,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
time_stamp: &'time [u8],
step: impl EcssEnumeration,
@@ -676,7 +672,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcStateStarted>,
seq_count: u16,
seq_count: u14,
msg_count: u16,
params: FailParamsWithStep<'time, '_>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -699,7 +695,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_counter: u16,
seq_counter: u14,
msg_counter: u16,
time_stamp: &'time [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -721,7 +717,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
request_id: &RequestId,
seq_count: u16,
seq_count: u14,
msg_count: u16,
params: FailParams<'time, '_>,
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
@@ -742,7 +738,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
subservice: u8,
seq_count: u16,
seq_count: u14,
msg_counter: u16,
req_id: &RequestId,
time_stamp: &'time [u8],
@@ -778,7 +774,7 @@ impl VerificationReportCreator {
&self,
src_data_buf: &'src_data mut [u8],
subservice: u8,
seq_count: u16,
seq_count: u14,
msg_counter: u16,
req_id: &RequestId,
step: Option<&(impl EcssEnumeration + ?Sized)>,
@@ -830,13 +826,14 @@ impl VerificationReportCreator {
sp_header,
tm_sec_header,
&src_data_buf[0..source_data_len],
true,
CreatorConfig::default(),
)
}
}
#[cfg(feature = "alloc")]
pub mod alloc_mod {
use arbitrary_int::u11;
use spacepackets::ecss::PusError;
use super::*;
@@ -845,7 +842,7 @@ pub mod alloc_mod {
#[derive(Clone)]
pub struct VerificationReporterConfig {
apid: u16,
apid: u11,
pub step_field_width: usize,
pub fail_code_field_width: usize,
pub max_fail_data_len: usize,
@@ -853,7 +850,7 @@ pub mod alloc_mod {
impl VerificationReporterConfig {
pub fn new(
apid: u16,
apid: u11,
step_field_width: usize,
fail_code_field_width: usize,
max_fail_data_len: usize,
@@ -901,13 +898,13 @@ pub mod alloc_mod {
> {
owner_id: ComponentId,
source_data_buf: RefCell<alloc::vec::Vec<u8>>,
pub report_creator: VerificationReportCreator,
pub reporter_creator: VerificationReportCreator,
pub tm_hook: VerificationHookInstance,
}
impl VerificationReporter<DummyVerificationHook> {
pub fn new(owner_id: ComponentId, cfg: &VerificationReporterConfig) -> Self {
let reporter = VerificationReportCreator::new(cfg.apid).unwrap();
let reporter = VerificationReportCreator::new(cfg.apid);
Self {
owner_id,
source_data_buf: RefCell::new(alloc::vec![
@@ -917,7 +914,7 @@ pub mod alloc_mod {
+ cfg.fail_code_field_width
+ cfg.max_fail_data_len
]),
report_creator: reporter,
reporter_creator: reporter,
tm_hook: DummyVerificationHook::default(),
}
}
@@ -931,7 +928,7 @@ pub mod alloc_mod {
cfg: &VerificationReporterConfig,
tm_hook: VerificationHookInstance,
) -> Self {
let reporter = VerificationReportCreator::new(cfg.apid).unwrap();
let reporter = VerificationReportCreator::new(cfg.apid);
Self {
owner_id,
source_data_buf: RefCell::new(alloc::vec![
@@ -941,7 +938,7 @@ pub mod alloc_mod {
+ cfg.fail_code_field_width
+ cfg.max_fail_data_len
]),
report_creator: reporter,
reporter_creator: reporter,
tm_hook,
}
}
@@ -950,7 +947,9 @@ pub mod alloc_mod {
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(self.report_creator.read_request_id(pus_tc))
VerificationToken::<TcStateNone>::new(
VerificationReportCreator::read_request_id_from_tc(pus_tc),
)
}
pub fn start_verification_with_req_id(
@@ -961,9 +960,9 @@ pub mod alloc_mod {
}
delegate!(
to self.report_creator {
pub fn set_apid(&mut self, apid: u16) -> bool;
pub fn apid(&self) -> u16;
to self.reporter_creator {
pub fn set_apid(&mut self, apid: u11);
pub fn apid(&self) -> u11;
pub fn dest_id(&self) -> u16;
pub fn set_dest_id(&mut self, dest_id: u16);
}
@@ -978,7 +977,7 @@ pub mod alloc_mod {
for VerificationReporter<VerificationHookInstance>
{
delegate!(
to self.report_creator {
to self.reporter_creator {
fn set_apid(&mut self, apid: Apid);
fn apid(&self) -> Apid;
}
@@ -1004,11 +1003,11 @@ pub mod alloc_mod {
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
let mut source_data_buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.reporter_creator
.acceptance_success(
source_data_buf.as_mut_slice(),
&token.request_id(),
0,
u14::new(0),
0,
time_stamp,
)
@@ -1027,8 +1026,14 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.acceptance_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
.reporter_creator
.acceptance_failure(
buf.as_mut_slice(),
&token.request_id(),
u14::new(0),
0,
params,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@@ -1046,8 +1051,14 @@ pub mod alloc_mod {
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.start_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
.reporter_creator
.start_success(
buf.as_mut_slice(),
&token.request_id(),
u14::new(0),
0,
time_stamp,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@@ -1066,8 +1077,14 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.start_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
.reporter_creator
.start_failure(
buf.as_mut_slice(),
&token.request_id(),
u14::new(0),
0,
params,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@@ -1086,11 +1103,11 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.reporter_creator
.step_success(
buf.as_mut_slice(),
&token.request_id(),
0,
u14::new(0),
0,
time_stamp,
step,
@@ -1113,8 +1130,8 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.step_failure(buf.as_mut_slice(), token, 0, 0, params)
.reporter_creator
.step_failure(buf.as_mut_slice(), token, u14::new(0), 0, params)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@@ -1134,8 +1151,14 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.completion_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
.reporter_creator
.completion_success(
buf.as_mut_slice(),
&token.request_id(),
u14::new(0),
0,
time_stamp,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id, PusTmVariant::Direct(tm_creator))?;
@@ -1154,8 +1177,14 @@ pub mod alloc_mod {
) -> Result<(), EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.report_creator
.completion_failure(buf.as_mut_slice(), &token.request_id(), 0, 00, params)
.reporter_creator
.completion_failure(
buf.as_mut_slice(),
&token.request_id(),
u14::new(0),
0,
params,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@@ -1305,6 +1334,7 @@ pub fn handle_step_failure_with_generic_params(
#[cfg(any(feature = "test_util", test))]
pub mod test_util {
use alloc::vec::Vec;
use arbitrary_int::u11;
use core::cell::RefCell;
use std::collections::VecDeque;
@@ -1366,7 +1396,7 @@ pub mod test_util {
fn set_apid(&mut self, _apid: Apid) {}
fn apid(&self) -> Apid {
0
u11::new(0)
}
fn acceptance_success(
@@ -1694,15 +1724,17 @@ pub mod tests {
};
use crate::pus::{ChannelWithId, PusTmVariant};
use crate::request::MessageMetadata;
use crate::spacepackets::seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProvider};
use crate::spacepackets::seq_count::{SequenceCounter, SequenceCounterCcsdsSimple};
use crate::tmtc::{PacketSenderWithSharedPool, SharedPacketPool};
use alloc::format;
use alloc::string::ToString;
use arbitrary_int::{u11, u14};
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
use spacepackets::ecss::{
EcssEnumU8, EcssEnumU16, EcssEnumU32, EcssEnumeration, PusError, PusPacket,
CreatorConfig, EcssEnumU8, EcssEnumU16, EcssEnumU32, EcssEnumeration, PusError, PusPacket,
WritablePusPacket,
};
use spacepackets::seq_count::SequenceCounterSimple;
use spacepackets::util::UnsignedEnum;
use spacepackets::{ByteConversionError, SpHeader};
use std::cell::RefCell;
@@ -1712,8 +1744,8 @@ pub mod tests {
use std::vec::Vec;
use super::{
DummyVerificationHook, FailParamHelper, SeqCountProviderSimple, TcStateAccepted,
TcStateStarted, VerificationHook, VerificationReportingProvider, WasAtLeastAccepted,
DummyVerificationHook, FailParamHelper, TcStateAccepted, TcStateStarted, VerificationHook,
VerificationReportingProvider, WasAtLeastAccepted,
handle_completion_failure_with_generic_params,
};
@@ -1779,13 +1811,13 @@ pub mod tests {
#[derive(Default)]
pub struct SequenceCounterHook {
pub seq_counter: CcsdsSimpleSeqCountProvider,
pub msg_counter: SeqCountProviderSimple<u16>,
pub seq_counter: SequenceCounterCcsdsSimple,
pub msg_counter: SequenceCounterSimple<u16>,
}
impl VerificationHook for SequenceCounterHook {
fn modify_tm(&self, tm: &mut spacepackets::ecss::tm::PusTmCreator) {
tm.set_seq_count(self.seq_counter.get_and_increment());
tm.set_seq_count(u14::new(self.seq_counter.get_and_increment()));
tm.set_msg_counter(self.msg_counter.get_and_increment());
}
}
@@ -1908,7 +1940,14 @@ pub mod tests {
fn check_acceptance_success(&self, timestamp: &[u8; 7]) {
let cmp_info = TmInfo {
requestor: MessageMetadata::new(self.request_id.into(), self.id),
common: CommonTmInfo::new(1, TEST_APID, 0, 0, self.reporter.dest_id(), timestamp),
common: CommonTmInfo::new(
1,
TEST_APID,
u14::new(0),
0,
self.reporter.dest_id(),
timestamp,
),
additional_data: None,
};
let mut service_queue = self.sender.service_queue.borrow_mut();
@@ -1917,7 +1956,7 @@ pub mod tests {
assert_eq!(info, cmp_info);
}
fn check_start_success(&mut self, seq_count: u16, msg_counter: u16, timestamp: &[u8]) {
fn check_start_success(&mut self, seq_count: u14, msg_counter: u16, timestamp: &[u8]) {
let mut srv_queue = self.sender.service_queue.borrow_mut();
let cmp_info = TmInfo {
requestor: MessageMetadata::new(self.request_id.into(), self.id),
@@ -1935,7 +1974,7 @@ pub mod tests {
assert_eq!(info, cmp_info);
}
fn check_completion_success(&mut self, seq_count: u16, msg_counter: u16) {
fn check_completion_success(&mut self, seq_count: u14, msg_counter: u16) {
let cmp_info = TmInfo {
requestor: MessageMetadata::new(self.request_id.into(), self.id),
common: CommonTmInfo::new(
@@ -1968,7 +2007,14 @@ pub mod tests {
fn check_acceptance_failure(&mut self, timestamp: &[u8; 7]) {
let cmp_info = TmInfo {
requestor: MessageMetadata::new(self.request_id.into(), self.id),
common: CommonTmInfo::new(2, TEST_APID, 0, 0, self.reporter.dest_id(), timestamp),
common: CommonTmInfo::new(
2,
TEST_APID,
u14::new(0),
0,
self.reporter.dest_id(),
timestamp,
),
additional_data: Some([0, 2].to_vec()),
};
let service_queue = self.sender.service_queue.get_mut();
@@ -2056,9 +2102,9 @@ pub mod tests {
}
fn create_generic_ping() -> PusTcCreator<'static> {
let sph = SpHeader::new_for_unseg_tc(TEST_APID, 0x34, 0);
let sph = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(0x34), 0);
let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
PusTcCreator::new(sph, tc_header, &[], true)
PusTcCreator::new(sph, tc_header, &[], CreatorConfig::default())
}
#[test]
@@ -2078,8 +2124,8 @@ pub mod tests {
fn test_state() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
assert_eq!(testbench.reporter.apid(), TEST_APID);
testbench.reporter.set_apid(TEST_APID + 1);
assert_eq!(testbench.reporter.apid(), TEST_APID + 1);
testbench.reporter.set_apid(u11::new(TEST_APID.value() + 1));
assert_eq!(testbench.reporter.apid().value(), TEST_APID.value() + 1);
}
#[test]
@@ -2229,7 +2275,7 @@ pub mod tests {
.expect("step 1 failed");
assert_eq!(testbench.sender.service_queue.borrow().len(), 4);
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(0, 0, &EMPTY_STAMP);
testbench.check_start_success(u14::new(0), 0, &EMPTY_STAMP);
testbench.check_step_success(0, &EMPTY_STAMP);
testbench.check_step_success(1, &EMPTY_STAMP);
}
@@ -2263,7 +2309,7 @@ pub mod tests {
.step_failure(started_token, fail_params)
.expect("Step failure failed");
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(0, 0, DUMMY_STAMP);
testbench.check_start_success(u14::new(0), 0, DUMMY_STAMP);
testbench.check_step_success(0, &EMPTY_STAMP);
testbench.check_step_failure(&fail_step, &fail_code, &fail_data_raw);
}
@@ -2285,7 +2331,7 @@ pub mod tests {
.completion_failure(started_token, fail_params)
.expect("Completion failure");
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(0, 0, DUMMY_STAMP);
testbench.check_start_success(u14::new(0), 0, DUMMY_STAMP);
testbench.check_completion_failure(&fail_code, &[]);
}
@@ -2305,8 +2351,8 @@ pub mod tests {
.completion_success(started_token, &EMPTY_STAMP)
.expect("Sending completion success failed");
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(0, 0, DUMMY_STAMP);
testbench.check_completion_success(0, 0);
testbench.check_start_success(u14::new(0), 0, DUMMY_STAMP);
testbench.check_completion_success(u14::new(0), 0);
}
#[test]
@@ -2327,8 +2373,8 @@ pub mod tests {
.completion_success(started_token, &EMPTY_STAMP)
.expect("Sending completion success failed");
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(1, 1, DUMMY_STAMP);
testbench.check_completion_success(2, 2);
testbench.check_start_success(u14::new(1), 1, DUMMY_STAMP);
testbench.check_completion_success(u14::new(2), 2);
}
#[test]
@@ -2387,7 +2433,7 @@ pub mod tests {
);
assert!(result.unwrap());
testbench.check_acceptance_success(&EMPTY_STAMP);
testbench.check_start_success(0, 0, &EMPTY_STAMP);
testbench.check_start_success(u14::new(0), 0, &EMPTY_STAMP);
testbench.check_step_failure(&step, &fail_code, fail_data.as_bytes());
}

View File

@@ -1,3 +1,4 @@
use arbitrary_int::{traits::Integer as _, u11};
use core::{fmt, marker::PhantomData};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -22,8 +23,8 @@ use crate::{
/// for them. This can be useful for tasks like tracking their progress.
pub type RequestId = u32;
/// CCSDS APID type definition. Please note that the APID is a 14 bit value.
pub type Apid = u16;
/// CCSDS APID type definition. Please note that the APID is a 11 bit value.
pub type Apid = u11;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct UniqueApidTargetId {
@@ -40,7 +41,7 @@ impl UniqueApidTargetId {
}
pub fn raw(&self) -> ComponentId {
((self.apid as u64) << 32) | (self.unique_id as u64)
((self.apid.as_u64()) << 32) | (self.unique_id as u64)
}
pub fn id(&self) -> ComponentId {
@@ -68,7 +69,7 @@ impl UniqueApidTargetId {
impl From<u64> for UniqueApidTargetId {
fn from(raw: u64) -> Self {
Self {
apid: (raw >> 32) as u16,
apid: u11::new((raw >> 32) as u16),
unique_id: raw as u32,
}
}
@@ -495,16 +496,19 @@ pub mod std_mod {
mod tests {
use std::sync::mpsc;
use alloc::string::ToString;
use spacepackets::{
ByteConversionError, SpHeader,
ecss::tc::{PusTcCreator, PusTcSecondaryHeader},
};
use crate::{
queue::{GenericReceiveError, GenericSendError},
request::{MessageMetadata, MessageSenderMap, MessageSenderStoreProvider},
};
use alloc::string::ToString;
use arbitrary_int::{u11, u14};
use spacepackets::{
ByteConversionError, SpHeader,
ecss::{
CreatorConfig,
tc::{PusTcCreator, PusTcSecondaryHeader},
},
};
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
@@ -514,8 +518,8 @@ mod tests {
#[test]
fn test_basic_target_id_with_apid() {
let id = UniqueApidTargetId::new(0x111, 0x01);
assert_eq!(id.apid, 0x111);
let id = UniqueApidTargetId::new(u11::new(0x111), 0x01);
assert_eq!(id.apid.value(), 0x111);
assert_eq!(id.unique_id, 0x01);
assert_eq!(id.id(), id.raw());
assert_eq!(u64::from(id), id.raw());
@@ -532,19 +536,20 @@ mod tests {
#[test]
fn test_basic_target_id_with_apid_from_pus_tc() {
let sp_header = SpHeader::new_for_unseg_tc(0x111, 5, 0);
let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x111), u14::new(5), 0);
let app_data = 1_u32.to_be_bytes();
let pus_tc = PusTcCreator::new_simple(sp_header, 17, 1, &app_data, true);
let pus_tc =
PusTcCreator::new_simple(sp_header, 17, 1, &app_data, CreatorConfig::default());
let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
assert_eq!(id.apid, 0x111);
assert_eq!(id.apid.value(), 0x111);
assert_eq!(id.unique_id, 1);
}
#[test]
fn test_basic_target_id_with_apid_from_pus_tc_invalid_app_data() {
let sp_header = SpHeader::new_for_unseg_tc(0x111, 5, 0);
let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x111), u14::new(5), 0);
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let pus_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
let pus_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, CreatorConfig::default());
let error = UniqueApidTargetId::from_pus_tc(&pus_tc);
assert!(error.is_err());
let error = error.unwrap_err();

View File

@@ -1,15 +1,16 @@
use arbitrary_int::{u11, u14};
use spacepackets::SpHeader;
use spacepackets::ecss::CreatorConfig;
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
use spacepackets::time::TimeWriter;
use spacepackets::time::cds::CdsTime;
pub struct PusTmWithCdsShortHelper {
apid: u16,
apid: u11,
cds_short_buf: [u8; 7],
}
impl PusTmWithCdsShortHelper {
pub fn new(apid: u16) -> Self {
pub fn new(apid: u11) -> Self {
Self {
apid,
cds_short_buf: [0; 7],
@@ -22,7 +23,7 @@ impl PusTmWithCdsShortHelper {
service: u8,
subservice: u8,
source_data: &'data [u8],
seq_count: u16,
seq_count: u14,
) -> PusTmCreator<'_, 'data> {
let time_stamp = CdsTime::now_with_u16_days().unwrap();
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
@@ -35,7 +36,7 @@ impl PusTmWithCdsShortHelper {
subservice: u8,
source_data: &'data [u8],
stamper: &CdsTime,
seq_count: u16,
seq_count: u14,
) -> PusTmCreator<'_, 'data> {
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
self.create_pus_tm_common(service, subservice, source_data, seq_count)
@@ -46,11 +47,16 @@ impl PusTmWithCdsShortHelper {
service: u8,
subservice: u8,
source_data: &'data [u8],
seq_count: u16,
seq_count: u14,
) -> PusTmCreator<'_, 'data> {
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);
PusTmCreator::new(reply_header, tc_header, source_data, true)
PusTmCreator::new(
reply_header,
tc_header,
source_data,
CreatorConfig::default(),
)
}
}
@@ -58,28 +64,29 @@ impl PusTmWithCdsShortHelper {
mod tests {
use spacepackets::{CcsdsPacket, ecss::PusPacket, time::cds::CdsTime};
use super::PusTmWithCdsShortHelper;
use super::*;
#[test]
fn test_helper_with_stamper() {
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123);
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(u11::new(0x123));
let stamper = CdsTime::new_with_u16_days(0, 0);
let tm = pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, 25);
let tm =
pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, u14::new(25));
assert_eq!(tm.service(), 17);
assert_eq!(tm.subservice(), 1);
assert_eq!(tm.user_data(), &[1, 2, 3, 4]);
assert_eq!(tm.seq_count(), 25);
assert_eq!(tm.seq_count().value(), 25);
assert_eq!(tm.timestamp(), [64, 0, 0, 0, 0, 0, 0])
}
#[test]
fn test_helper_from_now() {
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123);
let tm = pus_tm_helper.create_pus_tm_timestamp_now(17, 1, &[1, 2, 3, 4], 25);
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(u11::new(0x123));
let tm = pus_tm_helper.create_pus_tm_timestamp_now(17, 1, &[1, 2, 3, 4], u14::new(25));
assert_eq!(tm.service(), 17);
assert_eq!(tm.subservice(), 1);
assert_eq!(tm.user_data(), &[1, 2, 3, 4]);
assert_eq!(tm.seq_count(), 25);
assert_eq!(tm.seq_count().value(), 25);
assert_eq!(tm.timestamp().len(), 7);
}
}

View File

@@ -2,8 +2,8 @@
use core::mem::size_of;
use serde::{Deserialize, Serialize};
use spacepackets::ecss::{PfcReal, PfcUnsigned, Ptc};
use spacepackets::time::CcsdsTimeProvider;
use spacepackets::time::cds::CdsTime;
use spacepackets::time::{CcsdsTimeProvider, TimeWriter};
enum NumOfParamsInfo {
/// The parameter entry is a scalar field

View File

@@ -1,3 +1,4 @@
use arbitrary_int::u11;
use satrs::event_man::{
EventManagerWithMpsc, EventMessage, EventMessageU32, EventRoutingError, EventSendProvider,
EventU32SenderMpsc,
@@ -8,15 +9,15 @@ use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
use satrs::pus::event_man::{DefaultPusEventReportingMap, EventReporter, PusEventTmCreatorWithMap};
use satrs::request::UniqueApidTargetId;
use satrs::tmtc::PacketAsVec;
use spacepackets::ecss::PusError;
use spacepackets::ecss::tm::PusTmReader;
use spacepackets::ecss::{PusError, PusPacket};
use std::sync::mpsc::{self, SendError, TryRecvError};
use std::thread;
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityInfo>::new(1, 0);
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
const EMPTY_STAMP: [u8; 7] = [0; 7];
const TEST_APID: u16 = 0x02;
const TEST_APID: u11 = u11::new(0x02);
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
#[derive(Debug, Clone)]
@@ -35,8 +36,8 @@ fn test_threaded_usage() {
event_man.subscribe_all(pus_event_man_send_provider.target_id());
event_man.add_sender(pus_event_man_send_provider);
let (event_packet_tx, event_packet_rx) = mpsc::channel::<PacketAsVec>();
let reporter =
EventReporter::new(TEST_ID.raw(), 0x02, 0, 128).expect("Creating event reporter failed");
let reporter = EventReporter::new(TEST_ID.raw(), u11::new(0x02), 0, 128)
.expect("Creating event reporter failed");
let pus_event_man =
PusEventTmCreatorWithMap::new(reporter, DefaultPusEventReportingMap::default());
let error_handler = |event_msg: &EventMessageU32, error: EventRoutingError| {

View File

@@ -1,5 +1,7 @@
#[cfg(feature = "crossbeam")]
pub mod crossbeam_test {
use arbitrary_int::traits::Integer as _;
use arbitrary_int::u14;
use hashbrown::HashMap;
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
@@ -11,7 +13,7 @@ pub mod crossbeam_test {
use spacepackets::SpHeader;
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
use spacepackets::ecss::tm::PusTmReader;
use spacepackets::ecss::{EcssEnumU8, EcssEnumU16, PusPacket, WritablePusPacket};
use spacepackets::ecss::{CreatorConfig, EcssEnumU8, EcssEnumU16, WritablePusPacket};
use std::sync::RwLock;
use std::thread;
use std::time::Duration;
@@ -57,9 +59,9 @@ pub mod crossbeam_test {
let (tx_tc_1, rx_tc_1) = crossbeam_channel::bounded(3);
{
let mut tc_guard = shared_tc_pool.write().unwrap();
let sph = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sph = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
let pus_tc_0 = PusTcCreator::new_no_app_data(sph, tc_header, true);
let pus_tc_0 = PusTcCreator::new_no_app_data(sph, tc_header, CreatorConfig::default());
req_id_0 = RequestId::new(&pus_tc_0);
let addr = tc_guard
.free_element(pus_tc_0.len_written(), |buf| {
@@ -67,9 +69,9 @@ pub mod crossbeam_test {
})
.unwrap();
tx_tc_0.send(addr).unwrap();
let sph = SpHeader::new_for_unseg_tc(TEST_APID, 1, 0);
let sph = SpHeader::new_for_unseg_tc(TEST_APID, u14::new(1), 0);
let tc_header = PusTcSecondaryHeader::new_simple(5, 1);
let pus_tc_1 = PusTcCreator::new_no_app_data(sph, tc_header, true);
let pus_tc_1 = PusTcCreator::new_no_app_data(sph, tc_header, CreatorConfig::default());
req_id_1 = RequestId::new(&pus_tc_1);
let addr = tc_guard
.free_element(pus_tc_0.len_written(), |buf| {

View File

@@ -21,6 +21,7 @@ use std::{
thread,
};
use arbitrary_int::{traits::Integer, u11, u14};
use hashbrown::HashSet;
use satrs::{
ComponentId,
@@ -36,7 +37,7 @@ use satrs::{
};
use spacepackets::{
CcsdsPacket, PacketId, SpHeader,
ecss::{WritablePusPacket, tc::PusTcCreator},
ecss::{CreatorConfig, WritablePusPacket, tc::PusTcCreator},
};
use std::{collections::VecDeque, sync::Arc, vec::Vec};
@@ -192,7 +193,7 @@ fn test_cobs_server() {
matches!(tc_receiver.try_recv(), Err(mpsc::TryRecvError::Empty));
}
const TEST_APID_0: u16 = 0x02;
const TEST_APID_0: u11 = u11::new(0x02);
const TEST_PACKET_ID_0: PacketId = PacketId::new_for_tc(true, TEST_APID_0);
#[derive(Default)]
@@ -217,8 +218,8 @@ impl SpacePacketValidator for SimpleVerificator {
fn test_ccsds_server() {
let (tc_sender, tc_receiver) = mpsc::channel();
let mut tm_source = SyncTmSource::default();
let sph = SpHeader::new_for_unseg_tc(TEST_APID_0, 0, 0);
let verif_tm = PusTcCreator::new_simple(sph, 1, 1, &[], true);
let sph = SpHeader::new_for_unseg_tc(TEST_APID_0, u14::new(0), 0);
let verif_tm = PusTcCreator::new_simple(sph, 1, 1, &[], CreatorConfig::default());
let tm_0 = verif_tm.to_vec().expect("tm generation failed");
tm_source.add_tm(&tm_0);
let mut packet_id_lookup = SimpleVerificator::default();
@@ -267,8 +268,8 @@ fn test_ccsds_server() {
.expect("setting reas timeout failed");
// Send ping telecommand.
let sph = SpHeader::new_for_unseg_tc(TEST_APID_0, 0, 0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
let sph = SpHeader::new_for_unseg_tc(TEST_APID_0, u14::ZERO, 0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default());
let tc_0 = ping_tc.to_vec().expect("packet creation failed");
stream
.write_all(&tc_0)