diff --git a/.gitignore b/.gitignore index ed68b57..91f35d4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,7 @@ target/ /Cargo.lock output.log +output.log + /.idea/* !/.idea/runConfigurations diff --git a/satrs-example-stm32f3-disco/.cargo/def_config.toml b/satrs-example-stm32f3-disco/.cargo/def_config.toml new file mode 100644 index 0000000..4150986 --- /dev/null +++ b/satrs-example-stm32f3-disco/.cargo/def_config.toml @@ -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) diff --git a/satrs-example-stm32f3-disco/.gitignore b/satrs-example-stm32f3-disco/.gitignore index 767b60e..63b4a75 100644 --- a/satrs-example-stm32f3-disco/.gitignore +++ b/satrs-example-stm32f3-disco/.gitignore @@ -1,3 +1,4 @@ /target /itm.txt /.cargo/config* +/.vscode diff --git a/satrs-example-stm32f3-disco/.vscode/settings_default.json b/satrs-example-stm32f3-disco/.vscode/settings_default.json deleted file mode 100644 index e78c4ec..0000000 --- a/satrs-example-stm32f3-disco/.vscode/settings_default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "cortex-debug.gdbPath.linux": "gdb-multiarch" -} diff --git a/satrs-example-stm32f3-disco/Cargo.lock b/satrs-example-stm32f3-disco/Cargo.lock index e8d9f02..9043d7a 100644 --- a/satrs-example-stm32f3-disco/Cargo.lock +++ b/satrs-example-stm32f3-disco/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "atomic-polyfill" -version = "0.1.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" dependencies = [ "critical-section", ] @@ -55,20 +55,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bxcan" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b13b4b2ea9ab2ba924063ebb86ad895cb79f4a79bf90f27949eb20c335b30f9" +checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" dependencies = [ "bitflags", - "nb 1.0.0", + "embedded-hal 0.2.7", + "nb 1.1.0", "vcell", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cast" @@ -87,31 +88,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ - "num-integer", "num-traits", ] [[package]] -name = "cortex-m" -version = "0.7.6" +name = "cobs" +version = "0.2.3" 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 = [ "bare-metal 0.2.5", "bitfield", - "embedded-hal", + "critical-section", + "embedded-hal 0.2.7", "volatile-register", ] [[package]] name = "cortex-m-rt" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6d3328b8b5534f0c90acd66b68950f2763b37e0173cac4d8b4937c4a80761f9" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" dependencies = [ "cortex-m-rt-macros", ] @@ -124,48 +136,35 @@ checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] -name = "cortex-m-rtic" -version = "1.1.3" +name = "crc" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b82f1c39acd6c3a35c2013b6110c20f5bc534522791fabadeed49ccada2dce" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" dependencies = [ - "bare-metal 1.0.0", - "cortex-m", - "cortex-m-rtic-macros", - "heapless", - "rtic-core", - "rtic-monotonic", - "version_check", + "crc-catalog", ] [[package]] -name = "cortex-m-rtic-macros" -version = "1.1.5" +name = "crc-catalog" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8e9645ef54bec1cf70ac33e9bf9566e6507ab5b41ae6baf3735662194e8607" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "rtic-syntax", - "syn", -] +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "critical-section" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" [[package]] name = "darling" -version = "0.14.2" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -173,26 +172,37 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.2" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn", + "syn 2.0.53", ] [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "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]] @@ -214,6 +224,12 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "embedded-time" version = "0.12.1" @@ -225,25 +241,31 @@ dependencies = [ [[package]] name = "enumset" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" +checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ "darling", "proc-macro2", "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]] name = "fnv" version = "1.0.7" @@ -252,18 +274,42 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fugit" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab17bb279def6720d058cb6c052249938e7f99260ab534879281a95367a87e5" +checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" dependencies = [ "gcd", ] [[package]] -name = "gcd" -version = "2.2.0" +name = "futures-core" +version = "0.3.30" 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]] name = "generic-array" @@ -276,9 +322,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -286,29 +332,26 @@ dependencies = [ [[package]] name = "hash32" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" dependencies = [ "byteorder", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heapless" -version = "0.7.16" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "atomic-polyfill", "hash32", - "rustc_version 0.4.0", - "spin", "stable_deref_trait", ] @@ -320,40 +363,28 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "1.9.2" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] [[package]] 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 = [ "cortex-m", "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]] name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lsm303dlhc" @@ -362,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5d1a5c290951321d1b0d4a40edd828537de9889134a0e67c5146542ae57706" dependencies = [ "cast", - "embedded-hal", + "embedded-hal 0.2.7", "generic-array 0.11.2", ] @@ -372,7 +403,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -381,14 +412,14 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" dependencies = [ - "nb 1.0.0", + "nb 1.1.0", ] [[package]] name = "nb" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" [[package]] name = "num" @@ -414,19 +445,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -446,13 +476,33 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "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]] name = "panic-itm" version = "0.4.2" @@ -464,9 +514,21 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.11" +version = "1.0.14" 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]] name = "proc-macro-error" @@ -477,7 +539,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -494,31 +556,54 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "rtcc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3623619ce77c09a7d87cf7c61c5c887b9c7dee8805f66af6c4aa5824be4d9930" +checksum = "f4fbd0d5bed2b76e27a7ef872568b34072c1af94c277cd52c17a89d54673b3fe" dependencies = [ "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]] name = "rtic-core" version = "1.0.0" @@ -526,21 +611,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42" [[package]] -name = "rtic-monotonic" -version = "1.0.0" +name = "rtic-macros" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8b0b822d1a366470b9cea83a1d4e788392db763539dc4ba022bcc787fece82" - -[[package]] -name = "rtic-syntax" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad3ae243dd8d0a1b064615f664d4fa7e63929939074c564cbe5efdc4c503065" +checksum = "54053598ea24b1b74937724e366558412a1777eb2680b91ef646db540982789a" dependencies = [ "indexmap", + "proc-macro-error", "proc-macro2", "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]] @@ -558,31 +663,53 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.16", + "semver 1.0.22", ] [[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" dependencies = [ + "cobs 0.2.3 (git+https://github.com/robamu/cobs.rs.git?branch=all_features)", "cortex-m", "cortex-m-rt", - "cortex-m-rtic", - "embedded-hal", + "embedded-hal 0.2.7", "enumset", "heapless", "itm_logger", "panic-itm", + "rtic", + "rtic-monotonics", + "satrs", "stm32f3-discovery", "stm32f3xx-hal", - "systick-monotonic", ] [[package]] -name = "scopeguard" -version = "1.1.0" +name = "satrs-shared" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "75a402ba556a7f5eef707035b45e64a3259b09674311e98697f3dd0508a1bf51" +dependencies = [ + "spacepackets", +] [[package]] name = "semver" @@ -595,9 +722,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "semver-parser" @@ -607,17 +734,28 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "slice-group-by" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] -name = "spin" -version = "0.9.4" +name = "smallvec" +version = "1.13.2" 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 = [ - "lock_api", + "chrono", + "crc", + "delegate", + "num-traits", + "num_enum", + "zerocopy", ] [[package]] @@ -639,9 +777,9 @@ dependencies = [ [[package]] name = "stm32f3" -version = "0.14.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265cda62ac13307414de4aca58dbbbd8038ddba85cffbb335823aa216f2e3200" +checksum = "b28b37228ef3fa47956af38c6abd756e912f244c1657f14e66d42fc8d74ea96f" dependencies = [ "bare-metal 1.0.0", "cortex-m", @@ -651,7 +789,8 @@ dependencies = [ [[package]] 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 = [ "accelerometer", "cortex-m", @@ -663,20 +802,20 @@ dependencies = [ [[package]] name = "stm32f3xx-hal" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e422c5c044e8f3a068b1e14b83c071449e27c9d4bc0e24f972b552d79f2be03" +version = "0.11.0-alpha.0" +source = "git+https://github.com/robamu/stm32f3xx-hal?branch=complete-dma-update#04fc76b7912649c84b57bd0ab803ea3ccf2aadae" dependencies = [ - "bare-metal 1.0.0", "bxcan", "cfg-if", "cortex-m", "cortex-m-rt", + "critical-section", "embedded-dma", - "embedded-hal", + "embedded-hal 0.2.7", "embedded-time", "enumset", - "nb 1.0.0", + "nb 1.1.0", + "num-traits", "paste", "rtcc", "slice-group-by", @@ -691,14 +830,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90a4adc8cbd1726249b161898e48e0f3f1ce74d34dc784cbbc98fba4ed283fbf" dependencies = [ - "embedded-hal", + "embedded-hal 0.2.7", ] [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -706,27 +845,27 @@ dependencies = [ ] [[package]] -name = "systick-monotonic" -version = "1.0.1" +name = "syn" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fb822d5c615a0ae3a4795ee5b1d06381c7faf488d861c0a4fa8e6a88d5ff84" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ - "cortex-m", - "fugit", - "rtic-monotonic", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "usb-device" @@ -754,9 +893,30 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "volatile-register" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" dependencies = [ "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", +] diff --git a/satrs-example-stm32f3-disco/Cargo.toml b/satrs-example-stm32f3-disco/Cargo.toml index dec4cab..4337919 100644 --- a/satrs-example-stm32f3-disco/Cargo.toml +++ b/satrs-example-stm32f3-disco/Cargo.toml @@ -6,13 +6,19 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cortex-m = "0.7" +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" -embedded-hal = "0.2.6" -cortex-m-rtic = "1.0" -enumset = "1.0" -heapless = "0.7" -systick-monotonic = "1.0" +embedded-hal = "0.2.7" +enumset = "1" +heapless = "0.8" + +[dependencies.rtic] +version = "2" +features = ["thumbv7-backend"] + +[dependencies.rtic-monotonics] +version = "1" +features = ["cortex-m-systick"] [dependencies.cobs] git = "https://github.com/robamu/cobs.rs.git" @@ -29,22 +35,22 @@ version = "0.1.3-alpha.0" [dependencies.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"] -branch = "all_features" +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 = "all_features" +branch = "complete-dma-update-hal" # Can be used in workspace to develop and update BSP # path = "../stm32f3-discovery" -[dependencies.satrs-core] -git = "https://egit.irs.uni-stuttgart.de/rust/satrs-core.git" -version = "0.1.0-alpha.0" +[dependencies.satrs] +# git = "https://egit.irs.uni-stuttgart.de/rust/satrs-core.git" +version = "0.2.0-rc.0" default-features = false # this lets you use `cargo fix`! diff --git a/satrs-example-stm32f3-disco/README.md b/satrs-example-stm32f3-disco/README.md index 9e98f05..9d502fa 100644 --- a/satrs-example-stm32f3-disco/README.md +++ b/satrs-example-stm32f3-disco/README.md @@ -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 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 Building an application requires the `thumbv7em-none-eabihf` cross-compiler toolchain. @@ -42,13 +54,25 @@ cargo build ## 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 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` 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` to automatically rebuild and flash your application. @@ -67,9 +91,23 @@ configuration variables in your `settings.json`: ## Commanding with Python 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: - - How and where to connect serial interface on the MCU - - How to set up Python venv (or at least strongly recommend it) and install deps - - How to copy `def_tmtc_conf.json` to `tmtc_conf.json` and adapt it for custom serial port +It is recommended to use a virtual environment to do this. To set up one in the command line, +you can use `python3 -m venv venv` on Unix systems or `py -m venv venv` on Windows systems. +After doing this, you can check the [venv tutorial](https://docs.python.org/3/tutorial/venv.html) +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 +``` diff --git a/satrs-example-stm32f3-disco/openocd.gdb b/satrs-example-stm32f3-disco/openocd.gdb index 0ba0c09..06e81b1 100644 --- a/satrs-example-stm32f3-disco/openocd.gdb +++ b/satrs-example-stm32f3-disco/openocd.gdb @@ -24,7 +24,9 @@ break main # # send captured ITM to the file itm.fifo # # (the microcontroller SWO pin must be connected to the programmer SWO pin) # # 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) # # 8000000 must match the core clock frequency diff --git a/satrs-example-stm32f3-disco/pyclient/.gitignore b/satrs-example-stm32f3-disco/pyclient/.gitignore index a0c9366..da26576 100644 --- a/satrs-example-stm32f3-disco/pyclient/.gitignore +++ b/satrs-example-stm32f3-disco/pyclient/.gitignore @@ -1,4 +1,5 @@ /venv +/.tmtc-history.txt /log /.idea/* !/.idea/runConfigurations diff --git a/satrs-example-stm32f3-disco/pyclient/def_tmtc_conf.json b/satrs-example-stm32f3-disco/pyclient/def_tmtc_conf.json index 5665681..76db442 100644 --- a/satrs-example-stm32f3-disco/pyclient/def_tmtc_conf.json +++ b/satrs-example-stm32f3-disco/pyclient/def_tmtc_conf.json @@ -1,4 +1,4 @@ { "com_if": "serial_cobs", "serial_baudrate": 115200 -} \ No newline at end of file +} diff --git a/satrs-example-stm32f3-disco/pyclient/main.py b/satrs-example-stm32f3-disco/pyclient/main.py old mode 100644 new mode 100755 index a5fa9cd..d37da58 --- a/satrs-example-stm32f3-disco/pyclient/main.py +++ b/satrs-example-stm32f3-disco/pyclient/main.py @@ -1,39 +1,40 @@ #!/usr/bin/env python3 """Example client for the sat-rs example application""" -import enum import struct +import logging import sys 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 from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator from spacepackets.ecss.pus_17_test import Service17Tm 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.ccsds_backend import QueueWrapper +from tmtccmd.logging import add_colorlog_console_logger from tmtccmd.pus import VerificationWrapper -from tmtccmd.tm import CcsdsTmHandler, SpecificApidHandlerBase -from tmtccmd.com_if import ComInterface +from tmtccmd.tmtc import CcsdsTmHandler, SpecificApidHandlerBase +from tmtccmd.com import ComInterface from tmtccmd.config import ( + CmdTreeNode, default_json_path, SetupParams, - TmTcCfgHookBase, - TmtcDefinitionWrapper, - CoreServiceList, - OpCodeEntry, + HookBase, 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.logging import get_console_logger from tmtccmd.logging.pus import ( RegularTmtcLogWrapper, RawTmtcTimedLogWrapper, TimedLogWhen, ) -from tmtccmd.tc import ( +from tmtccmd.tmtc import ( TcQueueEntryType, ProcedureWrapper, TcProcedureType, @@ -41,27 +42,26 @@ from tmtccmd.tc import ( SendCbParams, 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.obj_id import ObjectIdDictT -from tmtccmd.util.tmtc_printer import FsfwTmTcPrinter - -LOGGER = get_console_logger() +_LOGGER = logging.getLogger() EXAMPLE_PUS_APID = 0x02 -class SatRsConfigHook(TmTcCfgHookBase): +class SatRsConfigHook(HookBase): def __init__(self, json_cfg_path: str): super().__init__(json_cfg_path=json_cfg_path) - def assign_communication_interface(self, com_if_key: str) -> Optional[ComInterface]: - from tmtccmd.config.com_if import ( + def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]: + from tmtccmd.config.com import ( create_com_interface_default, create_com_interface_cfg_default, ) + assert self.cfg_path is not None cfg = create_com_interface_cfg_default( com_if_key=com_if_key, json_cfg_path=self.cfg_path, @@ -76,35 +76,14 @@ class SatRsConfigHook(TmTcCfgHookBase): cfg.serial_cfg.serial_timeout = 0.5 return create_com_interface_default(cfg) - def get_tmtc_definitions(self) -> TmtcDefinitionWrapper: - from tmtccmd.config.globals import get_default_tmtc_defs + def get_command_definitions(self) -> CmdTreeNode: + """This function should return the root node of the command definition tree.""" + return create_cmd_definition_tree() - defs = get_default_tmtc_defs() - srv_5 = OpCodeEntry() - srv_5.add("0", "Event Test") - defs.add_service( - 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_cmd_history(self) -> Optional[History]: + """Optionlly return a history class for the past command paths which will be used + when prompting a command path from the user in CLI mode.""" + return FileHistory(".tmtc-history.txt") def get_object_ids(self) -> ObjectIdDictT: from tmtccmd.config.objects import get_core_object_ids @@ -112,74 +91,75 @@ class SatRsConfigHook(TmTcCfgHookBase): 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): def __init__( self, + file_logger: logging.Logger, verif_wrapper: VerificationWrapper, - printer: FsfwTmTcPrinter, raw_logger: RawTmtcTimedLogWrapper, ): super().__init__(EXAMPLE_PUS_APID, None) - self.printer = printer + self.file_logger = file_logger self.raw_logger = raw_logger 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: - tm_packet = PusTelemetry.unpack(packet) + pus_tm = PusTelemetry.unpack(packet, time_reader=CdsShortTimestamp.empty()) except ValueError as e: - LOGGER.warning("Could not generate PUS TM object from raw data") - LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}") + _LOGGER.warning("Could not generate PUS TM object from raw data") + _LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}") raise e - service = tm_packet.service - dedicated_handler = False + service = pus_tm.service + tm_packet = None 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) if res is None: - LOGGER.info( + _LOGGER.info( f"Received Verification TM[{tm_packet.service}, {tm_packet.subservice}] " 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}" ) else: self.verif_wrapper.log_to_console(tm_packet, res) self.verif_wrapper.log_to_file(tm_packet, res) - dedicated_handler = True if service == 3: - LOGGER.info("No handling for HK packets implemented") - LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]") - pus_tm = PusTelemetry.unpack(packet) + _LOGGER.info("No handling for HK packets implemented") + _LOGGER.info(f"Raw packet: 0x[{packet.hex(sep=',')}]") + pus_tm = PusTelemetry.unpack(packet, CdsShortTimestamp.empty()) if pus_tm.subservice == 25: if len(pus_tm.source_data) < 8: raise ValueError("No addressable ID in HK packet") json_str = pus_tm.source_data[8:] - dedicated_handler = True + _LOGGER.info("received JSON string: " + json_str.decode("utf-8")) if service == 5: - tm_packet = Service5Tm.unpack(packet) + tm_packet = Service5Tm.unpack(packet, time_reader) if service == 17: - tm_packet = Service17Tm.unpack(packet) - dedicated_handler = True + tm_packet = Service17Tm.unpack(packet, time_reader) 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: - self.printer.file_logger.info( - f"Received Test Packet with unknown subservice {tm_packet.subservice}" - ) - LOGGER.info( + _LOGGER.info( f"Received Test Packet with unknown subservice {tm_packet.subservice}" ) if tm_packet is None: - LOGGER.info( + _LOGGER.info( f"The service {service} is not implemented in Telemetry Factory" ) - tm_packet = PusTelemetry.unpack(packet) - self.raw_logger.log_tm(tm_packet) - if not dedicated_handler and tm_packet is not None: - self.printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet) + tm_packet = PusTelemetry.unpack(packet, time_reader) + self.raw_logger.log_tm(pus_tm) 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.verif_wrapper = verif_wrapper self.queue_helper = DefaultPusQueueHelper( - queue_wrapper=None, + queue_wrapper=QueueWrapper.empty(), + tc_sched_timestamp_len=7, 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): @@ -212,61 +195,55 @@ class TcHandler(TcHandlerBase): ) self.verif_wrapper.add_tc(pus_tc_wrapper.pus_tc) 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) elif entry_helper.entry_type == TcQueueEntryType.LOG: 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): - if helper.proc_type == TcProcedureType.DEFAULT: - def_proc = helper.to_def_procedure() - LOGGER.info( - f"Queue handling finished for service {def_proc.service} and " - f"op code {def_proc.op_code}" - ) + def queue_finished_cb(self, info: ProcedureWrapper): + if info.proc_type == TcProcedureType.DEFAULT: + def_proc = info.to_def_procedure() + _LOGGER.info(f"Queue handling finished for command {def_proc.cmd_path}") - def feed_cb(self, helper: ProcedureWrapper, wrapper: FeedWrapper): + def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper): q = self.queue_helper q.queue_wrapper = wrapper.queue_wrapper - if helper.proc_type == TcProcedureType.DEFAULT: - def_proc = helper.to_def_procedure() - service = def_proc.service - op_code = def_proc.op_code - if ( - service == CoreServiceList.SERVICE_17 - or service == CoreServiceList.SERVICE_17_ALT - ): + if info.proc_type == TcProcedureType.DEFAULT: + def_proc = info.to_def_procedure() + cmd_path = def_proc.cmd_path + if cmd_path == "/ping": 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(): + add_colorlog_console_logger(_LOGGER) tmtccmd.init_printout(False) hook_obj = SatRsConfigHook(json_cfg_path=default_json_path()) parser_wrapper = PreArgsParsingWrapper() parser_wrapper.create_default_parent_parser() parser_wrapper.create_default_parser() parser_wrapper.add_def_proc_args() - post_args_wrapper = parser_wrapper.parse(hook_obj) params = SetupParams() + post_args_wrapper = parser_wrapper.parse(hook_obj, params) proc_wrapper = ProcedureParamsWrapper() 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: - post_args_wrapper.set_params_with_prompts(params, proc_wrapper) + post_args_wrapper.set_params_with_prompts(proc_wrapper) params.apid = EXAMPLE_PUS_APID setup_args = SetupWrapper( hook_obj=hook_obj, setup_params=params, proc_param_wrapper=proc_wrapper ) # Create console logger helper and file loggers tmtc_logger = RegularTmtcLogWrapper() - printer = FsfwTmTcPrinter(tmtc_logger.logger) + file_logger = tmtc_logger.logger raw_logger = RawTmtcTimedLogWrapper(when=TimedLogWhen.PER_HOUR, interval=1) 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 - 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.add_apid_handler(tm_handler) @@ -288,7 +265,7 @@ def main(): if state.request == BackendRequest.TERMINATION_NO_ERROR: sys.exit(0) elif state.request == BackendRequest.DELAY_IDLE: - LOGGER.info("TMTC Client in IDLE mode") + _LOGGER.info("TMTC Client in IDLE mode") time.sleep(3.0) elif state.request == BackendRequest.DELAY_LISTENER: time.sleep(0.8) diff --git a/satrs-example-stm32f3-disco/pyclient/requirements.txt b/satrs-example-stm32f3-disco/pyclient/requirements.txt index d9a7ac1..e934469 100644 --- a/satrs-example-stm32f3-disco/pyclient/requirements.txt +++ b/satrs-example-stm32f3-disco/pyclient/requirements.txt @@ -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 diff --git a/satrs-example-stm32f3-disco/src/main.rs b/satrs-example-stm32f3-disco/src/main.rs index 8762cbf..8795786 100644 --- a/satrs-example-stm32f3-disco/src/main.rs +++ b/satrs-example-stm32f3-disco/src/main.rs @@ -4,35 +4,33 @@ extern crate panic_itm; use rtic::app; -use heapless::{ - mpmc::Q16, - pool, - pool::singleton::{Box, Pool}, -}; +use heapless::{mpmc::Q8, Vec}; #[allow(unused_imports)] use itm_logger::{debug, info, logger_init, warn}; -use satrs_core::spacepackets::{ecss::PusPacket, tm::PusTm}; -use satrs_core::{ - pus::{EcssTmErrorWithSend, EcssTmSenderCore}, - seq_count::SequenceCountProviderCore, +use rtic_monotonics::systick::fugit::TimerInstantU32; +use rtic_monotonics::systick::ExtU32; +use satrs::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::gpio::{PushPull, AF7, PA2, PA3}; use stm32f3xx_hal::pac::USART2; use stm32f3xx_hal::serial::{Rx, RxEvent, Serial, SerialDmaRx, SerialDmaTx, Tx, TxEvent}; -use systick_monotonic::{fugit::Duration, Systick}; const UART_BAUD: u32 = 115200; -const BLINK_FREQ_MS: u64 = 1000; -const TX_HANDLER_FREQ_MS: u64 = 20; -const MIN_DELAY_BETWEEN_TX_PACKETS_MS: u16 = 5; -const MAX_TC_LEN: usize = 200; -const MAX_TM_LEN: usize = 200; +const BLINK_FREQ_MS: u32 = 1000; +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>>; type RxType = Rx>>; -type MsDuration = Duration; +type InstantFugit = TimerInstantU32<1000>; type TxDmaTransferType = SerialDmaTx<&'static [u8], dma1::C7, TxType>; 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. static mut DMA_RX_BUF: [u8; TC_BUF_LEN] = [0; TC_BUF_LEN]; -static TX_REQUESTS: Q16<(Box, usize)> = Q16::new(); +type TmPacket = Vec; +type TcPacket = Vec; -const TC_POOL_SLOTS: usize = 12; -const TM_POOL_SLOTS: usize = 12; +static TM_REQUESTS: Q8 = Q8::new(); + +use core::cell::RefCell; use core::sync::atomic::{AtomicU16, Ordering}; pub struct SeqCountProviderAtomicRef { @@ -88,70 +88,56 @@ impl SequenceCountProviderCore for SeqCountProviderAtomicRef { static SEQ_COUNT_PROVIDER: SeqCountProviderAtomicRef = 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 { tx: TxType, dma_channel: dma1::C7, } -#[derive(Debug)] -pub enum TmStoreError { - StoreFull, - StoreSlotsTooSmall, -} - -impl From for EcssTmErrorWithSend { - fn from(value: TmStoreError) -> Self { - Self::SendError(value) - } -} - pub struct TmSender { - mem_block: Option>, + vec: Option>>, ctx: &'static str, } impl TmSender { - pub fn new(mem_block: Box, ctx: &'static str) -> Self { + pub fn new(tm_packet: TmPacket, ctx: &'static str) -> Self { Self { - mem_block: Some(mem_block), + vec: Some(RefCell::new(tm_packet)), ctx, } } } -impl EcssTmSenderCore for TmSender { - type Error = TmStoreError; +impl EcssChannel for TmSender { + fn id(&self) -> satrs::ChannelId { + 0 + } +} - fn send_tm( - &mut self, - tm: PusTm, - ) -> Result<(), satrs_core::pus::EcssTmErrorWithSend> { - let mem_block = self.mem_block.take(); - if mem_block.is_none() { +impl EcssTmSenderCore for TmSender { + fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { + let vec = self.vec.as_ref(); + if vec.is_none() { panic!("send_tm should only be called once"); } - let mut mem_block = mem_block.unwrap(); - if tm.len_packed() > MAX_TM_LEN { - return Err(EcssTmErrorWithSend::SendError( - TmStoreError::StoreSlotsTooSmall, - )); + let vec_ref = vec.unwrap(); + let mut vec = vec_ref.borrow_mut(); + match tm { + 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(()) } } @@ -163,33 +149,37 @@ pub enum UartTxState { Transmitting(Option), } -#[app(device = stm32f3xx_hal::pac, peripherals = true, dispatchers = [TIM20_BRK, TIM20_UP, TIM20_TRG_COM])] +pub struct UartTxShared { + last_completed: Option, + state: UartTxState, +} + +#[app(device = stm32f3xx_hal::pac, peripherals = true)] mod app { use super::*; use core::slice::Iter; use cortex_m::iprintln; - use satrs_core::pus::verification::FailParams; - use satrs_core::pus::verification::VerificationReporterCore; - use satrs_core::spacepackets::{ - ecss::EcssEnumU16, - tc::PusTc, - time::cds::P_FIELD_BASE, - tm::{PusTm, PusTmSecondaryHeader}, - CcsdsPacket, SpHeader, + use rtic_monotonics::systick::Systick; + use rtic_monotonics::Monotonic; + use satrs::pus::verification::FailParams; + use satrs::pus::verification::VerificationReporterCore; + use satrs::spacepackets::{ + ecss::tc::PusTcReader, ecss::tm::PusTmCreator, ecss::tm::PusTmSecondaryHeader, + ecss::EcssEnumU16, time::cds::P_FIELD_BASE, CcsdsPacket, SpHeader, }; #[allow(unused_imports)] use stm32f3_discovery::leds::Direction; use stm32f3_discovery::leds::Leds; use stm32f3xx_hal::prelude::*; - use stm32f3xx_hal::Toggle; use stm32f3_discovery::switch_hal::OutputSwitch; + use stm32f3xx_hal::Switch; #[allow(dead_code)] type SerialType = Serial>, PA3>)>; #[shared] struct Shared { - tx_transfer: UartTxState, + tx_shared: UartTxShared, rx_transfer: Option, } @@ -201,17 +191,14 @@ mod app { curr_dir: Iter<'static, Direction>, } - #[monotonic(binds = SysTick, default = true)] - type MonoTimer = Systick<1000>; - - #[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) { + #[init] + fn init(mut cx: init::Context) -> (Shared, Local) { 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(); let mut flash = cx.device.FLASH.constrain(); let clocks = rcc @@ -220,15 +207,16 @@ mod app { .sysclk(8.MHz()) .pclk1(8.MHz()) .freeze(&mut flash.acr); + + // Set up monotonic timer. + //let mono_timer = MonoTimer::new(cx.core.DWT, clocks, &mut cx.core.DCB); + // setup ITM output iprintln!( &mut cx.core.ITM.stim[0], "Starting sat-rs demo application for the STM32F3-Discovery" ); 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(); @@ -264,106 +252,138 @@ mod app { clocks, &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. - 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 (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 // by the hardware when data is received on RX (RXNE event) 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); info!(target: "init", "Spawning tasks"); blink::spawn().unwrap(); serial_tx_handler::spawn().unwrap(); ( Shared { - tx_transfer: UartTxState::Idle(Some(TxIdle { - tx: tx_serial, - dma_channel: dma1.ch7, - })), + tx_shared: UartTxShared { + last_completed: None, + state: UartTxState::Idle(Some(TxIdle { + tx: tx_serial, + dma_channel: dma1.ch7, + })), + }, rx_transfer: Some(rx_transfer), }, Local { + //timer: mono_timer, leds, last_dir: Direction::North, curr_dir: Direction::iter(), verif_reporter, }, - init::Monotonics(mono), ) } #[task(local = [leds, curr_dir, last_dir])] - fn blink(cx: blink::Context) { - let toggle_leds = |dir: &Direction| { - let leds = cx.local.leds; - let last_led = leds.for_direction(*cx.local.last_dir); + async fn blink(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(); - *cx.local.last_dir = *dir; + *last_dir = *dir; }; - - match cx.local.curr_dir.next() { - Some(dir) => { - toggle_leds(dir); - } - None => { - *cx.local.curr_dir = Direction::iter(); - toggle_leds(cx.local.curr_dir.next().unwrap()); + loop { + match curr_dir.next() { + Some(dir) => { + toggle_leds(dir); + } + None => { + *curr_dir = Direction::iter(); + toggle_leds(curr_dir.next().unwrap()); + } } + Systick::delay(BLINK_FREQ_MS.millis()).await; } - blink::spawn_after(MsDuration::from_ticks(BLINK_FREQ_MS)).unwrap(); } #[task( - shared = [tx_transfer], - local = [] + shared = [tx_shared], )] - fn serial_tx_handler(mut cx: serial_tx_handler::Context) { - if let Some((buf, len)) = TX_REQUESTS.dequeue() { - cx.shared.tx_transfer.lock(|tx_state| match tx_state { - UartTxState::Idle(tx) => { - //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. - 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(); + async fn serial_tx_handler(mut cx: serial_tx_handler::Context) { + loop { + 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 = (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 ], )] - fn serial_rx_handler( + async fn serial_rx_handler( cx: serial_rx_handler::Context, - received_packet: Box, - rx_len: usize, + received_packet: Vec, ) { + info!("running rx handler"); let tgt: &'static str = "serial_rx_handler"; 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 packet = received_packet.as_slice(); let mut start_idx = None; @@ -403,7 +423,7 @@ mod app { match cobs::decode(&received_packet.as_slice()[start_idx..], decode_buf) { Ok(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; match pus_tc { Ok((tc, tc_len)) => handle_tc( @@ -429,7 +449,7 @@ mod app { } fn handle_tc( - tc: PusTc, + tc: PusTcReader, tc_len: usize, verif_reporter: &mut VerificationReporterCore, src_data_buf: &mut [u8; MAX_TM_LEN], @@ -451,30 +471,23 @@ mod app { .acceptance_failure( src_data_buf, token, - &SEQ_COUNT_PROVIDER, - FailParams::new(stamp_buf, &EcssEnumU16::new(0), None), + SEQ_COUNT_PROVIDER.get(), + 0, + FailParams::new(stamp_buf, &EcssEnumU16::new(0), &[]), ) .unwrap(); - let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); - let mut sender = TmSender::new(mem_block, tgt); - if let Err(e) = - verif_reporter.send_acceptance_failure(sendable, &SEQ_COUNT_PROVIDER, &mut sender) - { + let sender = TmSender::new(TmPacket::new(), tgt); + if let Err(e) = verif_reporter.send_acceptance_failure(sendable, &sender) { warn!(target: tgt, "Sending acceptance failure failed: {:?}", e.0); }; return; } 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(); - let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); - let mut sender = TmSender::new(mem_block, tgt); - let accepted_token = match verif_reporter.send_acceptance_success( - sendable, - &SEQ_COUNT_PROVIDER, - &mut sender, - ) { + let sender = TmSender::new(TmPacket::new(), tgt); + let accepted_token = match verif_reporter.send_acceptance_success(sendable, &sender) { Ok(token) => token, Err(e) => { warn!(target: "serial_rx_handler", "Sending acceptance success failed: {:?}", e.0); @@ -485,15 +498,17 @@ mod app { if tc.service() == 17 { if tc.subservice() == 1 { 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(); - let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); - let mut sender = TmSender::new(mem_block, tgt); - let started_token = match verif_reporter.send_start_success( - sendable, - &SEQ_COUNT_PROVIDER, - &mut sender, - ) { + // let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); + let sender = TmSender::new(TmPacket::new(), tgt); + let started_token = match verif_reporter.send_start_success(sendable, &sender) { Ok(token) => token, Err(e) => { warn!(target: tgt, "Sending acceptance success failed: {:?}", e.0); @@ -507,24 +522,28 @@ mod app { let mut sp_header = SpHeader::tc_unseg(PUS_APID, SEQ_COUNT_PROVIDER.get(), 0).unwrap(); let sec_header = PusTmSecondaryHeader::new_simple(17, 2, stamp_buf); - let ping_reply = PusTm::new(&mut sp_header, sec_header, None, true); - let mut mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); - let reply_len = ping_reply.write_to_bytes(mem_block.as_mut_slice()).unwrap(); - if TX_REQUESTS.enqueue((mem_block, reply_len)).is_err() { + let ping_reply = PusTmCreator::new(&mut sp_header, sec_header, &[], true); + let mut tm_packet = TmPacket::new(); + tm_packet + .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"); return; } SEQ_COUNT_PROVIDER.increment(); 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(); - let mem_block = poolmod::TM::alloc().unwrap().init([0u8; MAX_TM_LEN]); - let mut sender = TmSender::new(mem_block, tgt); - if let Err(e) = verif_reporter.send_step_or_completion_success( - sendable, - &SEQ_COUNT_PROVIDER, - &mut sender, - ) { + let sender = TmSender::new(TmPacket::new(), tgt); + if let Err(e) = verif_reporter.send_step_or_completion_success(sendable, &sender) { warn!(target: tgt, "Sending completion success failed: {:?}", e.0); } } else { @@ -535,23 +554,23 @@ mod app { #[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(); if rx_ref.is_complete() { let uart_rx_owned = rx_transfer.take().unwrap(); let (buf, c, rx) = uart_rx_owned.stop(); // 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. - let mut mem_block = poolmod::TC::alloc() - .expect("allocating memory block for rx failed") - .init([0u8; TC_BUF_LEN]); - // Copy data into memory pool. - mem_block.copy_from_slice(buf); + tc_packet.resize(buf.len(), 0).expect("vec resize failed"); + tc_packet.copy_from_slice(buf); + + // Start the next transfer as soon as possible. *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) - .expect("spawning rx handler task failed"); + + // Send the vector to a regular task. + 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 // exceeded. Circular mode is not used here, so data might be missed. 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) { - cx.shared.tx_transfer.lock(|tx_state| match tx_state { - UartTxState::Idle(_) => (), - UartTxState::Transmitting(transfer) => { - let transfer_ref = transfer.as_ref().unwrap(); - if transfer_ref.is_complete() { - let transfer = transfer.take().unwrap(); - let (_, dma_channel, tx) = transfer.stop(); - *tx_state = UartTxState::Idle(Some(TxIdle { tx, dma_channel })); - serial_tx_handler::spawn_after(MsDuration::from_ticks( - MIN_DELAY_BETWEEN_TX_PACKETS_MS.into(), - )) - .unwrap(); + cx.shared + .tx_shared + .lock(|tx_shared| match &mut tx_shared.state { + UartTxState::Idle(_) => (), + UartTxState::Transmitting(transfer) => { + let transfer_ref = transfer.as_ref().unwrap(); + if transfer_ref.is_complete() { + let transfer = transfer.take().unwrap(); + let (_, dma_channel, mut tx) = transfer.stop(); + tx.clear_event(TxEvent::TransmissionComplete); + tx_shared.state = UartTxState::Idle(Some(TxIdle { tx, dma_channel })); + // We cache the last completed time to ensure that there is a minimum delay between consecutive + // transferred packets. + tx_shared.last_completed = Some(Systick::now()); + } } - } - }); + }); + let mut tc_packet = TcPacket::new(); cx.shared.rx_transfer.lock(|rx_transfer| { let rx_transfer_ref = rx_transfer.as_ref().unwrap(); // Received a partial packet. @@ -586,17 +608,15 @@ mod app { let rx_transfer_owned = rx_transfer.take().unwrap(); 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 - // during the interrupt. There are multiple ways to do this, we use a memory pool here - // to do this. - let mut mem_block = poolmod::TC::alloc() - .expect("allocating memory block for rx failed") - .init([0u8; TC_BUF_LEN]); - // Copy data into memory pool. - mem_block[0..rx_len as usize].copy_from_slice(&buf[0..rx_len as usize]); + // during the interrupt. There are multiple ways to do this, we use a stack + // allocated vector to do this. + tc_packet + .resize(rx_len as usize, 0) + .expect("vec resize failed"); + tc_packet[0..rx_len as usize].copy_from_slice(&buf[0..rx_len as usize]); rx.clear_event(RxEvent::Idle); - // Only send owning pointer to pool memory and the received packet length. - serial_rx_handler::spawn(mem_block, rx_len as usize) - .expect("spawning rx handler task failed"); + info!("spawning rx task"); + serial_rx_handler::spawn(tc_packet).expect("spawning rx handler failed"); *rx_transfer = Some(rx.read_exact(buf, ch)); } }); diff --git a/satrs-example-stm32f3-disco/.vscode/.gitignore b/satrs-example-stm32f3-disco/vscode/.gitignore similarity index 100% rename from satrs-example-stm32f3-disco/.vscode/.gitignore rename to satrs-example-stm32f3-disco/vscode/.gitignore diff --git a/satrs-example-stm32f3-disco/.vscode/extensions.json b/satrs-example-stm32f3-disco/vscode/extensions.json similarity index 99% rename from satrs-example-stm32f3-disco/.vscode/extensions.json rename to satrs-example-stm32f3-disco/vscode/extensions.json index dd3369c..57b3fbb 100644 --- a/satrs-example-stm32f3-disco/.vscode/extensions.json +++ b/satrs-example-stm32f3-disco/vscode/extensions.json @@ -9,4 +9,4 @@ ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] -} \ No newline at end of file +} diff --git a/satrs-example-stm32f3-disco/.vscode/launch.json b/satrs-example-stm32f3-disco/vscode/launch.json similarity index 100% rename from satrs-example-stm32f3-disco/.vscode/launch.json rename to satrs-example-stm32f3-disco/vscode/launch.json diff --git a/satrs-example-stm32f3-disco/.vscode/openocd-helpers.tcl b/satrs-example-stm32f3-disco/vscode/openocd-helpers.tcl similarity index 81% rename from satrs-example-stm32f3-disco/.vscode/openocd-helpers.tcl rename to satrs-example-stm32f3-disco/vscode/openocd-helpers.tcl index 4da6f7e..a1116b6 100644 --- a/satrs-example-stm32f3-disco/.vscode/openocd-helpers.tcl +++ b/satrs-example-stm32f3-disco/vscode/openocd-helpers.tcl @@ -11,7 +11,8 @@ proc CDSWOConfigure { CDCPUFreqHz CDSWOFreqHz CDSWOOutput } { # Alternative option: Pipe ITM output into itm.txt file # 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 itm port 0 on } diff --git a/satrs-example-stm32f3-disco/.vscode/tasks.json b/satrs-example-stm32f3-disco/vscode/tasks.json similarity index 100% rename from satrs-example-stm32f3-disco/.vscode/tasks.json rename to satrs-example-stm32f3-disco/vscode/tasks.json