optimize PUS stack code
Some checks are pending
Rust/sat-rs/pipeline/head Build started...

This commit is contained in:
Robin Müller 2024-05-02 11:58:46 +02:00
parent c586fd7fef
commit a00c843698
Signed by: muellerr
GPG Key ID: A649FB78196E3849
5 changed files with 87 additions and 107 deletions

View File

@ -68,12 +68,8 @@ impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusSe
const SERVICE_ID: u8 = PusServiceId::Event as u8; const SERVICE_ID: u8 = PusServiceId::Event as u8;
const SERVICE_STR: &'static str = "events"; const SERVICE_STR: &'static str = "events";
}
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> HandlingStatus {
EventServiceWrapper<TmSender, TcInMemConverter>
{
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> HandlingStatus {
let error_handler = |partial_error: &PartialPusHandlingError| { let error_handler = |partial_error: &PartialPusHandlingError| {
log::warn!( log::warn!(
"PUS {}({}) partial error: {:?}", "PUS {}({}) partial error: {:?}",

View File

@ -234,6 +234,15 @@ pub trait TargetedPusService {
fn check_for_request_timeouts(&mut self); fn check_for_request_timeouts(&mut self);
} }
/// Generic trait for services which handle packets directly. Kept minimal right now because
/// of the difficulty to allow flexible user code for these services..
pub trait DirectPusService {
const SERVICE_ID: u8;
const SERVICE_STR: &'static str;
fn poll_and_handle_next_tc(&mut self, timestamp: &[u8]) -> HandlingStatus;
}
/// This is a generic handler class for all PUS services where a PUS telecommand is converted /// This is a generic handler class for all PUS services where a PUS telecommand is converted
/// to a targeted request. /// to a targeted request.
/// ///
@ -524,11 +533,6 @@ pub fn generic_pus_request_timeout_handler(
Ok(()) Ok(())
} }
pub trait DirectPusService {
const SERVICE_ID: u8;
const SERVICE_STR: &'static str;
}
#[cfg(test)] #[cfg(test)]
pub(crate) mod tests { pub(crate) mod tests {
use std::time::Duration; use std::time::Duration;

View File

@ -84,36 +84,8 @@ impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusSe
const SERVICE_ID: u8 = PusServiceId::Verification as u8; const SERVICE_ID: u8 = PusServiceId::Verification as u8;
const SERVICE_STR: &'static str = "verification"; const SERVICE_STR: &'static str = "verification";
}
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> HandlingStatus {
SchedulingServiceWrapper<TmSender, TcInMemConverter>
{
pub fn release_tcs(&mut self) {
let id = self.pus_11_handler.service_helper.id();
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
self.tc_releaser.release(id, enabled, info, tc)
};
self.pus_11_handler
.scheduler_mut()
.update_time_from_now()
.unwrap();
let released_tcs = self
.pus_11_handler
.scheduler_mut()
.release_telecommands_with_buffer(
releaser,
&mut self.sched_tc_pool,
&mut self.releaser_buf,
)
.expect("releasing TCs failed");
if released_tcs > 0 {
info!("{released_tcs} TC(s) released from scheduler");
}
}
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> HandlingStatus {
let error_handler = |partial_error: &PartialPusHandlingError| { let error_handler = |partial_error: &PartialPusHandlingError| {
log::warn!( log::warn!(
"PUS {}({}) partial error: {:?}", "PUS {}({}) partial error: {:?}",
@ -160,6 +132,34 @@ impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
} }
} }
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
SchedulingServiceWrapper<TmSender, TcInMemConverter>
{
pub fn release_tcs(&mut self) {
let id = self.pus_11_handler.service_helper.id();
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
self.tc_releaser.release(id, enabled, info, tc)
};
self.pus_11_handler
.scheduler_mut()
.update_time_from_now()
.unwrap();
let released_tcs = self
.pus_11_handler
.scheduler_mut()
.release_telecommands_with_buffer(
releaser,
&mut self.sched_tc_pool,
&mut self.releaser_buf,
)
.expect("releasing TCs failed");
if released_tcs > 0 {
info!("{released_tcs} TC(s) released from scheduler");
}
}
}
pub fn create_scheduler_service_static( pub fn create_scheduler_service_static(
tm_sender: PacketSenderWithSharedPool, tm_sender: PacketSenderWithSharedPool,
tc_releaser: PacketSenderWithSharedPool, tc_releaser: PacketSenderWithSharedPool,

View File

@ -2,19 +2,17 @@ use crate::pus::mode::ModeServiceWrapper;
use derive_new::new; use derive_new::new;
use satrs::{ use satrs::{
pus::{EcssTcInMemConverter, EcssTmSender}, pus::{EcssTcInMemConverter, EcssTmSender},
spacepackets::{ spacepackets::time::{cds, TimeWriter},
ecss::PusServiceId,
time::{cds, TimeWriter},
},
}; };
use satrs_example::config::CustomPusServiceId;
use super::{ use super::{
action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper, action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper,
scheduler::SchedulingServiceWrapper, test::TestCustomServiceWrapper, HandlingStatus, scheduler::SchedulingServiceWrapper, test::TestCustomServiceWrapper, DirectPusService,
TargetedPusService, HandlingStatus, TargetedPusService,
}; };
// TODO: For better extensibility, we could create 2 vectors: One for direct PUS services and one
// for targeted services..
#[derive(new)] #[derive(new)]
pub struct PusStack<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> { pub struct PusStack<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> {
test_srv: TestCustomServiceWrapper<TmSender, TcInMemConverter>, test_srv: TestCustomServiceWrapper<TmSender, TcInMemConverter>,
@ -28,70 +26,56 @@ pub struct PusStack<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConvert
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
PusStack<TmSender, TcInMemConverter> PusStack<TmSender, TcInMemConverter>
{ {
pub fn direct_service_checker<S: DirectPusService>(
service: &mut S,
timestamp: &[u8],
nothing_to_do: &mut bool,
) {
let handling_status = service.poll_and_handle_next_tc(timestamp);
if handling_status == HandlingStatus::HandledOne {
*nothing_to_do = false;
}
}
pub fn targeted_service_checker<S: TargetedPusService>(
service: &mut S,
timestamp: &[u8],
nothing_to_do: &mut bool,
) {
let request_handling = service.poll_and_handle_next_tc_default_handler(timestamp);
let reply_handling = service.poll_and_handle_next_reply_default_handler(timestamp);
if request_handling == HandlingStatus::HandledOne
|| reply_handling == HandlingStatus::HandledOne
{
*nothing_to_do = false;
}
}
pub fn periodic_operation(&mut self) { pub fn periodic_operation(&mut self) {
// Release all telecommands which reached their release time before calling the service // Release all telecommands which reached their release time before calling the service
// handlers. // handlers.
self.schedule_srv.release_tcs(); self.schedule_srv.release_tcs();
let time_stamp = cds::CdsTime::now_with_u16_days() let timestamp = cds::CdsTime::now_with_u16_days()
.expect("time stamp generation error") .expect("time stamp generation error")
.to_vec() .to_vec()
.unwrap(); .unwrap();
// Hot loop which will run continuously until all request and reply handling is done. // Hot loop which will run continuously until all request and reply handling is done.
loop { loop {
let mut nothing_to_do = true; let mut nothing_to_do = true;
let mut is_srv_finished = Self::direct_service_checker(&mut self.test_srv, &timestamp, &mut nothing_to_do);
|_srv_id: u8, Self::direct_service_checker(&mut self.schedule_srv, &timestamp, &mut nothing_to_do);
tc_handling_status: HandlingStatus, Self::direct_service_checker(&mut self.event_srv, &timestamp, &mut nothing_to_do);
reply_handling_status: Option<HandlingStatus>| { Self::targeted_service_checker(
if tc_handling_status == HandlingStatus::HandledOne &mut self.action_srv_wrapper,
|| (reply_handling_status.is_some() &timestamp,
&& reply_handling_status.unwrap() == HandlingStatus::HandledOne) &mut nothing_to_do,
{
nothing_to_do = false;
}
};
is_srv_finished(
PusServiceId::Test as u8,
self.test_srv.poll_and_handle_next_tc(&time_stamp),
None,
); );
is_srv_finished( Self::targeted_service_checker(
PusServiceId::Scheduling as u8, &mut self.hk_srv_wrapper,
self.schedule_srv.poll_and_handle_next_tc(&time_stamp), &timestamp,
None, &mut nothing_to_do,
);
is_srv_finished(
PusServiceId::Event as u8,
self.event_srv.poll_and_handle_next_tc(&time_stamp),
None,
);
is_srv_finished(
PusServiceId::Action as u8,
self.action_srv_wrapper
.poll_and_handle_next_tc_default_handler(&time_stamp),
Some(
self.action_srv_wrapper
.poll_and_handle_next_reply_default_handler(&time_stamp),
),
);
is_srv_finished(
PusServiceId::Housekeeping as u8,
self.hk_srv_wrapper
.poll_and_handle_next_tc_default_handler(&time_stamp),
Some(
self.hk_srv_wrapper
.poll_and_handle_next_reply_default_handler(&time_stamp),
),
);
is_srv_finished(
CustomPusServiceId::Mode as u8,
self.mode_srv
.poll_and_handle_next_tc_default_handler(&time_stamp),
Some(
self.mode_srv
.poll_and_handle_next_reply_default_handler(&time_stamp),
),
); );
Self::targeted_service_checker(&mut self.mode_srv, &timestamp, &mut nothing_to_do);
if nothing_to_do { if nothing_to_do {
// Timeout checking is only done once. // Timeout checking is only done once.
self.action_srv_wrapper.check_for_request_timeouts(); self.action_srv_wrapper.check_for_request_timeouts();

View File

@ -33,7 +33,7 @@ pub fn create_test_service_static(
)); ));
TestCustomServiceWrapper { TestCustomServiceWrapper {
handler: pus17_handler, handler: pus17_handler,
test_srv_event_sender: event_sender, event_tx: event_sender,
} }
} }
@ -51,7 +51,7 @@ pub fn create_test_service_dynamic(
)); ));
TestCustomServiceWrapper { TestCustomServiceWrapper {
handler: pus17_handler, handler: pus17_handler,
test_srv_event_sender: event_sender, event_tx: event_sender,
} }
} }
@ -59,7 +59,7 @@ pub struct TestCustomServiceWrapper<TmSender: EcssTmSender, TcInMemConverter: Ec
{ {
pub handler: pub handler:
PusService17TestHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>, PusService17TestHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
pub test_srv_event_sender: mpsc::SyncSender<EventMessageU32>, pub event_tx: mpsc::SyncSender<EventMessageU32>,
} }
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusService impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusService
@ -68,12 +68,8 @@ impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> DirectPusSe
const SERVICE_ID: u8 = PusServiceId::Test as u8; const SERVICE_ID: u8 = PusServiceId::Test as u8;
const SERVICE_STR: &'static str = "test"; const SERVICE_STR: &'static str = "test";
}
impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter> fn poll_and_handle_next_tc(&mut self, timestamp: &[u8]) -> HandlingStatus {
TestCustomServiceWrapper<TmSender, TcInMemConverter>
{
pub fn poll_and_handle_next_tc(&mut self, timestamp: &[u8]) -> HandlingStatus {
let error_handler = |partial_error: &PartialPusHandlingError| { let error_handler = |partial_error: &PartialPusHandlingError| {
log::warn!( log::warn!(
"PUS {}({}) partial error: {:?}", "PUS {}({}) partial error: {:?}",
@ -120,7 +116,7 @@ impl<TmSender: EcssTmSender, TcInMemConverter: EcssTcInMemConverter>
.unwrap(); .unwrap();
if subservice == 128 { if subservice == 128 {
info!("generating test event"); info!("generating test event");
self.test_srv_event_sender self.event_tx
.send(EventMessage::new(PUS_TEST_SERVICE.id(), TEST_EVENT.into())) .send(EventMessage::new(PUS_TEST_SERVICE.id(), TEST_EVENT.into()))
.expect("Sending test event failed"); .expect("Sending test event failed");
match self.handler.service_helper.verif_reporter().start_success( match self.handler.service_helper.verif_reporter().start_success(