first TC handling

This commit is contained in:
Robin Mueller
2026-05-13 10:23:44 +02:00
parent 2cab8d7fed
commit bcc1cc850f
8 changed files with 418 additions and 67 deletions
@@ -7,7 +7,7 @@ use std::{
use clap::Parser;
use cobs::CobsDecoderOwned;
use embedded_models::Request;
use embedded_models::stm32f3;
use spacepackets::{CcsdsPacketCreatorOwned, CcsdsPacketReader, SpHeader};
use tmtc_utils::transport::serial::PacketTransportSerialCobs;
@@ -69,8 +69,7 @@ fn main() {
let mut transport = PacketTransportSerialCobs::new(serial, CobsDecoderOwned::new(1024));
if cli.ping {
let request = Request::Ping;
let tc = create_stm32f3_tc(&request);
let tc = create_stm32f3_tc(&embedded_models::stm32f3::Request::Ping);
log::info!(
"Sending ping request with TC ID: {:#010x}",
tc.ccsds_packet_id_and_psc().raw()
@@ -79,7 +78,7 @@ fn main() {
}
if let Some(freq_ms) = cli.set_led_frequency {
let request = Request::ChangeBlinkFrequency(Duration::from_millis(freq_ms as u64));
let request = stm32f3::Request::ChangeBlinkFrequency(Duration::from_millis(freq_ms as u64));
let tc = create_stm32f3_tc(&request);
log::info!(
"Sending change blink frequency request {:?} with TC ID: {:#010x}",
@@ -100,7 +99,7 @@ fn main() {
}
}
fn create_stm32f3_tc(request: &Request) -> CcsdsPacketCreatorOwned {
fn create_stm32f3_tc(request: &stm32f3::Request) -> CcsdsPacketCreatorOwned {
let req_raw = postcard::to_allocvec(&request).unwrap();
let sp_header = SpHeader::new_from_apid(satrs_stm32f3_disco_rtic::APID);
CcsdsPacketCreatorOwned::new_tc_with_checksum(sp_header, &req_raw).unwrap()
+1
View File
@@ -8,3 +8,4 @@ serde = { version = "1", default-features = false }
defmt = { version = "1", optional = true }
spacepackets = { version = "0.17", default-features = false, features = ["defmt", "serde"] }
postcard = { version = "1", features = ["defmt"] }
arbitrary-int = "2"
+42 -14
View File
@@ -1,33 +1,60 @@
#![no_std]
use core::time::Duration;
use spacepackets::{
CcsdsPacketCreationError, CcsdsPacketCreatorWithReservedData, CcsdsPacketIdAndPsc,
SpacePacketHeader, ccsds_packet_len_for_user_data_len_with_checksum,
};
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Request {
Ping,
ChangeBlinkFrequency(Duration),
pub mod stm32f3 {
use arbitrary_int::u11;
use core::time::Duration;
pub const PUS_APID: u11 = u11::new(0x02);
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Request {
Ping,
ChangeBlinkFrequency(Duration),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Response {
Ok,
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Response {
CommandDone,
/// This might look like a duplication, but we intentionally keep those separate so they can
/// change independently.
pub mod stm32h7 {
use arbitrary_int::u11;
use core::time::Duration;
pub const PUS_APID: u11 = u11::new(0x03);
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Request {
Ping,
ChangeBlinkFrequency(Duration),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Response {
Ok,
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct TmHeader {
pub tc_packet_id: Option<CcsdsPacketIdAndPsc>,
pub uptime_millis: u32,
pub uptime_millis: u64,
}
pub fn tm_size(tm_header: &TmHeader, response: &Response) -> usize {
pub fn tm_size<Response: serde::Serialize>(tm_header: &TmHeader, response: &Response) -> usize {
ccsds_packet_len_for_user_data_len_with_checksum(
postcard::experimental::serialized_size(tm_header).unwrap()
+ postcard::experimental::serialized_size(response).unwrap(),
@@ -35,7 +62,7 @@ pub fn tm_size(tm_header: &TmHeader, response: &Response) -> usize {
.unwrap()
}
pub fn create_tm_packet(
pub fn create_tm_packet<Response: serde::Serialize>(
buf: &mut [u8],
sp_header: SpacePacketHeader,
tm_header: TmHeader,
@@ -52,5 +79,6 @@ pub fn create_tm_packet(
postcard::to_slice(&response, &mut creator.packet_data_mut()[current_index..]).unwrap();
Ok(creator.finish())
}
#[cfg(test)]
mod tests {}
+1
View File
@@ -596,6 +596,7 @@ dependencies = [
name = "embedded-models"
version = "0.1.0"
dependencies = [
"arbitrary-int 2.0.0",
"defmt 1.0.1",
"postcard",
"serde",
@@ -1,8 +1,8 @@
#![no_std]
#![no_main]
use arbitrary_int::{u11, u14};
use arbitrary_int::u14;
use cortex_m_semihosting::debug::{self, EXIT_FAILURE, EXIT_SUCCESS};
use embedded_models::{create_tm_packet, tm_size, Response, TmHeader};
use embedded_models::{create_tm_packet, stm32f3, tm_size, TmHeader};
use spacepackets::{CcsdsPacketCreationError, CcsdsPacketIdAndPsc, SpHeader};
use defmt_rtt as _; // global logger
@@ -23,8 +23,6 @@ const TX_HANDLER_FREQ_MS: u32 = 20;
const MAX_TC_LEN: usize = 128;
const MAX_TM_LEN: usize = 128;
pub const PUS_APID: u11 = u11::new(0x02);
// This is the predictable maximum overhead of the COBS encoding scheme.
// It is simply the maximum packet lenght dividied by 254 rounded up.
const COBS_TM_OVERHEAD: usize = cobs::max_encoding_overhead(MAX_TM_LEN);
@@ -47,7 +45,7 @@ pub enum TmSendError {
#[derive(Debug, defmt::Format)]
pub struct RequestWithTcId {
pub request: embedded_models::Request,
pub request: stm32f3::Request,
pub tc_id: CcsdsPacketIdAndPsc,
}
@@ -57,7 +55,7 @@ mod app {
use super::*;
use arbitrary_int::u14;
use embedded_models::{Request, Response};
use embedded_models::stm32f3::{Request, Response};
use rtic::Mutex;
use rtic_sync::{
channel::{Receiver, Sender},
@@ -264,7 +262,7 @@ mod app {
tc_packet_id: CcsdsPacketIdAndPsc,
) -> Result<(), TmSendError> {
defmt::info!("Received PUS ping telecommand, sending ping reply");
send_tm(tc_packet_id, Response::CommandDone, *cx.local.seq_count)?;
send_tm(tc_packet_id, Response::Ok, *cx.local.seq_count)?;
*cx.local.seq_count = cx.local.seq_count.wrapping_add(u14::new(1));
Ok(())
}
@@ -281,7 +279,7 @@ mod app {
cx.shared
.blink_freq
.lock(|blink_freq| *blink_freq = duration);
send_tm(tc_packet_id, Response::CommandDone, *cx.local.seq_count)?;
send_tm(tc_packet_id, Response::Ok, *cx.local.seq_count)?;
*cx.local.seq_count = cx.local.seq_count.wrapping_add(u14::new(1));
Ok(())
}
@@ -289,13 +287,13 @@ mod app {
fn send_tm(
tc_packet_id: CcsdsPacketIdAndPsc,
response: Response,
response: stm32f3::Response,
current_seq_count: u14,
) -> Result<(), TmSendError> {
let sp_header = SpHeader::new_for_unseg_tc(PUS_APID, current_seq_count, 0);
let sp_header = SpHeader::new_for_unseg_tc(stm32f3::PUS_APID, current_seq_count, 0);
let tm_header = TmHeader {
tc_packet_id: Some(tc_packet_id),
uptime_millis: Mono::now().duration_since_epoch().to_millis(),
uptime_millis: Mono::now().duration_since_epoch().to_millis() as u64,
};
let mut tm_packet = TmPacket::new();
let tm_size = tm_size(&tm_header, &response);
+276 -8
View File
@@ -20,6 +20,22 @@ dependencies = [
"as-slice",
]
[[package]]
name = "arbitrary-int"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3cae0a5"
[[package]]
name = "arbitrary-int"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993a810118f8f37e9c4411c86f1c4c940a09a7ab34b7bf2d88d06f50c553fab7"
dependencies = [
"defmt 1.1.0",
"serde",
]
[[package]]
name = "as-slice"
version = "0.2.1"
@@ -29,6 +45,15 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -41,7 +66,7 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [
"rustc_version",
"rustc_version 0.2.3",
]
[[package]]
@@ -62,6 +87,18 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
[[package]]
name = "bitbybit"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec187a89ab07e209270175faf9e07ceb2755d984954e58a2296e325ddece2762"
dependencies = [
"arbitrary-int 1.3.0",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "bitfield"
version = "0.13.2"
@@ -101,6 +138,25 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [
"num-traits",
"serde",
]
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror",
]
[[package]]
name = "const-default"
version = "1.0.0"
@@ -140,6 +196,21 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "crc"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853"
[[package]]
name = "critical-section"
version = "1.2.0"
@@ -219,6 +290,17 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "delegate"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "document-features"
version = "0.2.12"
@@ -288,7 +370,7 @@ dependencies = [
"embassy-time",
"embedded-io-async",
"embedded-nal-async",
"heapless",
"heapless 0.9.3",
"managed",
"smoltcp",
]
@@ -337,7 +419,7 @@ dependencies = [
"embedded-storage",
"embedded-storage-async",
"futures-util",
"heapless",
"heapless 0.9.3",
"nb 1.1.0",
"proc-macro2",
"quote",
@@ -366,7 +448,7 @@ dependencies = [
"embedded-io-async",
"futures-core",
"futures-sink",
"heapless",
"heapless 0.9.3",
]
[[package]]
@@ -400,7 +482,7 @@ version = "0.3.2"
source = "git+https://github.com/embassy-rs/embassy.git?rev=dd8e4c14e53f088bae27c5d841ab7a4fa338a52c#dd8e4c14e53f088bae27c5d841ab7a4fa338a52c"
dependencies = [
"embassy-executor-timer-queue",
"heapless",
"heapless 0.9.3",
]
[[package]]
@@ -500,6 +582,17 @@ dependencies = [
"embedded-io",
]
[[package]]
name = "embedded-models"
version = "0.1.0"
dependencies = [
"arbitrary-int 2.1.1",
"defmt 1.1.0",
"postcard",
"serde",
"spacepackets",
]
[[package]]
name = "embedded-nal"
version = "0.9.0"
@@ -584,6 +677,15 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hash32"
version = "0.3.1"
@@ -599,6 +701,20 @@ version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32 0.2.1",
"rustc_version 0.4.1",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "heapless"
version = "0.9.3"
@@ -606,7 +722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4"
dependencies = [
"defmt 1.1.0",
"hash32",
"hash32 0.3.1",
"stable_deref_trait",
]
@@ -644,6 +760,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "managed"
version = "0.8.0"
@@ -681,6 +806,27 @@ dependencies = [
"libm",
]
[[package]]
name = "num_enum"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "panic-probe"
version = "1.0.0"
@@ -691,6 +837,12 @@ dependencies = [
"defmt 1.1.0",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.17"
@@ -703,6 +855,18 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
[[package]]
name = "postcard"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [
"cobs",
"defmt 1.1.0",
"heapless 0.7.17",
"serde",
]
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
@@ -842,7 +1006,16 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
"semver 0.9.0",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver 1.0.28",
]
[[package]]
@@ -855,6 +1028,7 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
name = "satrs-stm32h7-nucleo-rtic"
version = "0.1.0"
dependencies = [
"arbitrary-int 2.1.1",
"cortex-m",
"cortex-m-rt",
"defmt 1.1.0",
@@ -865,11 +1039,20 @@ dependencies = [
"embassy-sync",
"embassy-time",
"embedded-alloc",
"embedded-models",
"panic-probe",
"postcard",
"rtic",
"spacepackets",
"static_cell",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sdio-host"
version = "0.9.0"
@@ -891,12 +1074,48 @@ dependencies = [
"semver-parser",
]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "smoltcp"
version = "0.13.1"
@@ -907,10 +1126,39 @@ dependencies = [
"byteorder",
"cfg-if",
"defmt 0.3.100",
"heapless",
"heapless 0.9.3",
"managed",
]
[[package]]
name = "spacepackets"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94979a990b4333f43667cba9fe9e72b9c4e9ada82e09fbe8fb250844358590cc"
dependencies = [
"arbitrary-int 2.1.1",
"bitbybit",
"chrono",
"crc",
"defmt 1.1.0",
"delegate",
"num-traits",
"num_enum",
"paste",
"serde",
"thiserror",
"zerocopy",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -1069,3 +1317,23 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
dependencies = [
"vcell",
]
[[package]]
name = "zerocopy"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
@@ -14,41 +14,25 @@ name = "integration"
harness = false
[dependencies]
embedded-models = { path = "../models", features = ["defmt"] }
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
arbitrary-int = "2"
cortex-m-rt = "0.7"
defmt = "1"
defmt-rtt = "1"
# defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "1", features = ["print-defmt"] }
# cortex-m-semihosting = "0.5.0"
# TODO: Replace with embassy-hal.
# stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] }
embedded-alloc = "0.7"
static_cell = "2"
rtic = { version = "2", features = ["thumbv7-backend"] }
spacepackets = { version = "0.17", default-features = false, features = ["defmt"] }
postcard = "1"
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", rev = "dd8e4c14e53f088bae27c5d841ab7a4fa338a52c", version = "0.6", features = ["stm32h743zi", "memory-x", "defmt", "time-driver-any"]}
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "dd8e4c14e53f088bae27c5d841ab7a4fa338a52c", version = "0.5", features = ["defmt-timestamp-uptime-ms", "generic-queue-16"] }
embassy-net = { git = "https://github.com/embassy-rs/embassy.git", rev = "dd8e4c14e53f088bae27c5d841ab7a4fa338a52c", version = "0.9", features = ["medium-ethernet", "proto-ipv4", "tcp", "udp", "auto-icmp-echo-reply", "dhcpv4", "defmt"] }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", rev = "dd8e4c14e53f088bae27c5d841ab7a4fa338a52c" }
embedded-alloc = "0.7"
static_cell = "2"
# rtic-sync = { version = "1", features = ["defmt-03"] }
rtic = { version = "2", features = ["thumbv7-backend"] }
# [dependencies.smoltcp]
# version = "0.13"
# default-features = false
# features = ["medium-ethernet", "proto-ipv4", "socket-raw", "socket-dhcpv4", "socket-udp", "defmt"]
# [dependencies.rtic]
# version = "2"
# features = ["thumbv7-backend"]
# [dependencies.rtic-monotonics]
# version = "2"
# features = ["cortex-m-systick"]
# [dependencies.satrs]
# path = "../../satrs"
# default-features = false
# features = ["defmt", "heapless"]
[dev-dependencies]
defmt-test = "0.5"
@@ -28,6 +28,7 @@ const TM_QUEUE_DEPTH: usize = 32;
mod app {
use super::*;
use arbitrary_int::u14;
use embassy_net::udp::UdpSocket;
use embassy_net::StackResources;
use embassy_stm32::eth;
@@ -38,6 +39,14 @@ mod app {
use embassy_time::Duration;
use embassy_time::Timer;
use embassy_time::WithTimeout as _;
use embedded_models::create_tm_packet;
use embedded_models::stm32h7;
use embedded_models::tm_size;
use embedded_models::TmHeader;
use spacepackets::CcsdsPacketCreationError;
use spacepackets::CcsdsPacketIdAndPsc;
use spacepackets::CcsdsPacketReader;
use spacepackets::SpHeader;
use static_cell::StaticCell;
bind_interrupts!(struct Irqs {
@@ -90,6 +99,7 @@ mod app {
#[shared]
struct Shared {
sequence_count: u14,
blink_freq: embassy_time::Duration,
}
@@ -191,6 +201,7 @@ mod app {
(
Shared {
blink_freq: Duration::from_millis(DEFAULT_BLINK_FREQ_MS as u64),
sequence_count: u14::new(0),
},
Local {
link_led,
@@ -290,7 +301,9 @@ mod app {
if let Some(endpoint) = remote_endpoint {
while let Ok(packet) = cx.local.tm_rx.try_receive() {
match udp.send_to(&packet, endpoint).await {
Ok(_) => defmt::debug!("UDP TX: {} bytes to: {}", packet.len(), endpoint),
Ok(_) => {
defmt::debug!("UDP TX: {} bytes to: {}", packet.len(), endpoint)
}
Err(e) => defmt::warn!("udp send error: {}", e),
}
}
@@ -299,11 +312,70 @@ mod app {
}
}
#[task(local = [tc_rx])]
async fn tc_handler(cx: tc_handler::Context) {
#[task(local = [tc_rx, tm_tx], shared=[sequence_count, blink_freq])]
async fn tc_handler(mut cx: tc_handler::Context) {
loop {
let tc = cx.local.tc_rx.receive().await;
match CcsdsPacketReader::new_with_checksum(&tc) {
Ok(packet) => {
let packet_id = packet.packet_id();
let psc = packet.psc();
let tc_packet_id = CcsdsPacketIdAndPsc { packet_id, psc };
if let Ok(request) =
postcard::from_bytes::<stm32h7::Request>(packet.packet_data())
{
let response = match request {
stm32h7::Request::Ping => {
stm32h7::Response::Ok
}
stm32h7::Request::ChangeBlinkFrequency(duration) => {
cx.shared.blink_freq.lock(|current| {
*current = Duration::from_millis(duration.as_millis() as u64)
});
stm32h7::Response::Ok
}
};
let sequence_count = cx.shared.sequence_count.lock(|v| {
let current = *v;
*v = v.wrapping_add(u14::new(1));
current
});
// Send Pong/OK response immediately.
if let Err(e) =
send_tm(tc_packet_id, response, sequence_count, cx.local.tm_tx).await
{
defmt::warn!("Failed to send TM response: {}", e);
}
}
}
Err(e) => defmt::warn!("Failed to parse received TC packet: {}", e,),
}
defmt::info!("Received from UDP client: {}", tc.as_slice());
}
}
async fn send_tm(
tc_packet_id: CcsdsPacketIdAndPsc,
response: stm32h7::Response,
current_seq_count: u14,
sender: &embassy_sync::channel::Sender<
'static,
NoopRawMutex,
alloc::vec::Vec<u8>,
TM_QUEUE_DEPTH,
>,
) -> Result<(), CcsdsPacketCreationError> {
let sp_header = SpHeader::new_for_unseg_tc(stm32h7::PUS_APID, current_seq_count, 0);
let tm_header = TmHeader {
tc_packet_id: Some(tc_packet_id),
uptime_millis: embassy_time::Instant::now().as_millis(),
};
let tm_size = tm_size(&tm_header, &response);
let mut packet = alloc::vec![0; tm_size];
create_tm_packet(&mut packet, sp_header, tm_header, response)?;
sender.send(packet).await;
Ok(())
}
}