continue CCSDS scheduler

This commit is contained in:
2025-11-17 11:34:27 +01:00
parent f8628a5279
commit f4aff4780a
4 changed files with 46 additions and 67 deletions

View File

@@ -14,12 +14,12 @@ test:
embedded: embedded:
cargo check -p satrs --target=thumbv7em-none-eabihf --no-default-features cargo check -p satrs --target=thumbv7em-none-eabihf --no-default-features
fmt:
cargo fmt --all
check-fmt: check-fmt:
cargo fmt --all -- --check cargo fmt --all -- --check
fmt:
cargo fmt --all
clippy: clippy:
cargo clippy -- -D warnings cargo clippy -- -D warnings

View File

@@ -3,7 +3,7 @@ use core::{hash::Hash, time::Duration};
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub use alloc_mod::*; pub use alloc_mod::*;
use spacepackets::{ use spacepackets::{
ByteConversionError, PacketId, PacketSequenceControl, ByteConversionError, CcsdsPacketIdAndPsc,
time::{TimestampError, UnixTime}, time::{TimestampError, UnixTime},
}; };
@@ -24,6 +24,8 @@ pub enum ScheduleError {
NestedScheduledTc, NestedScheduledTc,
#[error("tc data empty")] #[error("tc data empty")]
TcDataEmpty, TcDataEmpty,
#[error("scheduler is full")]
Full,
#[error("timestamp error: {0}")] #[error("timestamp error: {0}")]
TimestampError(#[from] TimestampError), TimestampError(#[from] TimestampError),
#[error("wrong subservice number {0}")] #[error("wrong subservice number {0}")]
@@ -36,33 +38,32 @@ pub enum ScheduleError {
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CcsdsPacketId { pub struct CcsdsSchedulePacketId {
pub packet_id: PacketId, pub base: CcsdsPacketIdAndPsc,
pub psc: PacketSequenceControl, pub crc16: Option<u16>,
pub crc16: u16,
} }
impl Hash for CcsdsPacketId { impl Hash for CcsdsSchedulePacketId {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.packet_id.hash(state); self.base.hash(state);
self.psc.raw().hash(state);
self.crc16.hash(state); self.crc16.hash(state);
} }
} }
#[cfg(feature = "alloc")]
pub mod alloc_mod { pub mod alloc_mod {
use core::time::Duration; use core::time::Duration;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::time::SystemTimeError; use std::time::SystemTimeError;
use spacepackets::time::UnixTime; use spacepackets::{CcsdsPacketIdAndPsc, CcsdsPacketReader, time::UnixTime};
use crate::ccsds::scheduler::CcsdsPacketId; use crate::ccsds::scheduler::CcsdsSchedulePacketId;
pub struct CcsdsScheduler { pub struct CcsdsScheduler {
tc_map: alloc::collections::BTreeMap< tc_map: alloc::collections::BTreeMap<
UnixTime, UnixTime,
alloc::vec::Vec<(CcsdsPacketId, alloc::vec::Vec<u8>)>, alloc::vec::Vec<(CcsdsSchedulePacketId, alloc::vec::Vec<u8>)>,
>, >,
packet_limit: usize, packet_limit: usize,
pub(crate) current_time: UnixTime, pub(crate) current_time: UnixTime,
@@ -117,13 +118,30 @@ pub mod alloc_mod {
&self.current_time &self.current_time
} }
pub fn insert_telecommand_with_reader(
&mut self,
reader: &CcsdsPacketReader,
release_time: UnixTime,
) -> Result<(), super::ScheduleError> {
if self.num_of_entries() + 1 >= self.packet_limit {
return Err(super::ScheduleError::Full);
}
let base_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(reader);
Ok(())
}
// TODO: Implementation // TODO: Implementation
pub fn insert_telecommand( pub fn insert_telecommand(
&mut self, &mut self,
packet_id: CcsdsPacketId, packet_id: CcsdsSchedulePacketId,
packet: alloc::vec::Vec<u8>, raw_packet: &[u8],
release_time: UnixTime, release_time: UnixTime,
) { ) -> Result<(), super::ScheduleError> {
if self.num_of_entries() + 1 >= self.packet_limit {
return Err(super::ScheduleError::Full);
}
Ok(())
} }
} }
} }

View File

@@ -23,6 +23,7 @@ extern crate downcast_rs;
extern crate std; extern crate std;
pub mod action; pub mod action;
pub mod ccsds;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub mod dev_mgmt; pub mod dev_mgmt;
pub mod encoding; pub mod encoding;
@@ -51,7 +52,6 @@ pub mod scheduling;
pub mod subsystem; pub mod subsystem;
pub mod time; pub mod time;
pub mod tmtc; pub mod tmtc;
pub mod ccsds;
pub use spacepackets; pub use spacepackets;

View File

@@ -155,73 +155,34 @@ impl Display for StoreIdError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl Error for StoreIdError {} impl Error for StoreIdError {}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PoolError { pub enum PoolError {
/// Requested data block is too large /// Requested data block is too large
#[error("data to store with size {0} is too large")]
DataTooLarge(usize), DataTooLarge(usize),
/// The store is full. Contains the index of the full subpool /// The store is full. Contains the index of the full subpool
#[error("store does not have any capacity")]
StoreFull(u16), StoreFull(u16),
/// The store can not hold any data. /// The store can not hold any data.
#[error("store does not have any capacity")]
NoCapacity, NoCapacity,
/// Store ID is invalid. This also includes partial errors where only the subpool is invalid /// Store ID is invalid. This also includes partial errors where only the subpool is invalid
#[error("invalid store ID: {0}, address: {1:?}")]
InvalidStoreId(StoreIdError, Option<PoolAddr>), InvalidStoreId(StoreIdError, Option<PoolAddr>),
/// Valid subpool and packet index, but no data is stored at the given address /// Valid subpool and packet index, but no data is stored at the given address
#[error("no data exists at address {0:?}")]
DataDoesNotExist(PoolAddr), DataDoesNotExist(PoolAddr),
ByteConversionError(spacepackets::ByteConversionError), #[error("byte conversion error: {0}")]
ByteConversion(#[from] spacepackets::ByteConversionError),
#[error("lock error")]
LockError, LockError,
/// Internal or configuration errors /// Internal or configuration errors
#[error("lock error")]
InternalError(u32), InternalError(u32),
} }
impl Display for PoolError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
PoolError::DataTooLarge(size) => {
write!(f, "data to store with size {size} is too large")
}
PoolError::NoCapacity => {
write!(f, "store does not have any capacity")
}
PoolError::StoreFull(u16) => {
write!(f, "store is too full. index for full subpool: {u16}")
}
PoolError::InvalidStoreId(id_e, addr) => {
write!(f, "invalid store ID: {id_e}, address: {addr:?}")
}
PoolError::DataDoesNotExist(addr) => {
write!(f, "no data exists at address {addr:?}")
}
PoolError::InternalError(e) => {
write!(f, "internal error: {e}")
}
PoolError::ByteConversionError(e) => {
write!(f, "store error: {e}")
}
PoolError::LockError => {
write!(f, "lock error")
}
}
}
}
impl From<ByteConversionError> for PoolError {
fn from(value: ByteConversionError) -> Self {
Self::ByteConversionError(value)
}
}
#[cfg(feature = "std")]
impl Error for PoolError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let PoolError::InvalidStoreId(e, _) = self {
return Some(e);
}
None
}
}
/// Generic trait for pool providers which provide memory pools for variable sized packet data. /// Generic trait for pool providers which provide memory pools for variable sized packet data.
/// ///
/// It specifies a basic API to [Self::add], [Self::modify], [Self::read] and [Self::delete] data /// It specifies a basic API to [Self::add], [Self::modify], [Self::read] and [Self::delete] data