Merge branch 'main' into request-reply-messaging-mode-tree
Some checks are pending
Rust/sat-rs/pipeline/pr-main Build queued...

This commit is contained in:
Robin Müller 2024-03-25 16:14:41 +01:00
commit ce5d333962
18 changed files with 745 additions and 512 deletions

2
.gitignore vendored
View File

@ -3,5 +3,7 @@ target/
output.log output.log
/Cargo.lock /Cargo.lock
output.log
/.idea/* /.idea/*
!/.idea/runConfigurations !/.idea/runConfigurations

View File

@ -0,0 +1,28 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# uncomment ONE of these three option to make `cargo run` start a GDB session
# which option to pick depends on your system
# You can also replace openocd.gdb by jlink.gdb when using a J-Link.
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
# runner = "gdb-multiarch -q -x openocd.gdb"
# runner = "gdb -q -x openocd.gdb"
# runner = "probe-run --chip STM32F303VCTx --connect-under-reset"
rustflags = [
# LLD (shipped with the Rust toolchain) is used as the default linker
"-C", "link-arg=-Tlink.x",
# if you run into problems with LLD switch to the GNU linker by commenting out
# this line
# "-C", "linker=arm-none-eabi-ld",
# if you need to link to pre-compiled C libraries provided by a C toolchain
# use GCC as the linker by commenting out both lines above and then
# uncommenting the three lines below
# "-C", "linker=arm-none-eabi-gcc",
# "-C", "link-arg=-Wl,-Tlink.x",
# "-C", "link-arg=-nostartfiles",
]
[build]
# comment out the following line if you intend to run unit tests on host machine
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)

View File

@ -1,3 +1,4 @@
/target /target
/itm.txt /itm.txt
/.cargo/config* /.cargo/config*
/.vscode

View File

@ -1,3 +0,0 @@
{
"cortex-debug.gdbPath.linux": "gdb-multiarch"
}

View File

@ -13,9 +13,9 @@ dependencies = [
[[package]] [[package]]
name = "atomic-polyfill" name = "atomic-polyfill"
version = "0.1.11" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [ dependencies = [
"critical-section", "critical-section",
] ]
@ -55,20 +55,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bxcan" name = "bxcan"
version = "0.6.2" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b13b4b2ea9ab2ba924063ebb86ad895cb79f4a79bf90f27949eb20c335b30f9" checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"nb 1.0.0", "embedded-hal 0.2.7",
"nb 1.1.0",
"vcell", "vcell",
] ]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cast" name = "cast"
@ -87,31 +88,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.23" version = "0.4.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
dependencies = [ dependencies = [
"num-integer",
"num-traits", "num-traits",
] ]
[[package]] [[package]]
name = "cortex-m" name = "cobs"
version = "0.7.6" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "cobs"
version = "0.2.3"
source = "git+https://github.com/robamu/cobs.rs.git?branch=all_features#c70a7f30fd00a7cbdb7666dec12b437977385d40"
[[package]]
name = "cortex-m"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
dependencies = [ dependencies = [
"bare-metal 0.2.5", "bare-metal 0.2.5",
"bitfield", "bitfield",
"embedded-hal", "critical-section",
"embedded-hal 0.2.7",
"volatile-register", "volatile-register",
] ]
[[package]] [[package]]
name = "cortex-m-rt" name = "cortex-m-rt"
version = "0.7.2" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6d3328b8b5534f0c90acd66b68950f2763b37e0173cac4d8b4937c4a80761f9" checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1"
dependencies = [ dependencies = [
"cortex-m-rt-macros", "cortex-m-rt-macros",
] ]
@ -124,48 +136,35 @@ checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
name = "cortex-m-rtic" name = "crc"
version = "1.1.3" version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6b82f1c39acd6c3a35c2013b6110c20f5bc534522791fabadeed49ccada2dce" checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
dependencies = [ dependencies = [
"bare-metal 1.0.0", "crc-catalog",
"cortex-m",
"cortex-m-rtic-macros",
"heapless",
"rtic-core",
"rtic-monotonic",
"version_check",
] ]
[[package]] [[package]]
name = "cortex-m-rtic-macros" name = "crc-catalog"
version = "1.1.5" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8e9645ef54bec1cf70ac33e9bf9566e6507ab5b41ae6baf3735662194e8607" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"rtic-syntax",
"syn",
]
[[package]] [[package]]
name = "critical-section" name = "critical-section"
version = "1.1.1" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.14.2" version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"darling_macro", "darling_macro",
@ -173,26 +172,37 @@ dependencies = [
[[package]] [[package]]
name = "darling_core" name = "darling_core"
version = "0.14.2" version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
dependencies = [ dependencies = [
"fnv", "fnv",
"ident_case", "ident_case",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.53",
] ]
[[package]] [[package]]
name = "darling_macro" name = "darling_macro"
version = "0.14.2" version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn", "syn 2.0.53",
]
[[package]]
name = "delegate"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee5df75c70b95bd3aacc8e2fd098797692fb1d54121019c4de481e42f04c8a1"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
] ]
[[package]] [[package]]
@ -214,6 +224,12 @@ dependencies = [
"void", "void",
] ]
[[package]]
name = "embedded-hal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
[[package]] [[package]]
name = "embedded-time" name = "embedded-time"
version = "0.12.1" version = "0.12.1"
@ -225,25 +241,31 @@ dependencies = [
[[package]] [[package]]
name = "enumset" name = "enumset"
version = "1.0.12" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
dependencies = [ dependencies = [
"enumset_derive", "enumset_derive",
] ]
[[package]] [[package]]
name = "enumset_derive" name = "enumset_derive"
version = "0.6.1" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.53",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -252,18 +274,42 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "fugit" name = "fugit"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab17bb279def6720d058cb6c052249938e7f99260ab534879281a95367a87e5" checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
dependencies = [ dependencies = [
"gcd", "gcd",
] ]
[[package]] [[package]]
name = "gcd" name = "futures-core"
version = "2.2.0" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4b1b088ad0a967aa29540456b82fc8903f854775d33f71e9709c4efb3dfbfd2" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "gcd"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]] [[package]]
name = "generic-array" name = "generic-array"
@ -276,9 +322,9 @@ dependencies = [
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.6" version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [ dependencies = [
"typenum", "typenum",
"version_check", "version_check",
@ -286,29 +332,26 @@ dependencies = [
[[package]] [[package]]
name = "hash32" name = "hash32"
version = "0.2.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [ dependencies = [
"byteorder", "byteorder",
] ]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heapless" name = "heapless"
version = "0.7.16" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [ dependencies = [
"atomic-polyfill",
"hash32", "hash32",
"rustc_version 0.4.0",
"spin",
"stable_deref_trait", "stable_deref_trait",
] ]
@ -320,40 +363,28 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.2" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"autocfg", "equivalent",
"hashbrown", "hashbrown",
] ]
[[package]] [[package]]
name = "itm_logger" name = "itm_logger"
version = "0.1.3-pre.0" version = "0.1.3-alpha.0"
source = "git+https://github.com/robamu/itm_logger.rs.git?branch=all_features#83ee7a6c57f525a70d0cc5bb7e65826d0ce938a0"
dependencies = [ dependencies = [
"cortex-m", "cortex-m",
"log", "log",
] ]
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "lsm303dlhc" name = "lsm303dlhc"
@ -362,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5d1a5c290951321d1b0d4a40edd828537de9889134a0e67c5146542ae57706" checksum = "9e5d1a5c290951321d1b0d4a40edd828537de9889134a0e67c5146542ae57706"
dependencies = [ dependencies = [
"cast", "cast",
"embedded-hal", "embedded-hal 0.2.7",
"generic-array 0.11.2", "generic-array 0.11.2",
] ]
@ -372,7 +403,7 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94" checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
dependencies = [ dependencies = [
"generic-array 0.14.6", "generic-array 0.14.7",
] ]
[[package]] [[package]]
@ -381,14 +412,14 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [ dependencies = [
"nb 1.0.0", "nb 1.1.0",
] ]
[[package]] [[package]]
name = "nb" name = "nb"
version = "1.0.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]] [[package]]
name = "num" name = "num"
@ -414,19 +445,18 @@ dependencies = [
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [ dependencies = [
"autocfg",
"num-traits", "num-traits",
] ]
[[package]] [[package]]
name = "num-iter" name = "num-iter"
version = "0.1.43" version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -446,13 +476,33 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_enum"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]] [[package]]
name = "panic-itm" name = "panic-itm"
version = "0.4.2" version = "0.4.2"
@ -464,9 +514,21 @@ dependencies = [
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.11" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
@ -477,7 +539,7 @@ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
"version_check", "version_check",
] ]
@ -494,31 +556,54 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.49" version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "rtcc" name = "rtcc"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3623619ce77c09a7d87cf7c61c5c887b9c7dee8805f66af6c4aa5824be4d9930" checksum = "f4fbd0d5bed2b76e27a7ef872568b34072c1af94c277cd52c17a89d54673b3fe"
dependencies = [ dependencies = [
"chrono", "chrono",
] ]
[[package]]
name = "rtic"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c443db16326376bdd64377da268f6616d5f804aba8ce799bac7d1f7f244e9d51"
dependencies = [
"atomic-polyfill",
"bare-metal 1.0.0",
"cortex-m",
"critical-section",
"rtic-core",
"rtic-macros",
]
[[package]]
name = "rtic-common"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0786b50b81ef9d2a944a000f60405bb28bf30cd45da2d182f3fe636b2321f35c"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "rtic-core" name = "rtic-core"
version = "1.0.0" version = "1.0.0"
@ -526,21 +611,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42" checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42"
[[package]] [[package]]
name = "rtic-monotonic" name = "rtic-macros"
version = "1.0.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb8b0b822d1a366470b9cea83a1d4e788392db763539dc4ba022bcc787fece82" checksum = "54053598ea24b1b74937724e366558412a1777eb2680b91ef646db540982789a"
[[package]]
name = "rtic-syntax"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ad3ae243dd8d0a1b064615f664d4fa7e63929939074c564cbe5efdc4c503065"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.53",
]
[[package]]
name = "rtic-monotonics"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058c2397dbd5bb4c5650a0e368c3920953e458805ff5097a0511b8147b3619d7"
dependencies = [
"atomic-polyfill",
"cfg-if",
"cortex-m",
"embedded-hal 1.0.0",
"fugit",
"rtic-time",
]
[[package]]
name = "rtic-time"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b232e7aebc045cfea81cdd164bc2727a10aca9a4568d406d0a5661cdfd0f19"
dependencies = [
"critical-section",
"futures-util",
"rtic-common",
] ]
[[package]] [[package]]
@ -558,31 +663,53 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [ dependencies = [
"semver 1.0.16", "semver 1.0.22",
] ]
[[package]] [[package]]
name = "sat-rs-example-stm32f-disco" name = "satrs"
version = "0.2.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8cb19cba46a45047ff0879ebfbf9d6ae1c5b2e0e38b2e08760b10a441d4dae6"
dependencies = [
"cobs 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crc",
"delegate",
"num-traits",
"num_enum",
"paste",
"satrs-shared",
"smallvec",
"spacepackets",
]
[[package]]
name = "satrs-example-stm32f3-disco"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cobs 0.2.3 (git+https://github.com/robamu/cobs.rs.git?branch=all_features)",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"cortex-m-rtic", "embedded-hal 0.2.7",
"embedded-hal",
"enumset", "enumset",
"heapless", "heapless",
"itm_logger", "itm_logger",
"panic-itm", "panic-itm",
"rtic",
"rtic-monotonics",
"satrs",
"stm32f3-discovery", "stm32f3-discovery",
"stm32f3xx-hal", "stm32f3xx-hal",
"systick-monotonic",
] ]
[[package]] [[package]]
name = "scopeguard" name = "satrs-shared"
version = "1.1.0" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "75a402ba556a7f5eef707035b45e64a3259b09674311e98697f3dd0508a1bf51"
dependencies = [
"spacepackets",
]
[[package]] [[package]]
name = "semver" name = "semver"
@ -595,9 +722,9 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.16" version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]] [[package]]
name = "semver-parser" name = "semver-parser"
@ -607,17 +734,28 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]] [[package]]
name = "slice-group-by" name = "slice-group-by"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
[[package]] [[package]]
name = "spin" name = "smallvec"
version = "0.9.4" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spacepackets"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28246ae2451af240c3e3ff3c51363c7b6ad565ca6aa9bad23b8c725687c485e1"
dependencies = [ dependencies = [
"lock_api", "chrono",
"crc",
"delegate",
"num-traits",
"num_enum",
"zerocopy",
] ]
[[package]] [[package]]
@ -639,9 +777,9 @@ dependencies = [
[[package]] [[package]]
name = "stm32f3" name = "stm32f3"
version = "0.14.0" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265cda62ac13307414de4aca58dbbbd8038ddba85cffbb335823aa216f2e3200" checksum = "b28b37228ef3fa47956af38c6abd756e912f244c1657f14e66d42fc8d74ea96f"
dependencies = [ dependencies = [
"bare-metal 1.0.0", "bare-metal 1.0.0",
"cortex-m", "cortex-m",
@ -651,7 +789,8 @@ dependencies = [
[[package]] [[package]]
name = "stm32f3-discovery" name = "stm32f3-discovery"
version = "0.8.0-pre.0" version = "0.8.0-alpha.0"
source = "git+https://github.com/robamu/stm32f3-discovery?branch=complete-dma-update-hal#5ccacae07ceff02d7d3649df67a6a0ba2a144752"
dependencies = [ dependencies = [
"accelerometer", "accelerometer",
"cortex-m", "cortex-m",
@ -663,20 +802,20 @@ dependencies = [
[[package]] [[package]]
name = "stm32f3xx-hal" name = "stm32f3xx-hal"
version = "0.9.1" version = "0.11.0-alpha.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/robamu/stm32f3xx-hal?branch=complete-dma-update#04fc76b7912649c84b57bd0ab803ea3ccf2aadae"
checksum = "4e422c5c044e8f3a068b1e14b83c071449e27c9d4bc0e24f972b552d79f2be03"
dependencies = [ dependencies = [
"bare-metal 1.0.0",
"bxcan", "bxcan",
"cfg-if", "cfg-if",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"critical-section",
"embedded-dma", "embedded-dma",
"embedded-hal", "embedded-hal 0.2.7",
"embedded-time", "embedded-time",
"enumset", "enumset",
"nb 1.0.0", "nb 1.1.0",
"num-traits",
"paste", "paste",
"rtcc", "rtcc",
"slice-group-by", "slice-group-by",
@ -691,14 +830,14 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90a4adc8cbd1726249b161898e48e0f3f1ce74d34dc784cbbc98fba4ed283fbf" checksum = "90a4adc8cbd1726249b161898e48e0f3f1ce74d34dc784cbbc98fba4ed283fbf"
dependencies = [ dependencies = [
"embedded-hal", "embedded-hal 0.2.7",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -706,27 +845,27 @@ dependencies = [
] ]
[[package]] [[package]]
name = "systick-monotonic" name = "syn"
version = "1.0.1" version = "2.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fb822d5c615a0ae3a4795ee5b1d06381c7faf488d861c0a4fa8e6a88d5ff84" checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
dependencies = [ dependencies = [
"cortex-m", "proc-macro2",
"fugit", "quote",
"rtic-monotonic", "unicode-ident",
] ]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.16.0" version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]] [[package]]
name = "usb-device" name = "usb-device"
@ -754,9 +893,30 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]] [[package]]
name = "volatile-register" name = "volatile-register"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
dependencies = [ dependencies = [
"vcell", "vcell",
] ]
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]

View File

@ -6,13 +6,19 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
cortex-m = "0.7" cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7" cortex-m-rt = "0.7"
embedded-hal = "0.2.6" embedded-hal = "0.2.7"
cortex-m-rtic = "1.0" enumset = "1"
enumset = "1.0" heapless = "0.8"
heapless = "0.7"
systick-monotonic = "1.0" [dependencies.rtic]
version = "2"
features = ["thumbv7-backend"]
[dependencies.rtic-monotonics]
version = "1"
features = ["cortex-m-systick"]
[dependencies.cobs] [dependencies.cobs]
git = "https://github.com/robamu/cobs.rs.git" git = "https://github.com/robamu/cobs.rs.git"
@ -29,22 +35,22 @@ version = "0.1.3-alpha.0"
[dependencies.stm32f3xx-hal] [dependencies.stm32f3xx-hal]
git = "https://github.com/robamu/stm32f3xx-hal" git = "https://github.com/robamu/stm32f3xx-hal"
version = "0.10.0-alpha.0" version = "0.11.0-alpha.0"
features = ["stm32f303xc", "rt", "enumset"] features = ["stm32f303xc", "rt", "enumset"]
branch = "all_features" branch = "complete-dma-update"
# Can be used in workspace to develop and update HAL # Can be used in workspace to develop and update HAL
# path = "../stm32f3xx-hal" # path = "../stm32f3xx-hal"
[dependencies.stm32f3-discovery] [dependencies.stm32f3-discovery]
git = "https://github.com/robamu/stm32f3-discovery" git = "https://github.com/robamu/stm32f3-discovery"
version = "0.8.0-alpha.0" version = "0.8.0-alpha.0"
branch = "all_features" branch = "complete-dma-update-hal"
# Can be used in workspace to develop and update BSP # Can be used in workspace to develop and update BSP
# path = "../stm32f3-discovery" # path = "../stm32f3-discovery"
[dependencies.satrs-core] [dependencies.satrs]
git = "https://egit.irs.uni-stuttgart.de/rust/satrs-core.git" # git = "https://egit.irs.uni-stuttgart.de/rust/satrs-core.git"
version = "0.1.0-alpha.0" version = "0.2.0-rc.0"
default-features = false default-features = false
# this lets you use `cargo fix`! # this lets you use `cargo fix`!

View File

@ -11,6 +11,18 @@ used by the [Rust Embedded Book](https://docs.rust-embedded.org/book/intro/hardw
[Rust Discovery](https://docs.rust-embedded.org/discovery/f3discovery/) book as an introduction [Rust Discovery](https://docs.rust-embedded.org/discovery/f3discovery/) book as an introduction
to embedded Rust. to embedded Rust.
If you would like to access the ITM log output, you need to connect the PB3 pin to the CN3 pin
of the SWD header like [shown here](https://docs.rust-embedded.org/discovery/f3discovery/06-hello-world/index.html).
## Pre-Requisites
Make sure the following tools are installed:
1. `openocd`: This is the debug server used to debug the STM32F3. You can install this from
[`xPacks`](https://xpack.github.io/dev-tools/openocd/install/). You can also use the one provided
by a STM32Cube installation.
2. A debugger like `arm-none-eabi-gdb` or `gdb-multiarch`.
## Preparing Rust and the repository ## Preparing Rust and the repository
Building an application requires the `thumbv7em-none-eabihf` cross-compiler toolchain. Building an application requires the `thumbv7em-none-eabihf` cross-compiler toolchain.
@ -42,13 +54,25 @@ cargo build
## Flashing and Debugging from the command line ## Flashing and Debugging from the command line
TODO Make sure you have `openocd` and `itmdump` installed first.
1. Configure a runner inside your `.cargo/config.toml` file by uncommenting an appropriate line
depending on the application you want to use for debugging
2. Start `openocd` inside the project folder. This will start `openocd` with the provided
`openocd.cfg` configuration file.
3. Use `cargo run` to flash and debug the application in your terminal
4. Use `itmdump -F -f itm.txt` to print the logs received from the STM32F3 device. Please note
that the PB3 and CN3 pin of the SWD header need to be connected for this to work.
## Debugging with VS Code ## Debugging with VS Code
The STM32F3-Discovery comes with an on-board ST-Link so all that is required to flash and debug The STM32F3-Discovery comes with an on-board ST-Link so all that is required to flash and debug
the board is a Mini-USB cable. The code in this repository was debugged using `openocd` the board is a Mini-USB cable. The code in this repository was debugged using `openocd`
and the VS Code [`Cortex-Debug` plugin](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug). and the VS Code [`Cortex-Debug` plugin](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug).
Make sure to install this plugin first.
Sample configuration files are provided inside the `vscode` folder.
Use `cp vscode .vscode -r` to use them for your project.
Some sample configuration files for VS Code were provided as well. You can simply use `Run` and `Debug` Some sample configuration files for VS Code were provided as well. You can simply use `Run` and `Debug`
to automatically rebuild and flash your application. to automatically rebuild and flash your application.
@ -67,9 +91,23 @@ configuration variables in your `settings.json`:
## Commanding with Python ## Commanding with Python
When the SW is running on the Discovery board, you can command the MCU via a serial interface, When the SW is running on the Discovery board, you can command the MCU via a serial interface,
using COBS encoded CCSDS packets. using COBS encoded PUS packets.
TODO: It is recommended to use a virtual environment to do this. To set up one in the command line,
- How and where to connect serial interface on the MCU you can use `python3 -m venv venv` on Unix systems or `py -m venv venv` on Windows systems.
- How to set up Python venv (or at least strongly recommend it) and install deps After doing this, you can check the [venv tutorial](https://docs.python.org/3/tutorial/venv.html)
- How to copy `def_tmtc_conf.json` to `tmtc_conf.json` and adapt it for custom serial port on how to activate the environment and then use the following command to install the required
dependency:
```sh
pip install -r requirements.txt
```
The packets are exchanged using a dedicated serial interface. You can use any generic USB-to-UART
converter device with the TX pin connected to the PA3 pin and the RX pin connected to the PA2 pin.
A default configuration file for the python application is provided and can be used by running
```sh
cp def_tmtc_conf.json tmtc_conf.json
```

View File

@ -24,7 +24,9 @@ break main
# # send captured ITM to the file itm.fifo # # send captured ITM to the file itm.fifo
# # (the microcontroller SWO pin must be connected to the programmer SWO pin) # # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # 8000000 must match the core clock frequency # # 8000000 must match the core clock frequency
monitor tpiu config internal itm.txt uart off 8000000 # # 2000000 is the frequency of the SWO pin. This was added for newer
# openocd versions like v0.12.0.
monitor tpiu config internal itm.txt uart off 8000000 2000000
# # OR: make the microcontroller SWO pin output compatible with UART (8N1) # # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # 8000000 must match the core clock frequency # # 8000000 must match the core clock frequency

View File

@ -1,4 +1,5 @@
/venv /venv
/.tmtc-history.txt
/log /log
/.idea/* /.idea/*
!/.idea/runConfigurations !/.idea/runConfigurations

185
satrs-example-stm32f3-disco/pyclient/main.py Normal file → Executable file
View File

@ -1,39 +1,40 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Example client for the sat-rs example application""" """Example client for the sat-rs example application"""
import enum
import struct import struct
import logging
import sys import sys
import time import time
from typing import Optional, cast from typing import Any, Optional, cast
from prompt_toolkit.history import FileHistory, History
from spacepackets.ecss.tm import CdsShortTimestamp
import tmtccmd import tmtccmd
from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator
from spacepackets.ecss.pus_17_test import Service17Tm from spacepackets.ecss.pus_17_test import Service17Tm
from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm
from tmtccmd import CcsdsTmtcBackend, TcHandlerBase, ProcedureParamsWrapper from tmtccmd import TcHandlerBase, ProcedureParamsWrapper
from tmtccmd.core.base import BackendRequest from tmtccmd.core.base import BackendRequest
from tmtccmd.core.ccsds_backend import QueueWrapper
from tmtccmd.logging import add_colorlog_console_logger
from tmtccmd.pus import VerificationWrapper from tmtccmd.pus import VerificationWrapper
from tmtccmd.tm import CcsdsTmHandler, SpecificApidHandlerBase from tmtccmd.tmtc import CcsdsTmHandler, SpecificApidHandlerBase
from tmtccmd.com_if import ComInterface from tmtccmd.com import ComInterface
from tmtccmd.config import ( from tmtccmd.config import (
CmdTreeNode,
default_json_path, default_json_path,
SetupParams, SetupParams,
TmTcCfgHookBase, HookBase,
TmtcDefinitionWrapper,
CoreServiceList,
OpCodeEntry,
params_to_procedure_conversion, params_to_procedure_conversion,
) )
from tmtccmd.config.com_if import SerialCfgWrapper from tmtccmd.config.com import SerialCfgWrapper
from tmtccmd.config import PreArgsParsingWrapper, SetupWrapper from tmtccmd.config import PreArgsParsingWrapper, SetupWrapper
from tmtccmd.logging import get_console_logger
from tmtccmd.logging.pus import ( from tmtccmd.logging.pus import (
RegularTmtcLogWrapper, RegularTmtcLogWrapper,
RawTmtcTimedLogWrapper, RawTmtcTimedLogWrapper,
TimedLogWhen, TimedLogWhen,
) )
from tmtccmd.tc import ( from tmtccmd.tmtc import (
TcQueueEntryType, TcQueueEntryType,
ProcedureWrapper, ProcedureWrapper,
TcProcedureType, TcProcedureType,
@ -41,27 +42,26 @@ from tmtccmd.tc import (
SendCbParams, SendCbParams,
DefaultPusQueueHelper, DefaultPusQueueHelper,
) )
from tmtccmd.tm.pus_5_event import Service5Tm from tmtccmd.pus.s5_fsfw_event import Service5Tm
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
from tmtccmd.util.obj_id import ObjectIdDictT from tmtccmd.util.obj_id import ObjectIdDictT
from tmtccmd.util.tmtc_printer import FsfwTmTcPrinter _LOGGER = logging.getLogger()
LOGGER = get_console_logger()
EXAMPLE_PUS_APID = 0x02 EXAMPLE_PUS_APID = 0x02
class SatRsConfigHook(TmTcCfgHookBase): class SatRsConfigHook(HookBase):
def __init__(self, json_cfg_path: str): def __init__(self, json_cfg_path: str):
super().__init__(json_cfg_path=json_cfg_path) super().__init__(json_cfg_path=json_cfg_path)
def assign_communication_interface(self, com_if_key: str) -> Optional[ComInterface]: def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]:
from tmtccmd.config.com_if import ( from tmtccmd.config.com import (
create_com_interface_default, create_com_interface_default,
create_com_interface_cfg_default, create_com_interface_cfg_default,
) )
assert self.cfg_path is not None
cfg = create_com_interface_cfg_default( cfg = create_com_interface_cfg_default(
com_if_key=com_if_key, com_if_key=com_if_key,
json_cfg_path=self.cfg_path, json_cfg_path=self.cfg_path,
@ -76,35 +76,14 @@ class SatRsConfigHook(TmTcCfgHookBase):
cfg.serial_cfg.serial_timeout = 0.5 cfg.serial_cfg.serial_timeout = 0.5
return create_com_interface_default(cfg) return create_com_interface_default(cfg)
def get_tmtc_definitions(self) -> TmtcDefinitionWrapper: def get_command_definitions(self) -> CmdTreeNode:
from tmtccmd.config.globals import get_default_tmtc_defs """This function should return the root node of the command definition tree."""
return create_cmd_definition_tree()
defs = get_default_tmtc_defs() def get_cmd_history(self) -> Optional[History]:
srv_5 = OpCodeEntry() """Optionlly return a history class for the past command paths which will be used
srv_5.add("0", "Event Test") when prompting a command path from the user in CLI mode."""
defs.add_service( return FileHistory(".tmtc-history.txt")
name=CoreServiceList.SERVICE_5.value,
info="PUS Service 5 Event",
op_code_entry=srv_5,
)
srv_17 = OpCodeEntry()
srv_17.add("0", "Ping Test")
defs.add_service(
name=CoreServiceList.SERVICE_17_ALT,
info="PUS Service 17 Test",
op_code_entry=srv_17,
)
srv_3 = OpCodeEntry()
defs.add_service(
name=CoreServiceList.SERVICE_3,
info="PUS Service 3 Housekeeping",
op_code_entry=srv_3,
)
return defs
def perform_mode_operation(self, tmtc_backend: CcsdsTmtcBackend, mode: int):
LOGGER.info("Mode operation hook was called")
pass
def get_object_ids(self) -> ObjectIdDictT: def get_object_ids(self) -> ObjectIdDictT:
from tmtccmd.config.objects import get_core_object_ids from tmtccmd.config.objects import get_core_object_ids
@ -112,74 +91,75 @@ class SatRsConfigHook(TmTcCfgHookBase):
return get_core_object_ids() return get_core_object_ids()
def create_cmd_definition_tree() -> CmdTreeNode:
root_node = CmdTreeNode.root_node()
root_node.add_child(CmdTreeNode("ping", "Send PUS ping TC"))
return root_node
class PusHandler(SpecificApidHandlerBase): class PusHandler(SpecificApidHandlerBase):
def __init__( def __init__(
self, self,
file_logger: logging.Logger,
verif_wrapper: VerificationWrapper, verif_wrapper: VerificationWrapper,
printer: FsfwTmTcPrinter,
raw_logger: RawTmtcTimedLogWrapper, raw_logger: RawTmtcTimedLogWrapper,
): ):
super().__init__(EXAMPLE_PUS_APID, None) super().__init__(EXAMPLE_PUS_APID, None)
self.printer = printer self.file_logger = file_logger
self.raw_logger = raw_logger self.raw_logger = raw_logger
self.verif_wrapper = verif_wrapper self.verif_wrapper = verif_wrapper
def handle_tm(self, packet: bytes, _user_args: any): def handle_tm(self, packet: bytes, _user_args: Any):
time_reader = CdsShortTimestamp.empty()
try: try:
tm_packet = PusTelemetry.unpack(packet) pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty())
except ValueError as e: except ValueError as e:
LOGGER.warning("Could not generate PUS TM object from raw data") _LOGGER.warning("Could not generate PUS TM object from raw data")
LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}") _LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}")
raise e raise e
service = tm_packet.service service = pus_tm.service
dedicated_handler = False tm_packet = None
if service == 1: if service == 1:
tm_packet = Service1Tm.unpack(data=packet, params=UnpackParams(1, 2)) tm_packet = Service1Tm.unpack(
data=packet, params=UnpackParams(time_reader, 1, 2)
)
res = self.verif_wrapper.add_tm(tm_packet) res = self.verif_wrapper.add_tm(tm_packet)
if res is None: if res is None:
LOGGER.info( _LOGGER.info(
f"Received Verification TM[{tm_packet.service}, {tm_packet.subservice}] " f"Received Verification TM[{tm_packet.service}, {tm_packet.subservice}] "
f"with Request ID {tm_packet.tc_req_id.as_u32():#08x}" f"with Request ID {tm_packet.tc_req_id.as_u32():#08x}"
) )
LOGGER.warning( _LOGGER.warning(
f"No matching telecommand found for {tm_packet.tc_req_id}" f"No matching telecommand found for {tm_packet.tc_req_id}"
) )
else: else:
self.verif_wrapper.log_to_console(tm_packet, res) self.verif_wrapper.log_to_console(tm_packet, res)
self.verif_wrapper.log_to_file(tm_packet, res) self.verif_wrapper.log_to_file(tm_packet, res)
dedicated_handler = True
if service == 3: if service == 3:
LOGGER.info("No handling for HK packets implemented") _LOGGER.info("No handling for HK packets implemented")
LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]") _LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]")
pus_tm = PusTelemetry.unpack(packet) pus_tm = PusTelemetry.unpack(packet, CdsShortTimestamp.empty())
if pus_tm.subservice == 25: if pus_tm.subservice == 25:
if len(pus_tm.source_data) < 8: if len(pus_tm.source_data) < 8:
raise ValueError("No addressable ID in HK packet") raise ValueError("No addressable ID in HK packet")
json_str = pus_tm.source_data[8:] json_str = pus_tm.source_data[8:]
dedicated_handler = True _LOGGER.info("received JSON string: " + json_str.decode("utf-8"))
if service == 5: if service == 5:
tm_packet = Service5Tm.unpack(packet) tm_packet = Service5Tm.unpack(packet, time_reader)
if service == 17: if service == 17:
tm_packet = Service17Tm.unpack(packet) tm_packet = Service17Tm.unpack(packet, time_reader)
dedicated_handler = True
if tm_packet.subservice == 2: if tm_packet.subservice == 2:
self.printer.file_logger.info("Received Ping Reply TM[17,2]") _LOGGER.info("Received Ping Reply TM[17,2]")
LOGGER.info("Received Ping Reply TM[17,2]")
else: else:
self.printer.file_logger.info( _LOGGER.info(
f"Received Test Packet with unknown subservice {tm_packet.subservice}"
)
LOGGER.info(
f"Received Test Packet with unknown subservice {tm_packet.subservice}" f"Received Test Packet with unknown subservice {tm_packet.subservice}"
) )
if tm_packet is None: if tm_packet is None:
LOGGER.info( _LOGGER.info(
f"The service {service} is not implemented in Telemetry Factory" f"The service {service} is not implemented in Telemetry Factory"
) )
tm_packet = PusTelemetry.unpack(packet) tm_packet = PusTelemetry.unpack(packet, time_reader)
self.raw_logger.log_tm(tm_packet) self.raw_logger.log_tm(pus_tm)
if not dedicated_handler and tm_packet is not None:
self.printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet)
def make_addressable_id(target_id: int, unique_id: int) -> bytes: def make_addressable_id(target_id: int, unique_id: int) -> bytes:
@ -198,8 +178,11 @@ class TcHandler(TcHandlerBase):
self.seq_count_provider = seq_count_provider self.seq_count_provider = seq_count_provider
self.verif_wrapper = verif_wrapper self.verif_wrapper = verif_wrapper
self.queue_helper = DefaultPusQueueHelper( self.queue_helper = DefaultPusQueueHelper(
queue_wrapper=None, queue_wrapper=QueueWrapper.empty(),
tc_sched_timestamp_len=7,
seq_cnt_provider=seq_count_provider, seq_cnt_provider=seq_count_provider,
pus_verificator=verif_wrapper.pus_verificator,
default_pus_apid=EXAMPLE_PUS_APID,
) )
def send_cb(self, send_params: SendCbParams): def send_cb(self, send_params: SendCbParams):
@ -212,61 +195,55 @@ class TcHandler(TcHandlerBase):
) )
self.verif_wrapper.add_tc(pus_tc_wrapper.pus_tc) self.verif_wrapper.add_tc(pus_tc_wrapper.pus_tc)
raw_tc = pus_tc_wrapper.pus_tc.pack() raw_tc = pus_tc_wrapper.pus_tc.pack()
LOGGER.info(f"Sending {pus_tc_wrapper.pus_tc}") _LOGGER.info(f"Sending {pus_tc_wrapper.pus_tc}")
send_params.com_if.send(raw_tc) send_params.com_if.send(raw_tc)
elif entry_helper.entry_type == TcQueueEntryType.LOG: elif entry_helper.entry_type == TcQueueEntryType.LOG:
log_entry = entry_helper.to_log_entry() log_entry = entry_helper.to_log_entry()
LOGGER.info(log_entry.log_str) _LOGGER.info(log_entry.log_str)
def queue_finished_cb(self, helper: ProcedureWrapper): def queue_finished_cb(self, info: ProcedureWrapper):
if helper.proc_type == TcProcedureType.DEFAULT: if info.proc_type == TcProcedureType.DEFAULT:
def_proc = helper.to_def_procedure() def_proc = info.to_def_procedure()
LOGGER.info( _LOGGER.info(f"Queue handling finished for command {def_proc.cmd_path}")
f"Queue handling finished for service {def_proc.service} and "
f"op code {def_proc.op_code}"
)
def feed_cb(self, helper: ProcedureWrapper, wrapper: FeedWrapper): def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):
q = self.queue_helper q = self.queue_helper
q.queue_wrapper = wrapper.queue_wrapper q.queue_wrapper = wrapper.queue_wrapper
if helper.proc_type == TcProcedureType.DEFAULT: if info.proc_type == TcProcedureType.DEFAULT:
def_proc = helper.to_def_procedure() def_proc = info.to_def_procedure()
service = def_proc.service cmd_path = def_proc.cmd_path
op_code = def_proc.op_code if cmd_path == "/ping":
if (
service == CoreServiceList.SERVICE_17
or service == CoreServiceList.SERVICE_17_ALT
):
q.add_log_cmd("Sending PUS ping telecommand") q.add_log_cmd("Sending PUS ping telecommand")
return q.add_pus_tc(PusTelecommand(service=17, subservice=1)) q.add_pus_tc(PusTelecommand(service=17, subservice=1))
def main(): def main():
add_colorlog_console_logger(_LOGGER)
tmtccmd.init_printout(False) tmtccmd.init_printout(False)
hook_obj = SatRsConfigHook(json_cfg_path=default_json_path()) hook_obj = SatRsConfigHook(json_cfg_path=default_json_path())
parser_wrapper = PreArgsParsingWrapper() parser_wrapper = PreArgsParsingWrapper()
parser_wrapper.create_default_parent_parser() parser_wrapper.create_default_parent_parser()
parser_wrapper.create_default_parser() parser_wrapper.create_default_parser()
parser_wrapper.add_def_proc_args() parser_wrapper.add_def_proc_args()
post_args_wrapper = parser_wrapper.parse(hook_obj)
params = SetupParams() params = SetupParams()
post_args_wrapper = parser_wrapper.parse(hook_obj, params)
proc_wrapper = ProcedureParamsWrapper() proc_wrapper = ProcedureParamsWrapper()
if post_args_wrapper.use_gui: if post_args_wrapper.use_gui:
post_args_wrapper.set_params_without_prompts(params, proc_wrapper) post_args_wrapper.set_params_without_prompts(proc_wrapper)
else: else:
post_args_wrapper.set_params_with_prompts(params, proc_wrapper) post_args_wrapper.set_params_with_prompts(proc_wrapper)
params.apid = EXAMPLE_PUS_APID params.apid = EXAMPLE_PUS_APID
setup_args = SetupWrapper( setup_args = SetupWrapper(
hook_obj=hook_obj, setup_params=params, proc_param_wrapper=proc_wrapper hook_obj=hook_obj, setup_params=params, proc_param_wrapper=proc_wrapper
) )
# Create console logger helper and file loggers # Create console logger helper and file loggers
tmtc_logger = RegularTmtcLogWrapper() tmtc_logger = RegularTmtcLogWrapper()
printer = FsfwTmTcPrinter(tmtc_logger.logger) file_logger = tmtc_logger.logger
raw_logger = RawTmtcTimedLogWrapper(when=TimedLogWhen.PER_HOUR, interval=1) raw_logger = RawTmtcTimedLogWrapper(when=TimedLogWhen.PER_HOUR, interval=1)
verificator = PusVerificator() verificator = PusVerificator()
verification_wrapper = VerificationWrapper(verificator, LOGGER, printer.file_logger) verification_wrapper = VerificationWrapper(verificator, _LOGGER, file_logger)
# Create primary TM handler and add it to the CCSDS Packet Handler # Create primary TM handler and add it to the CCSDS Packet Handler
tm_handler = PusHandler(verification_wrapper, printer, raw_logger) tm_handler = PusHandler(file_logger, verification_wrapper, raw_logger)
ccsds_handler = CcsdsTmHandler(generic_handler=None) ccsds_handler = CcsdsTmHandler(generic_handler=None)
ccsds_handler.add_apid_handler(tm_handler) ccsds_handler.add_apid_handler(tm_handler)
@ -288,7 +265,7 @@ def main():
if state.request == BackendRequest.TERMINATION_NO_ERROR: if state.request == BackendRequest.TERMINATION_NO_ERROR:
sys.exit(0) sys.exit(0)
elif state.request == BackendRequest.DELAY_IDLE: elif state.request == BackendRequest.DELAY_IDLE:
LOGGER.info("TMTC Client in IDLE mode") _LOGGER.info("TMTC Client in IDLE mode")
time.sleep(3.0) time.sleep(3.0)
elif state.request == BackendRequest.DELAY_LISTENER: elif state.request == BackendRequest.DELAY_LISTENER:
time.sleep(0.8) time.sleep(0.8)

View File

@ -1,2 +1,2 @@
tmtccmd == 4.0.0a0 tmtccmd == 8.0.0rc.0
# -e git+https://github.com/robamu-org/tmtccmd.git@main#egg=tmtccmd # -e git+https://github.com/robamu-org/tmtccmd.git@main#egg=tmtccmd

View File

@ -4,35 +4,33 @@ extern crate panic_itm;
use rtic::app; use rtic::app;
use heapless::{ use heapless::{mpmc::Q8, Vec};
mpmc::Q16,
pool,
pool::singleton::{Box, Pool},
};
#[allow(unused_imports)] #[allow(unused_imports)]
use itm_logger::{debug, info, logger_init, warn}; use itm_logger::{debug, info, logger_init, warn};
use satrs_core::spacepackets::{ecss::PusPacket, tm::PusTm}; use rtic_monotonics::systick::fugit::TimerInstantU32;
use satrs_core::{ use rtic_monotonics::systick::ExtU32;
pus::{EcssTmErrorWithSend, EcssTmSenderCore}, use satrs::seq_count::SequenceCountProviderCore;
seq_count::SequenceCountProviderCore, use satrs::{
pool::StoreError,
pus::{EcssChannel, EcssTmSenderCore, EcssTmtcError, PusTmWrapper},
spacepackets::{ecss::PusPacket, ecss::WritablePusPacket},
}; };
use stm32f3xx_hal::dma::dma1; use stm32f3xx_hal::dma::dma1;
use stm32f3xx_hal::gpio::{PushPull, AF7, PA2, PA3}; use stm32f3xx_hal::gpio::{PushPull, AF7, PA2, PA3};
use stm32f3xx_hal::pac::USART2; use stm32f3xx_hal::pac::USART2;
use stm32f3xx_hal::serial::{Rx, RxEvent, Serial, SerialDmaRx, SerialDmaTx, Tx, TxEvent}; use stm32f3xx_hal::serial::{Rx, RxEvent, Serial, SerialDmaRx, SerialDmaTx, Tx, TxEvent};
use systick_monotonic::{fugit::Duration, Systick};
const UART_BAUD: u32 = 115200; const UART_BAUD: u32 = 115200;
const BLINK_FREQ_MS: u64 = 1000; const BLINK_FREQ_MS: u32 = 1000;
const TX_HANDLER_FREQ_MS: u64 = 20; const TX_HANDLER_FREQ_MS: u32 = 20;
const MIN_DELAY_BETWEEN_TX_PACKETS_MS: u16 = 5; const MIN_DELAY_BETWEEN_TX_PACKETS_MS: u32 = 5;
const MAX_TC_LEN: usize = 200; const MAX_TC_LEN: usize = 128;
const MAX_TM_LEN: usize = 200; const MAX_TM_LEN: usize = 128;
pub const PUS_APID: u16 = 0x02; pub const PUS_APID: u16 = 0x02;
type TxType = Tx<USART2, PA2<AF7<PushPull>>>; type TxType = Tx<USART2, PA2<AF7<PushPull>>>;
type RxType = Rx<USART2, PA3<AF7<PushPull>>>; type RxType = Rx<USART2, PA3<AF7<PushPull>>>;
type MsDuration = Duration<u64, 1, 1000>; type InstantFugit = TimerInstantU32<1000>;
type TxDmaTransferType = SerialDmaTx<&'static [u8], dma1::C7, TxType>; type TxDmaTransferType = SerialDmaTx<&'static [u8], dma1::C7, TxType>;
type RxDmaTransferType = SerialDmaRx<&'static mut [u8], dma1::C6, RxType>; type RxDmaTransferType = SerialDmaRx<&'static mut [u8], dma1::C6, RxType>;
@ -51,10 +49,12 @@ static mut DMA_TX_BUF: [u8; TM_BUF_LEN] = [0; TM_BUF_LEN];
// transfer buffer. // transfer buffer.
static mut DMA_RX_BUF: [u8; TC_BUF_LEN] = [0; TC_BUF_LEN]; static mut DMA_RX_BUF: [u8; TC_BUF_LEN] = [0; TC_BUF_LEN];
static TX_REQUESTS: Q16<(Box<poolmod::TM>, usize)> = Q16::new(); type TmPacket = Vec<u8, MAX_TM_LEN>;
type TcPacket = Vec<u8, MAX_TC_LEN>;
const TC_POOL_SLOTS: usize = 12; static TM_REQUESTS: Q8<TmPacket> = Q8::new();
const TM_POOL_SLOTS: usize = 12;
use core::cell::RefCell;
use core::sync::atomic::{AtomicU16, Ordering}; use core::sync::atomic::{AtomicU16, Ordering};
pub struct SeqCountProviderAtomicRef { pub struct SeqCountProviderAtomicRef {
@ -88,70 +88,56 @@ impl SequenceCountProviderCore<u16> for SeqCountProviderAtomicRef {
static SEQ_COUNT_PROVIDER: SeqCountProviderAtomicRef = static SEQ_COUNT_PROVIDER: SeqCountProviderAtomicRef =
SeqCountProviderAtomicRef::new(Ordering::Relaxed); SeqCountProviderAtomicRef::new(Ordering::Relaxed);
// Otherwise, warnings because of heapless pool macro.
#[allow(non_camel_case_types)]
mod poolmod {
use super::*;
// Must hold full TC length including COBS overhead.
pool!(TC: [u8; TC_BUF_LEN]);
// Only encoded at the end, so no need to account for COBS overhead.
pool!(TM: [u8; MAX_TM_LEN]);
}
pub struct TxIdle { pub struct TxIdle {
tx: TxType, tx: TxType,
dma_channel: dma1::C7, dma_channel: dma1::C7,
} }
#[derive(Debug)]
pub enum TmStoreError {
StoreFull,
StoreSlotsTooSmall,
}
impl From<TmStoreError> for EcssTmErrorWithSend<TmStoreError> {
fn from(value: TmStoreError) -> Self {
Self::SendError(value)
}
}
pub struct TmSender { pub struct TmSender {
mem_block: Option<Box<poolmod::TM>>, vec: Option<RefCell<Vec<u8, MAX_TM_LEN>>>,
ctx: &'static str, ctx: &'static str,
} }
impl TmSender { impl TmSender {
pub fn new(mem_block: Box<poolmod::TM>, ctx: &'static str) -> Self { pub fn new(tm_packet: TmPacket, ctx: &'static str) -> Self {
Self { Self {
mem_block: Some(mem_block), vec: Some(RefCell::new(tm_packet)),
ctx, ctx,
} }
} }
} }
impl EcssTmSenderCore for TmSender { impl EcssChannel for TmSender {
type Error = TmStoreError; fn id(&self) -> satrs::ChannelId {
0
}
}
fn send_tm( impl EcssTmSenderCore for TmSender {
&mut self, fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
tm: PusTm, let vec = self.vec.as_ref();
) -> Result<(), satrs_core::pus::EcssTmErrorWithSend<Self::Error>> { if vec.is_none() {
let mem_block = self.mem_block.take();
if mem_block.is_none() {
panic!("send_tm should only be called once"); panic!("send_tm should only be called once");
} }
let mut mem_block = mem_block.unwrap(); let vec_ref = vec.unwrap();
if tm.len_packed() > MAX_TM_LEN { let mut vec = vec_ref.borrow_mut();
return Err(EcssTmErrorWithSend::SendError( match tm {
TmStoreError::StoreSlotsTooSmall, PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
)); PusTmWrapper::Direct(tm) => {
if tm.len_written() > MAX_TM_LEN {
return Err(EcssTmtcError::Store(StoreError::DataTooLarge(
tm.len_written(),
)));
}
vec.resize(tm.len_written(), 0).expect("vec resize failed");
tm.write_to_bytes(vec.as_mut_slice())?;
info!(target: self.ctx, "Sending TM[{},{}] with size {}", tm.service(), tm.subservice(), tm.len_written());
drop(vec);
TM_REQUESTS
.enqueue(vec_ref.take())
.map_err(|_| EcssTmtcError::Store(StoreError::StoreFull(0)))?;
}
} }
tm.write_to_bytes(mem_block.as_mut_slice())
.map_err(|e| EcssTmErrorWithSend::EcssTmError(e.into()))?;
info!(target: self.ctx, "Sending TM[{},{}] with size {}", tm.service(), tm.subservice(), tm.len_packed());
TX_REQUESTS
.enqueue((mem_block, tm.len_packed()))
.map_err(|_| TmStoreError::StoreFull)?;
Ok(()) Ok(())
} }
} }
@ -163,33 +149,37 @@ pub enum UartTxState {
Transmitting(Option<TxDmaTransferType>), Transmitting(Option<TxDmaTransferType>),
} }
#[app(device = stm32f3xx_hal::pac, peripherals = true, dispatchers = [TIM20_BRK, TIM20_UP, TIM20_TRG_COM])] pub struct UartTxShared {
last_completed: Option<InstantFugit>,
state: UartTxState,
}
#[app(device = stm32f3xx_hal::pac, peripherals = true)]
mod app { mod app {
use super::*; use super::*;
use core::slice::Iter; use core::slice::Iter;
use cortex_m::iprintln; use cortex_m::iprintln;
use satrs_core::pus::verification::FailParams; use rtic_monotonics::systick::Systick;
use satrs_core::pus::verification::VerificationReporterCore; use rtic_monotonics::Monotonic;
use satrs_core::spacepackets::{ use satrs::pus::verification::FailParams;
ecss::EcssEnumU16, use satrs::pus::verification::VerificationReporterCore;
tc::PusTc, use satrs::spacepackets::{
time::cds::P_FIELD_BASE, ecss::tc::PusTcReader, ecss::tm::PusTmCreator, ecss::tm::PusTmSecondaryHeader,
tm::{PusTm, PusTmSecondaryHeader}, ecss::EcssEnumU16, time::cds::P_FIELD_BASE, CcsdsPacket, SpHeader,
CcsdsPacket, SpHeader,
}; };
#[allow(unused_imports)] #[allow(unused_imports)]
use stm32f3_discovery::leds::Direction; use stm32f3_discovery::leds::Direction;
use stm32f3_discovery::leds::Leds; use stm32f3_discovery::leds::Leds;
use stm32f3xx_hal::prelude::*; use stm32f3xx_hal::prelude::*;
use stm32f3xx_hal::Toggle;
use stm32f3_discovery::switch_hal::OutputSwitch; use stm32f3_discovery::switch_hal::OutputSwitch;
use stm32f3xx_hal::Switch;
#[allow(dead_code)] #[allow(dead_code)]
type SerialType = Serial<USART2, (PA2<AF7<PushPull>>, PA3<AF7<PushPull>>)>; type SerialType = Serial<USART2, (PA2<AF7<PushPull>>, PA3<AF7<PushPull>>)>;
#[shared] #[shared]
struct Shared { struct Shared {
tx_transfer: UartTxState, tx_shared: UartTxShared,
rx_transfer: Option<RxDmaTransferType>, rx_transfer: Option<RxDmaTransferType>,
} }
@ -201,17 +191,14 @@ mod app {
curr_dir: Iter<'static, Direction>, curr_dir: Iter<'static, Direction>,
} }
#[monotonic(binds = SysTick, default = true)] #[init]
type MonoTimer = Systick<1000>; fn init(mut cx: init::Context) -> (Shared, Local) {
#[init(local = [
tc_pool_mem: [u8; TC_BUF_LEN * TC_POOL_SLOTS] = [0; TC_BUF_LEN * TC_POOL_SLOTS],
tm_pool_mem: [u8; MAX_TM_LEN * TM_POOL_SLOTS] = [0; MAX_TM_LEN * TM_POOL_SLOTS]
])]
fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) {
let mut rcc = cx.device.RCC.constrain(); let mut rcc = cx.device.RCC.constrain();
let mono = Systick::new(cx.core.SYST, 8_000_000); // Initialize the systick interrupt & obtain the token to prove that we did
let systick_mono_token = rtic_monotonics::create_systick_token!();
Systick::start(cx.core.SYST, 8_000_000, systick_mono_token);
logger_init(); logger_init();
let mut flash = cx.device.FLASH.constrain(); let mut flash = cx.device.FLASH.constrain();
let clocks = rcc let clocks = rcc
@ -220,15 +207,16 @@ mod app {
.sysclk(8.MHz()) .sysclk(8.MHz())
.pclk1(8.MHz()) .pclk1(8.MHz())
.freeze(&mut flash.acr); .freeze(&mut flash.acr);
// Set up monotonic timer.
//let mono_timer = MonoTimer::new(cx.core.DWT, clocks, &mut cx.core.DCB);
// setup ITM output // setup ITM output
iprintln!( iprintln!(
&mut cx.core.ITM.stim[0], &mut cx.core.ITM.stim[0],
"Starting sat-rs demo application for the STM32F3-Discovery" "Starting sat-rs demo application for the STM32F3-Discovery"
); );
let mut gpioe = cx.device.GPIOE.split(&mut rcc.ahb); let mut gpioe = cx.device.GPIOE.split(&mut rcc.ahb);
// Assign memory to the pools.
poolmod::TC::grow(cx.local.tc_pool_mem);
poolmod::TM::grow(cx.local.tm_pool_mem);
let verif_reporter = VerificationReporterCore::new(PUS_APID).unwrap(); let verif_reporter = VerificationReporterCore::new(PUS_APID).unwrap();
@ -264,106 +252,138 @@ mod app {
clocks, clocks,
&mut rcc.apb1, &mut rcc.apb1,
); );
usart2.configure_rx_interrupt(RxEvent::Idle, Toggle::On); usart2.configure_rx_interrupt(RxEvent::Idle, Switch::On);
// This interrupt is enabled to re-schedule new transfers in the interrupt handler immediately. // This interrupt is enabled to re-schedule new transfers in the interrupt handler immediately.
usart2.configure_tx_interrupt(TxEvent::TransmissionComplete, Toggle::On); usart2.configure_tx_interrupt(TxEvent::TransmissionComplete, Switch::On);
let dma1 = cx.device.DMA1.split(&mut rcc.ahb); let dma1 = cx.device.DMA1.split(&mut rcc.ahb);
let (tx_serial, mut rx_serial) = usart2.split(); let (mut tx_serial, mut rx_serial) = usart2.split();
// This interrupt is immediately triggered, clear it. It will only be reset // This interrupt is immediately triggered, clear it. It will only be reset
// by the hardware when data is received on RX (RXNE event) // 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); let rx_transfer = rx_serial.read_exact(unsafe { DMA_RX_BUF.as_mut_slice() }, dma1.ch6);
info!(target: "init", "Spawning tasks"); info!(target: "init", "Spawning tasks");
blink::spawn().unwrap(); blink::spawn().unwrap();
serial_tx_handler::spawn().unwrap(); serial_tx_handler::spawn().unwrap();
( (
Shared { Shared {
tx_transfer: UartTxState::Idle(Some(TxIdle { tx_shared: UartTxShared {
tx: tx_serial, last_completed: None,
dma_channel: dma1.ch7, state: UartTxState::Idle(Some(TxIdle {
})), tx: tx_serial,
dma_channel: dma1.ch7,
})),
},
rx_transfer: Some(rx_transfer), rx_transfer: Some(rx_transfer),
}, },
Local { Local {
//timer: mono_timer,
leds, leds,
last_dir: Direction::North, last_dir: Direction::North,
curr_dir: Direction::iter(), curr_dir: Direction::iter(),
verif_reporter, verif_reporter,
}, },
init::Monotonics(mono),
) )
} }
#[task(local = [leds, curr_dir, last_dir])] #[task(local = [leds, curr_dir, last_dir])]
fn blink(cx: blink::Context) { async fn blink(cx: blink::Context) {
let toggle_leds = |dir: &Direction| { let blink::LocalResources {
let leds = cx.local.leds; leds,
let last_led = leds.for_direction(*cx.local.last_dir); curr_dir,
last_dir,
..
} = cx.local;
let mut toggle_leds = |dir: &Direction| {
let last_led = leds.for_direction(*last_dir);
last_led.off().ok(); last_led.off().ok();
let led = leds.for_direction(*dir); let led = leds.for_direction(*dir);
led.on().ok(); led.on().ok();
*cx.local.last_dir = *dir; *last_dir = *dir;
}; };
loop {
match cx.local.curr_dir.next() { match curr_dir.next() {
Some(dir) => { Some(dir) => {
toggle_leds(dir); toggle_leds(dir);
} }
None => { None => {
*cx.local.curr_dir = Direction::iter(); *curr_dir = Direction::iter();
toggle_leds(cx.local.curr_dir.next().unwrap()); toggle_leds(curr_dir.next().unwrap());
}
} }
Systick::delay(BLINK_FREQ_MS.millis()).await;
} }
blink::spawn_after(MsDuration::from_ticks(BLINK_FREQ_MS)).unwrap();
} }
#[task( #[task(
shared = [tx_transfer], shared = [tx_shared],
local = []
)] )]
fn serial_tx_handler(mut cx: serial_tx_handler::Context) { async fn serial_tx_handler(mut cx: serial_tx_handler::Context) {
if let Some((buf, len)) = TX_REQUESTS.dequeue() { loop {
cx.shared.tx_transfer.lock(|tx_state| match tx_state { let is_idle = cx.shared.tx_shared.lock(|tx_shared| {
UartTxState::Idle(tx) => { if let UartTxState::Idle(_) = tx_shared.state {
//debug!(target: "serial_tx_handler", "bytes: {:x?}", &buf[0..len]); return true;
// Safety: We only copy the data into the TX DMA buffer in this task.
// If the DMA is active, another branch will be taken.
let mut_tx_dma_buf = unsafe { &mut DMA_TX_BUF };
// 0 sentinel value as start marker
mut_tx_dma_buf[0] = 0;
// Should never panic, we accounted for the overhead.
// Write into transfer buffer directly, no need for intermediate
// encoding buffer.
let encoded_len = cobs::encode(&buf[0..len], &mut mut_tx_dma_buf[1..]);
// 0 end marker
mut_tx_dma_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.
let transfer = tx_idle
.tx
.write_all(&mut_tx_dma_buf[0..encoded_len + 2], tx_idle.dma_channel);
*tx_state = UartTxState::Transmitting(Some(transfer));
// The memory block is automatically returned to the pool when it is dropped.
}
UartTxState::Transmitting(_) => {
// This is a SW configuration error. Only the ISR which
// detects transfer completion should be able to spawn a new
// task, and that ISR should set the state to IDLE.
panic!("invalid internal tx state detected")
}
})
} else {
cx.shared.tx_transfer.lock(|tx_state| {
if let UartTxState::Idle(_) = tx_state {
serial_tx_handler::spawn_after(MsDuration::from_ticks(TX_HANDLER_FREQ_MS))
.unwrap();
} }
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 = (Systick::now() - last_completed).to_millis();
if elapsed_ms < MIN_DELAY_BETWEEN_TX_PACKETS_MS {
Systick::delay((MIN_DELAY_BETWEEN_TX_PACKETS_MS - elapsed_ms).millis())
.await;
}
}
} else {
// Check for completion after 1 ms
Systick::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
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
Systick::delay(1.millis()).await;
continue;
}
// Nothing to do, and we are idle.
Systick::delay(TX_HANDLER_FREQ_MS.millis()).await;
} }
} }
@ -375,14 +395,14 @@ mod app {
verif_reporter verif_reporter
], ],
)] )]
fn serial_rx_handler( async fn serial_rx_handler(
cx: serial_rx_handler::Context, cx: serial_rx_handler::Context,
received_packet: Box<poolmod::TC>, received_packet: Vec<u8, MAX_TC_LEN>,
rx_len: usize,
) { ) {
info!("running rx handler");
let tgt: &'static str = "serial_rx_handler"; let tgt: &'static str = "serial_rx_handler";
cx.local.stamp_buf[0] = P_FIELD_BASE; cx.local.stamp_buf[0] = P_FIELD_BASE;
info!(target: tgt, "Received packet with {} bytes", rx_len); info!(target: tgt, "Received packet with {} bytes", received_packet.len());
let decode_buf = cx.local.decode_buf; let decode_buf = cx.local.decode_buf;
let packet = received_packet.as_slice(); let packet = received_packet.as_slice();
let mut start_idx = None; let mut start_idx = None;
@ -403,7 +423,7 @@ mod app {
match cobs::decode(&received_packet.as_slice()[start_idx..], decode_buf) { match cobs::decode(&received_packet.as_slice()[start_idx..], decode_buf) {
Ok(len) => { Ok(len) => {
info!(target: tgt, "Decoded packet length: {}", len); info!(target: tgt, "Decoded packet length: {}", len);
let pus_tc = PusTc::from_bytes(decode_buf); let pus_tc = PusTcReader::new(decode_buf);
let verif_reporter = cx.local.verif_reporter; let verif_reporter = cx.local.verif_reporter;
match pus_tc { match pus_tc {
Ok((tc, tc_len)) => handle_tc( Ok((tc, tc_len)) => handle_tc(
@ -429,7 +449,7 @@ mod app {
} }
fn handle_tc( fn handle_tc(
tc: PusTc, tc: PusTcReader,
tc_len: usize, tc_len: usize,
verif_reporter: &mut VerificationReporterCore, verif_reporter: &mut VerificationReporterCore,
src_data_buf: &mut [u8; MAX_TM_LEN], src_data_buf: &mut [u8; MAX_TM_LEN],
@ -451,30 +471,23 @@ mod app {
.acceptance_failure( .acceptance_failure(
src_data_buf, src_data_buf,
token, token,
&SEQ_COUNT_PROVIDER, SEQ_COUNT_PROVIDER.get(),
FailParams::new(stamp_buf, &EcssEnumU16::new(0), None), 0,
FailParams::new(stamp_buf, &EcssEnumU16::new(0), &[]),
) )
.unwrap(); .unwrap();
let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); let sender = TmSender::new(TmPacket::new(), tgt);
let mut sender = TmSender::new(mem_block, tgt); if let Err(e) = verif_reporter.send_acceptance_failure(sendable, &sender) {
if let Err(e) =
verif_reporter.send_acceptance_failure(sendable, &SEQ_COUNT_PROVIDER, &mut sender)
{
warn!(target: tgt, "Sending acceptance failure failed: {:?}", e.0); warn!(target: tgt, "Sending acceptance failure failed: {:?}", e.0);
}; };
return; return;
} }
let sendable = verif_reporter let sendable = verif_reporter
.acceptance_success(src_data_buf, token, &SEQ_COUNT_PROVIDER, stamp_buf) .acceptance_success(src_data_buf, token, SEQ_COUNT_PROVIDER.get(), 0, stamp_buf)
.unwrap(); .unwrap();
let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); let sender = TmSender::new(TmPacket::new(), tgt);
let mut sender = TmSender::new(mem_block, tgt); let accepted_token = match verif_reporter.send_acceptance_success(sendable, &sender) {
let accepted_token = match verif_reporter.send_acceptance_success(
sendable,
&SEQ_COUNT_PROVIDER,
&mut sender,
) {
Ok(token) => token, Ok(token) => token,
Err(e) => { Err(e) => {
warn!(target: "serial_rx_handler", "Sending acceptance success failed: {:?}", e.0); warn!(target: "serial_rx_handler", "Sending acceptance success failed: {:?}", e.0);
@ -485,15 +498,17 @@ mod app {
if tc.service() == 17 { if tc.service() == 17 {
if tc.subservice() == 1 { if tc.subservice() == 1 {
let sendable = verif_reporter let sendable = verif_reporter
.start_success(src_data_buf, accepted_token, &SEQ_COUNT_PROVIDER, stamp_buf) .start_success(
src_data_buf,
accepted_token,
SEQ_COUNT_PROVIDER.get(),
0,
stamp_buf,
)
.unwrap(); .unwrap();
let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); // let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]);
let mut sender = TmSender::new(mem_block, tgt); let sender = TmSender::new(TmPacket::new(), tgt);
let started_token = match verif_reporter.send_start_success( let started_token = match verif_reporter.send_start_success(sendable, &sender) {
sendable,
&SEQ_COUNT_PROVIDER,
&mut sender,
) {
Ok(token) => token, Ok(token) => token,
Err(e) => { Err(e) => {
warn!(target: tgt, "Sending acceptance success failed: {:?}", e.0); warn!(target: tgt, "Sending acceptance success failed: {:?}", e.0);
@ -507,24 +522,28 @@ mod app {
let mut sp_header = let mut sp_header =
SpHeader::tc_unseg(PUS_APID, SEQ_COUNT_PROVIDER.get(), 0).unwrap(); SpHeader::tc_unseg(PUS_APID, SEQ_COUNT_PROVIDER.get(), 0).unwrap();
let sec_header = PusTmSecondaryHeader::new_simple(17, 2, stamp_buf); let sec_header = PusTmSecondaryHeader::new_simple(17, 2, stamp_buf);
let ping_reply = PusTm::new(&mut sp_header, sec_header, None, true); let ping_reply = PusTmCreator::new(&mut sp_header, sec_header, &[], true);
let mut mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); let mut tm_packet = TmPacket::new();
let reply_len = ping_reply.write_to_bytes(mem_block.as_mut_slice()).unwrap(); tm_packet
if TX_REQUESTS.enqueue((mem_block, reply_len)).is_err() { .resize(ping_reply.len_written(), 0)
.expect("vec resize failed");
ping_reply.write_to_bytes(&mut tm_packet).unwrap();
if TM_REQUESTS.enqueue(tm_packet).is_err() {
warn!(target: tgt, "TC queue full"); warn!(target: tgt, "TC queue full");
return; return;
} }
SEQ_COUNT_PROVIDER.increment(); SEQ_COUNT_PROVIDER.increment();
let sendable = verif_reporter let sendable = verif_reporter
.completion_success(src_data_buf, started_token, &SEQ_COUNT_PROVIDER, stamp_buf) .completion_success(
src_data_buf,
started_token,
SEQ_COUNT_PROVIDER.get(),
0,
stamp_buf,
)
.unwrap(); .unwrap();
let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); let sender = TmSender::new(TmPacket::new(), tgt);
let mut sender = TmSender::new(mem_block, tgt); if let Err(e) = verif_reporter.send_step_or_completion_success(sendable, &sender) {
if let Err(e) = verif_reporter.send_step_or_completion_success(
sendable,
&SEQ_COUNT_PROVIDER,
&mut sender,
) {
warn!(target: tgt, "Sending completion success failed: {:?}", e.0); warn!(target: tgt, "Sending completion success failed: {:?}", e.0);
} }
} else { } else {
@ -535,23 +554,23 @@ mod app {
#[task(binds = DMA1_CH6, shared = [rx_transfer])] #[task(binds = DMA1_CH6, shared = [rx_transfer])]
fn rx_dma_isr(mut cx: rx_dma_isr::Context) { fn rx_dma_isr(mut cx: rx_dma_isr::Context) {
let mut tc_packet = TcPacket::new();
cx.shared.rx_transfer.lock(|rx_transfer| { cx.shared.rx_transfer.lock(|rx_transfer| {
let rx_ref = rx_transfer.as_ref().unwrap(); let rx_ref = rx_transfer.as_ref().unwrap();
if rx_ref.is_complete() { if rx_ref.is_complete() {
let uart_rx_owned = rx_transfer.take().unwrap(); let uart_rx_owned = rx_transfer.take().unwrap();
let (buf, c, rx) = uart_rx_owned.stop(); let (buf, c, rx) = uart_rx_owned.stop();
// The received data is transferred to another task now to avoid any processing overhead // The received data is transferred to another task now to avoid any processing overhead
// during the interrupt. There are multiple ways to do this, we use a memory pool here // during the interrupt. There are multiple ways to do this, we use a stack allocaed vector here
// to do this. // to do this.
let mut mem_block = poolmod::TC::alloc() tc_packet.resize(buf.len(), 0).expect("vec resize failed");
.expect("allocating memory block for rx failed") tc_packet.copy_from_slice(buf);
.init([0u8; TC_BUF_LEN]);
// Copy data into memory pool. // Start the next transfer as soon as possible.
mem_block.copy_from_slice(buf);
*rx_transfer = Some(rx.read_exact(buf, c)); *rx_transfer = Some(rx.read_exact(buf, c));
// Only send owning pointer to pool memory and the received packet length.
serial_rx_handler::spawn(mem_block, TC_BUF_LEN) // Send the vector to a regular task.
.expect("spawning rx handler task failed"); serial_rx_handler::spawn(tc_packet).expect("spawning rx handler task failed");
// If this happens, there is a high chance that the maximum packet length was // If this happens, there is a high chance that the maximum packet length was
// exceeded. Circular mode is not used here, so data might be missed. // exceeded. Circular mode is not used here, so data might be missed.
warn!( warn!(
@ -562,23 +581,26 @@ mod app {
}); });
} }
#[task(binds = USART2_EXTI26, shared = [rx_transfer, tx_transfer])] #[task(binds = USART2_EXTI26, shared = [rx_transfer, tx_shared])]
fn serial_isr(mut cx: serial_isr::Context) { fn serial_isr(mut cx: serial_isr::Context) {
cx.shared.tx_transfer.lock(|tx_state| match tx_state { cx.shared
UartTxState::Idle(_) => (), .tx_shared
UartTxState::Transmitting(transfer) => { .lock(|tx_shared| match &mut tx_shared.state {
let transfer_ref = transfer.as_ref().unwrap(); UartTxState::Idle(_) => (),
if transfer_ref.is_complete() { UartTxState::Transmitting(transfer) => {
let transfer = transfer.take().unwrap(); let transfer_ref = transfer.as_ref().unwrap();
let (_, dma_channel, tx) = transfer.stop(); if transfer_ref.is_complete() {
*tx_state = UartTxState::Idle(Some(TxIdle { tx, dma_channel })); let transfer = transfer.take().unwrap();
serial_tx_handler::spawn_after(MsDuration::from_ticks( let (_, dma_channel, mut tx) = transfer.stop();
MIN_DELAY_BETWEEN_TX_PACKETS_MS.into(), tx.clear_event(TxEvent::TransmissionComplete);
)) tx_shared.state = UartTxState::Idle(Some(TxIdle { tx, dma_channel }));
.unwrap(); // We cache the last completed time to ensure that there is a minimum delay between consecutive
// transferred packets.
tx_shared.last_completed = Some(Systick::now());
}
} }
} });
}); let mut tc_packet = TcPacket::new();
cx.shared.rx_transfer.lock(|rx_transfer| { cx.shared.rx_transfer.lock(|rx_transfer| {
let rx_transfer_ref = rx_transfer.as_ref().unwrap(); let rx_transfer_ref = rx_transfer.as_ref().unwrap();
// Received a partial packet. // Received a partial packet.
@ -586,17 +608,15 @@ mod app {
let rx_transfer_owned = rx_transfer.take().unwrap(); let rx_transfer_owned = rx_transfer.take().unwrap();
let (buf, ch, mut rx, rx_len) = rx_transfer_owned.stop_and_return_received_bytes(); let (buf, ch, mut rx, rx_len) = rx_transfer_owned.stop_and_return_received_bytes();
// The received data is transferred to another task now to avoid any processing overhead // The received data is transferred to another task now to avoid any processing overhead
// during the interrupt. There are multiple ways to do this, we use a memory pool here // during the interrupt. There are multiple ways to do this, we use a stack
// to do this. // allocated vector to do this.
let mut mem_block = poolmod::TC::alloc() tc_packet
.expect("allocating memory block for rx failed") .resize(rx_len as usize, 0)
.init([0u8; TC_BUF_LEN]); .expect("vec resize failed");
// Copy data into memory pool. tc_packet[0..rx_len as usize].copy_from_slice(&buf[0..rx_len as usize]);
mem_block[0..rx_len as usize].copy_from_slice(&buf[0..rx_len as usize]);
rx.clear_event(RxEvent::Idle); rx.clear_event(RxEvent::Idle);
// Only send owning pointer to pool memory and the received packet length. info!("spawning rx task");
serial_rx_handler::spawn(mem_block, rx_len as usize) serial_rx_handler::spawn(tc_packet).expect("spawning rx handler failed");
.expect("spawning rx handler task failed");
*rx_transfer = Some(rx.read_exact(buf, ch)); *rx_transfer = Some(rx.read_exact(buf, ch));
} }
}); });

View File

@ -11,7 +11,8 @@ proc CDSWOConfigure { CDCPUFreqHz CDSWOFreqHz CDSWOOutput } {
# Alternative option: Pipe ITM output into itm.txt file # Alternative option: Pipe ITM output into itm.txt file
# tpiu config internal itm.txt uart off $CDCPUFreqHz # tpiu config internal itm.txt uart off $CDCPUFreqHz
# Default option so SWO display of VS code works. # Default option so SWO display of VS code works. Please note that this might not be required
# anymore starting at openocd v0.12.0
tpiu config internal $CDSWOOutput uart off $CDCPUFreqHz $CDSWOFreqHz tpiu config internal $CDSWOOutput uart off $CDCPUFreqHz $CDSWOFreqHz
itm port 0 on itm port 0 on
} }