From 2c5d774f1e4c54031d6d96a0398a60cdeec73ab1 Mon Sep 17 00:00:00 2001 From: MarwanMashaly1 <90435216+MarwanMashaly1@users.noreply.github.com> Date: Wed, 1 May 2024 13:23:18 -0400 Subject: [PATCH 1/5] Update message size test (#104) * add size check for different message types * add dbg msgs and cleanup * fix dbg msg * add consts instead of hardcoded values * update consts --- libraries/messages/src/lib.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libraries/messages/src/lib.rs b/libraries/messages/src/lib.rs index c89fb673..90fdccc1 100644 --- a/libraries/messages/src/lib.rs +++ b/libraries/messages/src/lib.rs @@ -25,6 +25,11 @@ pub mod sensor_status; pub mod state; pub const MAX_SIZE: usize = 64; +pub const MAX_HEALTH_SIZE: usize = 47; +pub const MAX_SENSOR_SIZE: usize = 53; +pub const MAX_STATE_SIZE: usize = 13; +pub const MAX_LOG_SIZE: usize = 15; +pub const MAX_COMMAND_SIZE: usize = 15; pub use logging::{ErrorContext, Event, Log, LogLevel}; @@ -70,7 +75,7 @@ impl Message { #[cfg(test)] mod test { - use crate::{Message, MAX_SIZE}; + use crate::{Message, MAX_HEALTH_SIZE, MAX_COMMAND_SIZE, MAX_LOG_SIZE, MAX_SENSOR_SIZE, MAX_STATE_SIZE}; use proptest::prelude::*; proptest! { @@ -78,8 +83,25 @@ mod test { fn message_size(msg: Message) { let bytes = postcard::to_allocvec(&msg).unwrap(); - dbg!(msg); - assert!(dbg!(bytes.len()) <= MAX_SIZE); + dbg!(&msg); + // The size of the message should be less than or equal the maximum size. + match msg.data { + crate::Data::State(_) => { + assert!(dbg!(bytes.len()) <= MAX_STATE_SIZE); + } + crate::Data::Sensor(_) => { + assert!(dbg!(bytes.len()) <= MAX_SENSOR_SIZE); + } + crate::Data::Log(_) => { + assert!(dbg!(bytes.len()) <= MAX_LOG_SIZE); + } + crate::Data::Command(_) => { + assert!(dbg!(bytes.len()) <= MAX_COMMAND_SIZE); + } + crate::Data::Health(_) => { + assert!(dbg!(bytes.len()) <= MAX_HEALTH_SIZE); + } + } } } } From beef05902cf80fa0d66eb290d4202f0bbc58eb65 Mon Sep 17 00:00:00 2001 From: Danny Harani Date: Wed, 1 May 2024 14:32:07 -0400 Subject: [PATCH 2/5] Rename sender to node (#102) * Renamed sender to node in applicable settings. * Cleanup Comments --------- Co-authored-by: Noah Sprenger --- boards/beacon/src/types.rs | 8 +++--- boards/camera/src/communication.rs | 2 +- boards/camera/src/types.rs | 6 ++-- boards/communication/src/communication.rs | 8 +++--- boards/communication/src/types.rs | 8 +++--- boards/power/src/communication.rs | 2 +- boards/power/src/types.rs | 6 ++-- boards/recovery/src/communication.rs | 4 +-- .../state_machine/states/wait_for_recovery.rs | 2 +- boards/recovery/src/types.rs | 8 +++--- boards/sensor/src/communication.rs | 6 ++-- boards/sensor/src/types.rs | 8 +++--- libraries/messages/src/command.rs | 4 +-- libraries/messages/src/lib.rs | 8 +++--- libraries/messages/src/node.rs | 27 ++++++++++++++++++ libraries/messages/src/sender.rs | 28 ------------------- 16 files changed, 67 insertions(+), 68 deletions(-) create mode 100644 libraries/messages/src/node.rs delete mode 100644 libraries/messages/src/sender.rs diff --git a/boards/beacon/src/types.rs b/boards/beacon/src/types.rs index d2fccd10..1274347f 100644 --- a/boards/beacon/src/types.rs +++ b/boards/beacon/src/types.rs @@ -1,7 +1,7 @@ -use messages::sender::Sender; -use messages::sender::Sender::BeaconBoard; +use messages::node::Node; +use messages::node::Node::BeaconBoard; // ------- -// Sender ID +// Node ID // ------- -pub static COM_ID: Sender = BeaconBoard; \ No newline at end of file +pub static COM_ID: Node = BeaconBoard; \ No newline at end of file diff --git a/boards/camera/src/communication.rs b/boards/camera/src/communication.rs index cb30c676..1a54fdae 100644 --- a/boards/camera/src/communication.rs +++ b/boards/camera/src/communication.rs @@ -103,7 +103,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::SensorBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) diff --git a/boards/camera/src/types.rs b/boards/camera/src/types.rs index 352f57f0..cea33bb0 100644 --- a/boards/camera/src/types.rs +++ b/boards/camera/src/types.rs @@ -1,5 +1,5 @@ -use messages::sender::{Sender, Sender::CameraBoard}; +use messages::node::{Node, Node::CameraBoard}; // ------- -// Sender ID +// Node ID // ------- -pub static _COM_ID: Sender = CameraBoard; +pub static _COM_ID: Node = CameraBoard; diff --git a/boards/communication/src/communication.rs b/boards/communication/src/communication.rs index 1ea183af..6af79cb4 100644 --- a/boards/communication/src/communication.rs +++ b/boards/communication/src/communication.rs @@ -120,7 +120,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::RecoveryBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) @@ -129,7 +129,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::sender::Sender::SensorBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) @@ -138,7 +138,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::PowerBoard.into()).unwrap(), + filter: ecan::StandardId::new(messages::node::Node::PowerBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Power filter")); @@ -146,7 +146,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::GroundStation.into()) + filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) diff --git a/boards/communication/src/types.rs b/boards/communication/src/types.rs index 236121d8..34315d1c 100644 --- a/boards/communication/src/types.rs +++ b/boards/communication/src/types.rs @@ -1,13 +1,13 @@ use atsamd_hal::gpio::*; use atsamd_hal::sercom::uart::EightBit; use atsamd_hal::sercom::{uart, IoSet1, Sercom5}; -use messages::sender::Sender; -use messages::sender::Sender::CommunicationBoard; +use messages::node::Node; +use messages::node::Node::CommunicationBoard; // ------- -// Sender ID +// Node ID // ------- -pub static COM_ID: Sender = CommunicationBoard; +pub static COM_ID: Node = CommunicationBoard; // ------- // Ground Station diff --git a/boards/power/src/communication.rs b/boards/power/src/communication.rs index 4d42abf2..59ca7b66 100644 --- a/boards/power/src/communication.rs +++ b/boards/power/src/communication.rs @@ -108,7 +108,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::sender::Sender::CommunicationBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::CommunicationBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) diff --git a/boards/power/src/types.rs b/boards/power/src/types.rs index 196af97b..f8bae4ef 100644 --- a/boards/power/src/types.rs +++ b/boards/power/src/types.rs @@ -1,5 +1,5 @@ -use messages::sender::{Sender, Sender::PowerBoard}; +use messages::node::{Node, Node::PowerBoard}; // ------- -// Sender ID +// Node ID // ------- -pub static _COM_ID: Sender = PowerBoard; +pub static _COM_ID: Node = PowerBoard; diff --git a/boards/recovery/src/communication.rs b/boards/recovery/src/communication.rs index 4d667b7b..c6e4d6e4 100644 --- a/boards/recovery/src/communication.rs +++ b/boards/recovery/src/communication.rs @@ -111,7 +111,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::SensorBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) @@ -121,7 +121,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::sender::Sender::CommunicationBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::CommunicationBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) diff --git a/boards/recovery/src/state_machine/states/wait_for_recovery.rs b/boards/recovery/src/state_machine/states/wait_for_recovery.rs index cd404c88..52d4a3aa 100644 --- a/boards/recovery/src/state_machine/states/wait_for_recovery.rs +++ b/boards/recovery/src/state_machine/states/wait_for_recovery.rs @@ -5,7 +5,7 @@ use crate::state_machine::{RocketStates, State, StateMachineContext, TransitionI use crate::types::COM_ID; use defmt::{write, Format, Formatter}; use messages::command::{Command, PowerDown, RadioRate, RadioRateChange}; -use messages::sender::Sender::SensorBoard; +use messages::node::Node::SensorBoard; use messages::Message; use rtic::mutex::Mutex; diff --git a/boards/recovery/src/types.rs b/boards/recovery/src/types.rs index d7f5356d..6e6c29f3 100644 --- a/boards/recovery/src/types.rs +++ b/boards/recovery/src/types.rs @@ -1,7 +1,7 @@ -use messages::sender::Sender; -use messages::sender::Sender::RecoveryBoard; +use messages::node::Node; +use messages::node::Node::RecoveryBoard; // ------- -// Sender ID +// Node ID // ------- -pub static COM_ID: Sender = RecoveryBoard; +pub static COM_ID: Node = RecoveryBoard; diff --git a/boards/sensor/src/communication.rs b/boards/sensor/src/communication.rs index 2ef700ca..5eeda897 100644 --- a/boards/sensor/src/communication.rs +++ b/boards/sensor/src/communication.rs @@ -112,7 +112,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::CommunicationBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::CommunicationBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) @@ -121,7 +121,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::sender::Sender::RecoveryBoard.into()) + filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) @@ -130,7 +130,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::sender::Sender::GroundStation.into()) + filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()) .unwrap(), mask: ecan::StandardId::ZERO, }) diff --git a/boards/sensor/src/types.rs b/boards/sensor/src/types.rs index fe0877ab..7c063a71 100644 --- a/boards/sensor/src/types.rs +++ b/boards/sensor/src/types.rs @@ -8,14 +8,14 @@ use hal::dmac::BufferPair; use hal::sercom::IoSet2; use hal::sercom::Sercom4; -use messages::sender::Sender; -use messages::sender::Sender::SensorBoard; +use messages::node::Node; +use messages::node::Node::SensorBoard; use sbg_rs::sbg::SBG_BUFFER_SIZE; // ------- -// Sender ID +// Node ID // ------- -pub static COM_ID: Sender = SensorBoard; +pub static COM_ID: Node = SensorBoard; // ------- // SBG diff --git a/libraries/messages/src/command.rs b/libraries/messages/src/command.rs index 6ad0b804..8e2f0b40 100644 --- a/libraries/messages/src/command.rs +++ b/libraries/messages/src/command.rs @@ -1,4 +1,4 @@ -use crate::sender::Sender; +use crate::node::Node; use derive_more::From; use messages_proc_macros_lib::common_derives; @@ -32,7 +32,7 @@ pub struct DeployMain { #[common_derives] #[derive(From)] pub struct PowerDown { - pub board: Sender, // This isn't proper naming !! This is the board to be powered down. Changes name of sender.rs to board.rs. + pub board: Node, } #[common_derives] diff --git a/libraries/messages/src/lib.rs b/libraries/messages/src/lib.rs index 90fdccc1..e6316d1e 100644 --- a/libraries/messages/src/lib.rs +++ b/libraries/messages/src/lib.rs @@ -7,7 +7,7 @@ use crate::command::Command; use crate::health::Health; -use crate::sender::Sender; +use crate::node::Node; use crate::sensor::Sensor; use crate::state::State; use derive_more::From; @@ -19,7 +19,7 @@ use messages_proc_macros_lib::common_derives; pub mod command; pub mod health; mod logging; -pub mod sender; +pub mod node; pub mod sensor; pub mod sensor_status; pub mod state; @@ -42,7 +42,7 @@ pub struct Message { pub timestamp: u64, /// The original sender of this message. - pub sender: Sender, + pub sender: Node, /// The data contained in this message. pub data: Data, @@ -62,7 +62,7 @@ pub enum Data { impl Message { pub fn new( timestamp: &Instant, - sender: Sender, + sender: Node, data: impl Into, ) -> Self { Message { diff --git a/libraries/messages/src/node.rs b/libraries/messages/src/node.rs new file mode 100644 index 00000000..3eff0712 --- /dev/null +++ b/libraries/messages/src/node.rs @@ -0,0 +1,27 @@ +use messages_proc_macros_lib::common_derives; + +#[common_derives] +#[derive(Copy)] +pub enum Node { + GroundStation, + SensorBoard, + RecoveryBoard, + CommunicationBoard, + PowerBoard, + CameraBoard, + BeaconBoard, +} + +impl From for u16 { + fn from(node: Node) -> Self { + match node { + Node::GroundStation => 0, + Node::SensorBoard => 1, + Node::RecoveryBoard => 2, + Node::CommunicationBoard => 3, + Node::PowerBoard => 4, + Node::CameraBoard => 5, + Node::BeaconBoard => 6, + } + } +} diff --git a/libraries/messages/src/sender.rs b/libraries/messages/src/sender.rs deleted file mode 100644 index 2bc90999..00000000 --- a/libraries/messages/src/sender.rs +++ /dev/null @@ -1,28 +0,0 @@ -use messages_proc_macros_lib::common_derives; - -// I don't agree with the naming, We can use these as Ids to sent commands to that specific board. -#[common_derives] -#[derive(Copy)] -pub enum Sender { - GroundStation, - SensorBoard, - RecoveryBoard, - CommunicationBoard, - PowerBoard, - CameraBoard, - BeaconBoard, -} - -impl From for u16 { - fn from(sender: Sender) -> Self { - match sender { - Sender::GroundStation => 0, - Sender::SensorBoard => 1, - Sender::RecoveryBoard => 2, - Sender::CommunicationBoard => 3, - Sender::PowerBoard => 4, - Sender::CameraBoard => 5, - Sender::BeaconBoard => 6, - } - } -} From 8f34d7f985763951794dc58375c7c90c43edd65b Mon Sep 17 00:00:00 2001 From: Fernando Nogueira Date: Sat, 11 May 2024 12:20:55 -0400 Subject: [PATCH 3/5] format: run cargo fmt (#106) * format: run cargo fmt * ci: --- .github/workflows/clippy.yml | 3 + boards/beacon/src/communication.rs | 2 +- boards/beacon/src/main.rs | 29 ++++----- boards/beacon/src/types.rs | 2 +- boards/camera/src/communication.rs | 3 +- boards/camera/src/data_manager.rs | 6 +- boards/communication/src/communication.rs | 9 +-- boards/recovery/src/communication.rs | 3 +- boards/recovery/src/data_manager.rs | 14 ++-- boards/sensor/src/communication.rs | 6 +- boards/sensor/src/data_manager.rs | 3 +- libraries/messages/src/lib.rs | 4 +- libraries/sbg-rs/src/data_conversion.rs | 79 +++++++++++++++-------- 13 files changed, 93 insertions(+), 70 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index bf48bc47..0f021d0f 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -19,6 +19,8 @@ jobs: components: clippy toolchain: stable target: thumbv7em-none-eabihf + - name: cargofmt + run: cargo fmt --check - uses: actions/cache@v3 with: path: | @@ -31,3 +33,4 @@ jobs: - uses: actions-rs/clippy-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file diff --git a/boards/beacon/src/communication.rs b/boards/beacon/src/communication.rs index 52a04d58..765597b7 100644 --- a/boards/beacon/src/communication.rs +++ b/boards/beacon/src/communication.rs @@ -1 +1 @@ -//! Interface the SPI-based CAN device here. \ No newline at end of file +//! Interface the SPI-based CAN device here. diff --git a/boards/beacon/src/main.rs b/boards/beacon/src/main.rs index 5fb6b46a..fbf26102 100644 --- a/boards/beacon/src/main.rs +++ b/boards/beacon/src/main.rs @@ -9,19 +9,22 @@ use common_arm::SdManager; use common_arm::*; use data_manager::DataManager; // use defmt::info; -use messages::sensor::Sensor; -use messages::*; -use stm32l0xx_hal as hal; use hal::{ gpio::*, + gpio::{ + gpioa::{PA10, PA9}, + Output, PushPull, + }, prelude::*, rcc::Config, - gpio::{gpioa::{PA9, PA10}, Output, PushPull}, }; +use messages::sensor::Sensor; +use messages::*; +use stm32l0xx_hal as hal; use systick_monotonic::*; -// use https://github.com/lora-rs/lora-rs.git +// use https://github.com/lora-rs/lora-rs.git /// Custom panic handler. /// Reset the system if a panic occurs. @@ -30,7 +33,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { stm32l0xx_hal::pac::SCB::sys_reset(); } -// Add dispatchers +// Add dispatchers #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [EXTI0_1, EXTI2_3, EXTI4_15])] mod app { @@ -56,11 +59,11 @@ mod app { fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { let device = cx.device; let core = cx.core; - - // configure the clock + + // configure the clock let mut rcc = device.RCC.freeze(Config::hse(64_000_000u32.Hz())); - // configure leds + // configure leds let gpioa = device.GPIOA.split(&mut rcc); let mut green_led = gpioa.pa9.into_push_pull_output(); let mut red_led = gpioa.pa10.into_push_pull_output(); @@ -73,12 +76,8 @@ mod app { Shared { em: ErrorManager::new(), data_manager: DataManager::new(), - - }, - Local { - green_led, - red_led, }, + Local { green_led, red_led }, init::Monotonics(mono), ) } @@ -97,7 +96,7 @@ mod app { todo!("Send messages over CAN"); } - #[task(capacity = 5)] + #[task(capacity = 5)] fn send_external(cx: send_external::Context, m: Message) { todo!("Send messages over LORA"); } diff --git a/boards/beacon/src/types.rs b/boards/beacon/src/types.rs index 1274347f..c13f876d 100644 --- a/boards/beacon/src/types.rs +++ b/boards/beacon/src/types.rs @@ -4,4 +4,4 @@ use messages::node::Node::BeaconBoard; // ------- // Node ID // ------- -pub static COM_ID: Node = BeaconBoard; \ No newline at end of file +pub static COM_ID: Node = BeaconBoard; diff --git a/boards/camera/src/communication.rs b/boards/camera/src/communication.rs index 1a54fdae..d3a36b35 100644 --- a/boards/camera/src/communication.rs +++ b/boards/camera/src/communication.rs @@ -103,8 +103,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Sensor filter")); diff --git a/boards/camera/src/data_manager.rs b/boards/camera/src/data_manager.rs index 5e62aca9..bcafdcb1 100644 --- a/boards/camera/src/data_manager.rs +++ b/boards/camera/src/data_manager.rs @@ -64,7 +64,7 @@ impl DataManager { Some(air) => match air.altitude { Some(altitude) => altitude > HEIGHT_MIN, None => false, - } + }, None => false, } } @@ -105,8 +105,8 @@ impl DataManager { match self.air.as_ref() { Some(air) => match air.altitude { Some(altitude) => altitude < MAIN_HEIGHT, - None => false - } + None => false, + }, None => false, } } diff --git a/boards/communication/src/communication.rs b/boards/communication/src/communication.rs index 6af79cb4..bdee0df0 100644 --- a/boards/communication/src/communication.rs +++ b/boards/communication/src/communication.rs @@ -120,8 +120,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Recovery filter")); @@ -129,8 +128,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Sensor filter")); @@ -146,8 +144,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Ground Station filter")); diff --git a/boards/recovery/src/communication.rs b/boards/recovery/src/communication.rs index c6e4d6e4..ee914d38 100644 --- a/boards/recovery/src/communication.rs +++ b/boards/recovery/src/communication.rs @@ -111,8 +111,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::SensorBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Sensor Board filter")); diff --git a/boards/recovery/src/data_manager.rs b/boards/recovery/src/data_manager.rs index 605d6285..a6acb042 100644 --- a/boards/recovery/src/data_manager.rs +++ b/boards/recovery/src/data_manager.rs @@ -78,7 +78,7 @@ impl DataManager { Some(air) => match air.altitude { Some(altitude) => altitude > HEIGHT_MIN, None => false, - } + }, None => false, } } @@ -120,7 +120,7 @@ impl DataManager { Some(air) => match air.altitude { Some(altitude) => altitude < MAIN_HEIGHT, None => false, - } + }, None => false, } } @@ -132,11 +132,11 @@ impl DataManager { messages::Data::Sensor(sensor) => match sensor.data { messages::sensor::SensorData::Air(air_data) => { /* - NOTE!!! - There should be added a counter to check how many times - the alt is dropped, if the number is high switch to - the on board barometer. - */ + NOTE!!! + There should be added a counter to check how many times + the alt is dropped, if the number is high switch to + the on board barometer. + */ if let Some(alt) = air_data.altitude { let tup_data: (f32, u32) = (alt, air_data.time_stamp); diff --git a/boards/sensor/src/communication.rs b/boards/sensor/src/communication.rs index 5eeda897..097adcbb 100644 --- a/boards/sensor/src/communication.rs +++ b/boards/sensor/src/communication.rs @@ -121,8 +121,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo0, - filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::RecoveryBoard.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Recovery filter")); @@ -130,8 +129,7 @@ impl CanDevice0 { can.filters_standard() .push(Filter::Classic { action: Action::StoreFifo1, - filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()) - .unwrap(), + filter: ecan::StandardId::new(messages::node::Node::GroundStation.into()).unwrap(), mask: ecan::StandardId::ZERO, }) .unwrap_or_else(|_| panic!("Ground Station filter")); diff --git a/boards/sensor/src/data_manager.rs b/boards/sensor/src/data_manager.rs index 4c895db0..5691b5cd 100644 --- a/boards/sensor/src/data_manager.rs +++ b/boards/sensor/src/data_manager.rs @@ -1,7 +1,8 @@ use crate::app::sleep_system; use common_arm::{spawn, HydraError}; use messages::sensor::{ - Air, EkfNav1, EkfNav2, EkfQuat, GpsPos1, GpsPos2, GpsVel, Imu1, Imu2, SensorData, UtcTime, EkfNavAcc, GpsPosAcc, GpsVelAcc, + Air, EkfNav1, EkfNav2, EkfNavAcc, EkfQuat, GpsPos1, GpsPos2, GpsPosAcc, GpsVel, GpsVelAcc, + Imu1, Imu2, SensorData, UtcTime, }; use messages::Message; diff --git a/libraries/messages/src/lib.rs b/libraries/messages/src/lib.rs index e6316d1e..9541c85c 100644 --- a/libraries/messages/src/lib.rs +++ b/libraries/messages/src/lib.rs @@ -75,7 +75,9 @@ impl Message { #[cfg(test)] mod test { - use crate::{Message, MAX_HEALTH_SIZE, MAX_COMMAND_SIZE, MAX_LOG_SIZE, MAX_SENSOR_SIZE, MAX_STATE_SIZE}; + use crate::{ + Message, MAX_COMMAND_SIZE, MAX_HEALTH_SIZE, MAX_LOG_SIZE, MAX_SENSOR_SIZE, MAX_STATE_SIZE, + }; use proptest::prelude::*; proptest! { diff --git a/libraries/sbg-rs/src/data_conversion.rs b/libraries/sbg-rs/src/data_conversion.rs index 2ff7a675..f54c8c6d 100644 --- a/libraries/sbg-rs/src/data_conversion.rs +++ b/libraries/sbg-rs/src/data_conversion.rs @@ -1,11 +1,15 @@ use crate::bindings::{ - SbgLogAirData, SbgLogEkfNavData, SbgLogEkfQuatData, SbgLogGpsVel, SbgLogImuData, SbgLogUtcData, SbgLogGpsPos, + SbgLogAirData, SbgLogEkfNavData, SbgLogEkfQuatData, SbgLogGpsPos, SbgLogGpsVel, SbgLogImuData, + SbgLogUtcData, }; use bitflags::Flags; -use messages::sensor::{Air, EkfNav1, EkfNav2, EkfNavAcc, EkfQuat, GpsVel, Imu1, Imu2, UtcTime, GpsPos1, GpsPos2, GpsPosAcc, GpsVelAcc}; +use messages::sensor::{ + Air, EkfNav1, EkfNav2, EkfNavAcc, EkfQuat, GpsPos1, GpsPos2, GpsPosAcc, GpsVel, GpsVelAcc, + Imu1, Imu2, UtcTime, +}; use messages::sensor_status::{ - AirFlags, AirStatus, EkfFlags, EkfStatus, GpsVelStatus, GpsVelStatusE, ImuFlags, ImuStatus, - UtcStatus, UtcTimeStatus, GpsPositionStatus, GpsPositionStatusE + AirFlags, AirStatus, EkfFlags, EkfStatus, GpsPositionStatus, GpsPositionStatusE, GpsVelStatus, + GpsVelStatusE, ImuFlags, ImuStatus, UtcStatus, UtcTimeStatus, }; /// Simple helper function to work with the flags structure and set the fields as needed. @@ -23,29 +27,49 @@ where impl From for (GpsPos1, GpsPos2, GpsPosAcc) { fn from(value: SbgLogGpsPos) -> Self { let status = GpsPositionStatus::new(value.status); - + let valid = matches!(status.get_status(), Some(GpsPositionStatusE::SolComputed)); - + ( GpsPos1 { - latitude: if valid {Some(value.latitude)} else {None}, - longitude: if valid {Some(value.longitude)} else {None}, + latitude: if valid { Some(value.latitude) } else { None }, + longitude: if valid { Some(value.longitude) } else { None }, }, GpsPos2 { - altitude: if valid {Some(value.altitude)} else {None}, - undulation: if valid {Some(value.undulation)} else {None}, - time_of_week: if valid {Some(value.timeOfWeek)} else {None}, + altitude: if valid { Some(value.altitude) } else { None }, + undulation: if valid { Some(value.undulation) } else { None }, + time_of_week: if valid { Some(value.timeOfWeek) } else { None }, }, GpsPosAcc { status, time_stamp: value.timeStamp, - latitude_accuracy: if valid {Some(value.latitudeAccuracy)} else {None}, - longitude_accuracy: if valid {Some(value.longitudeAccuracy)} else {None}, - altitude_accuracy: if valid {Some(value.altitudeAccuracy)} else {None}, - num_sv_used: if valid {Some(value.numSvUsed)} else {None}, - base_station_id: if valid {Some(value.baseStationId)} else {None}, - differential_age: if valid {Some(value.differentialAge)} else {None}, - } + latitude_accuracy: if valid { + Some(value.latitudeAccuracy) + } else { + None + }, + longitude_accuracy: if valid { + Some(value.longitudeAccuracy) + } else { + None + }, + altitude_accuracy: if valid { + Some(value.altitudeAccuracy) + } else { + None + }, + num_sv_used: if valid { Some(value.numSvUsed) } else { None }, + base_station_id: if valid { + Some(value.baseStationId) + } else { + None + }, + differential_age: if valid { + Some(value.differentialAge) + } else { + None + }, + }, ) } } @@ -53,10 +77,13 @@ impl From for (GpsPos1, GpsPos2, GpsPosAcc) { impl From for UtcTime { fn from(value: SbgLogUtcData) -> Self { let status = UtcTimeStatus::new(value.status); - let valid = matches!(status.get_utc_status(), Some(UtcStatus::Valid | UtcStatus::NoLeapSec)); + let valid = matches!( + status.get_utc_status(), + Some(UtcStatus::Valid | UtcStatus::NoLeapSec) + ); Self { - time_stamp: value.timeStamp, // not convinced this is matched valid to the Utc Status bitmask. + time_stamp: value.timeStamp, // not convinced this is matched valid to the Utc Status bitmask. status, year: if valid { Some(value.year) } else { None }, month: if valid { Some(value.month) } else { None }, @@ -114,7 +141,6 @@ impl From for (EkfNav1, EkfNav2, EkfNavAcc) { EkfNav1 { time_stamp: value.timeStamp, velocity: check(&flags, EkfFlags::VelocityValid, value.velocity), - }, EkfNav2 { undulation: check(&flags, EkfFlags::AttitudeValid, value.undulation), @@ -124,7 +150,7 @@ impl From for (EkfNav1, EkfNav2, EkfNavAcc) { velocity_std_dev: check(&flags, EkfFlags::VelocityValid, value.velocityStdDev), position_std_dev: check(&flags, EkfFlags::PositionValid, value.positionStdDev), status, - } + }, ) } } @@ -142,7 +168,7 @@ impl From for (Imu1, Imu2) { accelerometers: check(&flags, ImuFlags::AccelsInRange, value.accelerometers), }, Imu2 { - temperature: Some(value.temperature), // we cannot check since no flag exists. Keep in option for uniformity. + temperature: Some(value.temperature), // we cannot check since no flag exists. Keep in option for uniformity. delta_velocity: check(&flags, ImuFlags::AccelsInRange, value.deltaVelocity), delta_angle: check(&flags, ImuFlags::GyrosInRange, value.deltaAngle), }, @@ -159,16 +185,15 @@ impl From for (GpsVel, GpsVelAcc) { ( GpsVel { time_stamp: value.timeStamp, - time_of_week: if valid {Some(value.timeOfWeek) } else {None}, + time_of_week: if valid { Some(value.timeOfWeek) } else { None }, status, velocity: if valid { Some(value.velocity) } else { None }, course: if valid { Some(value.course) } else { None }, - }, + }, GpsVelAcc { velocity_acc: if valid { Some(value.velocityAcc) } else { None }, course_acc: if valid { Some(value.courseAcc) } else { None }, - } - + }, ) } } From a05f34a96e06c592eaf13512697f5ce7f287e7f0 Mon Sep 17 00:00:00 2001 From: Fernando Nogueira Date: Wed, 15 May 2024 13:10:36 -0400 Subject: [PATCH 4/5] Update Dev container and README (#108) * docs: * chore:update dockerfile * chore: update dockerfile * chore: make dockerfile multiplayer --- .devcontainer/Dockerfile | 27 ++++++++++++----- .gitignore | 3 +- README.md | 62 +++++++++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8c950e5a..06c8907b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,24 @@ +# Base image for toolchain download +FROM mcr.microsoft.com/devcontainers/rust:latest as toolchain + +RUN mkdir -p /toolchain && \ + curl -L "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz" \ + | tar --strip-components=1 -xJ -C /toolchain + +# Final image FROM mcr.microsoft.com/devcontainers/rust:latest +# Copy the toolchain from the previous stage +COPY --from=toolchain /toolchain /toolchain + +ENV PATH="${PATH}:/toolchain/bin" ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get upgrade -y && apt-get install -y cmake pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev libssl-dev -# Install ARM GCC deps -RUN mkdir -p toolchain && \ - curl -L "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz" \ - | tar --strip-components=1 -xJ -C toolchain && \ - cargo install --locked probe-rs --features cli -ENV PATH="${PATH}:/toolchain/bin" \ No newline at end of file +# Necessary system packages +RUN apt-get update && apt-get install -y cmake pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev libssl-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Install Rust crates +RUN cargo install probe-rs --features cli \ + && cargo install cargo-make \ No newline at end of file diff --git a/.gitignore b/.gitignore index ce0aec4d..d5446d17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target /.vscode/.cortex-debug.registers.state.json /.vscode/.cortex-debug.peripherals.state.json -/.vscode/settings.json \ No newline at end of file +/.vscode/settings.json +/toolchain diff --git a/README.md b/README.md index 32273847..16db41b5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # HYDRA   [![Build Status]][actions] [![docs-badge]][docs] -*HYper Dynamic Rocketry Avionics* + +***HY**per **D**ynamic **R**ocketry **A**vionics* [Build Status]: https://github.com/uorocketry/hydra/actions/workflows/build.yml/badge.svg [actions]: https://github.com/uorocketry/hydra/actions?query=branch%3Amaster @@ -12,46 +13,60 @@ ## Getting Started -1. Install Rust: https://www.rust-lang.org/tools/install -2. Build: `cargo build` -3. Install probe-run: `cargo install --git https://github.com/uorocketry/probe-run` - - `probe-run` currently requires a patch to flash our chip, so please use the above version while the patch is upstreamed -4. Install cargo-make: `cargo install cargo-make` -4. Flash: `cargo run --bin main` -5. Run tests: `cargo make test-host` or `cargo make test-device` +> If you are in a DevContainer skip to step 5. + +- Install Rust: https://www.rust-lang.org/tools/install +- Install necessary build tools: + - cargo-make: `cargo install cargo-make` + - probe-rs: `cargo install probe-rs --features cli` +- Install the [ARM GNU Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) (last tested with 13.2) and have it available in your PATH + - Arch Linux: `sudo pacman -S arm-none-eabi-gcc` + - Alpine/Debian/Ubuntu: + - MacOS: `brew install arm-none-eabi-gcc` +- Build: `cargo build` + - In case it fails, try `cargo build --release` +- Run tests: + - In the host machine: `cargo make test-host` + - In the device: `cargo make test-device` +- Flash on hardware: `cargo run --bin main` For more detailed instructions on flashing, debugging, and more, please see [the wiki](https://avwiki.uorocketry.ca/en/Avionics/HYDRA/Software). ## Windows Users ### Setting up with Docker -1. Install Docker: https://docs.docker.com/desktop/install/windows-install/ -2. Install VS Code: https://code.visualstudio.com/download -3. From VS Code, install the "Dev Containers" extension -4. press `ctrl` + `shift` + `p`, and search for `Dev Containers: Open Folder in Container` + +- Install [Docker](https://docs.docker.com/desktop/install/windows-install/) +- Install [VS Code](https://code.visualstudio.com/download) +- From VS Code, install the "Dev Containers" extension +- press `ctrl` + `shift` + `p`, and search for `Dev Containers: Open Folder in Container` ### Setting up with WSL -1. Enable WSL: https://learn.microsoft.com/en-us/windows/wsl/install -2. Install a linux distro from the Microsoft Store -4. Install ARM GNU Toolchain: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + +- Enable WSL: https://learn.microsoft.com/en-us/windows/wsl/install +- Install a linux distro from the Microsoft Store +- Install the [ARM GNU Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) - NOTE: You may find this in your distro's package manager, but ensure it is version 13.2. - Ubuntu has an outdated version in its repositories. If using Ubuntu, download it manually from the link above -3. Follow the rest of the instructions in [Getting Started](#-getting-started) +- Follow the rest of the instructions in [Getting Started](#-getting-started) ### Flashing + After plugging in J-Link, it will likely show up as unknown. + 1. Install Zadig: https://zadig.akeo.ie/ 2. From Zadig, select J-Link as the device and WinUSB as the driver 3. click Install Driver If using WSL or Docker with a WSL backend (you probably are), you need to tell Windows to share J-Link with WSL. -1. From WSL, install linux-tools-generic - 1. on Ubuntu: `sudo apt install linux-tools-generic` -2. Install usbipd-win: https://github.com/dorssel/usbipd-win/releases -3. Open command prompt/powershell with admin privileges and run `usbipd list` -4. Make note of the entry called J-Link and run `usbipd bind --busid ` -5. Next, run `usbipd attach --wsl --busid ` -6. You can now follow the flashing instructions in [Getting Started](#-getting-started) + +- From WSL, install linux-tools-generic + - on Ubuntu: `sudo apt install linux-tools-generic` +- Install usbipd-win: https://github.com/dorssel/usbipd-win/releases +- Open command prompt/powershell with admin privileges and run `usbipd list` +- Make note of the entry called J-Link and run `usbipd bind --busid ` +- Next, run `usbipd attach --wsl --busid ` +- You can now follow the flashing instructions in [Getting Started](#getting-started) ## Documentation @@ -60,6 +75,7 @@ Run `cargo doc --open` to build and open the documentation. Most documentation f Documentation is also automatically built and deployed to https://hydra-docs.uorocketry.ca/common_arm ## Project Structure + The project is structured in a way to allow reuse of the code across various boards and other projects. - `boards`: Folder containing each individual board's binary crates. Any code in those crates should only contain logic specific to the board. From 0251afa4491cbfa66486f800c7d8cd94454006eb Mon Sep 17 00:00:00 2001 From: Eilay Katsnelson <22532056+eilayk@users.noreply.github.com> Date: Sat, 8 Jun 2024 12:54:36 -0400 Subject: [PATCH 5/5] Add Recovery Timeout (#101) * create recovery timer mechanism * fix build * clear interrupts * WIP: Timer Update * fix build errors * optimize * fix linting * Fix: Cippy warnings * Fix: remove magic number * Fix: remove magic number * Fix: Clippy * Fix: Import --------- Co-authored-by: Eilay Katsnelson Co-authored-by: Noah Sprenger --- boards/recovery/src/data_manager.rs | 27 ++++++++++------ boards/recovery/src/main.rs | 31 +++++++++++++++++-- boards/recovery/src/state_machine/mod.rs | 11 +++++-- .../state_machine/states/terminal_descent.rs | 10 ++++++ .../state_machine/states/wait_for_recovery.rs | 4 +++ 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/boards/recovery/src/data_manager.rs b/boards/recovery/src/data_manager.rs index a6acb042..acceff1e 100644 --- a/boards/recovery/src/data_manager.rs +++ b/boards/recovery/src/data_manager.rs @@ -8,6 +8,9 @@ use messages::Message; const MAIN_HEIGHT: f32 = 876.0; // meters ASL const HEIGHT_MIN: f32 = 600.0; // meters ASL +const RECOVERY_DATA_POINTS: u8 = 8; // number of barometric altitude readings held by the recovery + // algorithm +const RECOVERY_TIMER_TIMEOUT: u8 = 15; // minutes pub struct DataManager { pub air: Option, @@ -16,8 +19,11 @@ pub struct DataManager { pub imu: (Option, Option), pub utc_time: Option, pub gps_vel: Option, - pub historical_barometer_altitude: HistoryBuffer<(f32, u32), 8>, + pub historical_barometer_altitude: HistoryBuffer<(f32, u32), 8>, // RECOVERY_DATA_POINTS (issue + // when putting as const) pub current_state: Option, + // each tick represents a minute that passed + pub recovery_counter: u8, } impl DataManager { @@ -32,11 +38,12 @@ impl DataManager { gps_vel: None, historical_barometer_altitude, current_state: None, + recovery_counter: 0, } } /// Returns true if the rocket is descending pub fn is_falling(&self) -> bool { - if self.historical_barometer_altitude.len() < 8 { + if (self.historical_barometer_altitude.len() as u8) < RECOVERY_DATA_POINTS { return false; } let mut buf = self.historical_barometer_altitude.oldest_ordered(); @@ -56,14 +63,14 @@ impl DataManager { avg_sum += slope; prev = i; } - match avg_sum / 7.0 { + match avg_sum / (RECOVERY_DATA_POINTS as f32 - 1.0) { // 7 because we have 8 points. // exclusive range x if !(-100.0..=-5.0).contains(&x) => { return false; } _ => { - info!("avg: {}", avg_sum / 7.0); + info!("avg: {}", avg_sum / (RECOVERY_DATA_POINTS as f32 - 1.0)); } } } @@ -82,8 +89,8 @@ impl DataManager { None => false, } } - pub fn is_landed(&self) -> bool { - if self.historical_barometer_altitude.len() < 8 { + pub fn is_landed(&mut self) -> bool { + if self.historical_barometer_altitude.len() < RECOVERY_DATA_POINTS.into() { return false; } let mut buf = self.historical_barometer_altitude.oldest_ordered(); @@ -99,13 +106,15 @@ impl DataManager { avg_sum += (i.0 - prev.0) / time_diff; prev = i; } - match avg_sum / 7.0 { + match avg_sum / (RECOVERY_DATA_POINTS as f32 - 1.0) { // inclusive range x if (-0.25..=0.25).contains(&x) => { - return true; + if self.recovery_counter >= RECOVERY_TIMER_TIMEOUT { + return true; + } } _ => { - // continue + self.recovery_counter = 0; } } } diff --git a/boards/recovery/src/main.rs b/boards/recovery/src/main.rs index bd08c8f8..c96fbbc7 100644 --- a/boards/recovery/src/main.rs +++ b/boards/recovery/src/main.rs @@ -19,6 +19,7 @@ use data_manager::DataManager; use gpio_manager::GPIOManager; use hal::gpio::{Pin, Pins, PushPullOutput, PB16, PB17}; use hal::prelude::*; +use hal::timer::TimerCounter2; use mcan::messageram::SharedMemory; use messages::*; use state_machine::{StateMachine, StateMachineContext}; @@ -42,6 +43,7 @@ mod app { data_manager: DataManager, can0: communication::CanDevice0, gpio: GPIOManager, + recovery_timer: TimerCounter2, } #[local] @@ -78,7 +80,7 @@ mod app { // SAFETY: Misusing the PAC API can break the system. // This is safe because we only steal the MCLK. - let (_, _, _, _mclk) = unsafe { clocks.pac.steal() }; + let (_, _, _, mut mclk) = unsafe { clocks.pac.steal() }; /* CAN config */ let (pclk_can, gclk0) = Pclk::enable(tokens.pclks.can0, gclk0); @@ -104,6 +106,11 @@ mod app { /* State Machine config */ let state_machine = StateMachine::new(); + /* Recovery Timer config */ + let (pclk_tc2tc3, gclk0) = Pclk::enable(tokens.pclks.tc2_tc3, gclk0); + let timerclk: hal::clock::v1::Tc2Tc3Clock = pclk_tc2tc3.into(); + let recovery_timer = hal::timer::TimerCounter2::tc2_(&timerclk, peripherals.TC2, &mut mclk); + /* Spawn tasks */ run_sm::spawn().ok(); state_send::spawn().ok(); @@ -120,6 +127,7 @@ mod app { data_manager: DataManager::new(), can0, gpio, + recovery_timer, }, Local { led_green, @@ -136,6 +144,25 @@ mod app { loop {} } + // interrupt handler for recovery counter + #[task(binds=TC2, shared=[data_manager, recovery_timer])] + fn recovery_counter_tick(mut cx: recovery_counter_tick::Context) { + cx.shared.recovery_timer.lock(|timer| { + if timer.wait().is_ok() { + cx.shared.data_manager.lock(|data| { + data.recovery_counter += 1; + }); + // restart timer after interrupt + let duration_mins = atsamd_hal::fugit::MinutesDurationU32::minutes(1); + // timer requires specific duration format + let timer_duration: atsamd_hal::fugit::Duration = + duration_mins.convert(); + timer.start(timer_duration); + } + timer.enable_interrupt(); // clear interrupt + }); + } + #[task(priority = 3, local = [fired: bool = false], shared=[gpio, &em])] fn fire_drogue(mut cx: fire_drogue::Context) { cx.shared.em.run(|| { @@ -175,7 +202,7 @@ mod app { /// Runs the state machine. /// This takes control of the shared resources. - #[task(priority = 3, local = [state_machine], shared = [can0, gpio, data_manager, &em])] + #[task(priority = 3, local = [state_machine], shared = [can0, gpio, data_manager, &em, recovery_timer])] fn run_sm(mut cx: run_sm::Context) { cx.local.state_machine.run(&mut StateMachineContext { shared_resources: &mut cx.shared, diff --git a/boards/recovery/src/state_machine/mod.rs b/boards/recovery/src/state_machine/mod.rs index 7b13913f..3972b687 100644 --- a/boards/recovery/src/state_machine/mod.rs +++ b/boards/recovery/src/state_machine/mod.rs @@ -5,6 +5,7 @@ use crate::communication::CanDevice0; use crate::data_manager::DataManager; use crate::gpio_manager::GPIOManager; use crate::state_machine::states::*; +use atsamd_hal::timer::TimerCounter2; pub use black_magic::*; use core::fmt::Debug; use defmt::Format; @@ -17,6 +18,7 @@ pub trait StateMachineSharedResources { fn lock_can(&mut self, f: &dyn Fn(&mut CanDevice0)); fn lock_data_manager(&mut self, f: &dyn Fn(&mut DataManager)); fn lock_gpio(&mut self, f: &dyn Fn(&mut GPIOManager)); + fn lock_recovery_timer(&mut self, f: &dyn Fn(&mut TimerCounter2)); } impl<'a> StateMachineSharedResources for crate::app::__rtic_internal_run_smSharedResources<'a> { @@ -29,6 +31,9 @@ impl<'a> StateMachineSharedResources for crate::app::__rtic_internal_run_smShare fn lock_gpio(&mut self, fun: &dyn Fn(&mut GPIOManager)) { self.gpio.lock(fun) } + fn lock_recovery_timer(&mut self, fun: &dyn Fn(&mut TimerCounter2)) { + self.recovery_timer.lock(fun) + } } pub struct StateMachineContext<'a, 'b> { @@ -103,9 +108,9 @@ impl From for RocketStates { } } // Linter: an implementation of From is preferred since it gives you Into<_> for free where the reverse isn't true -impl Into for RocketStates { - fn into(self) -> state::StateData { - match self { +impl From for state::StateData { + fn from(val: RocketStates) -> Self { + match val { RocketStates::Initializing(_) => state::StateData::Initializing, RocketStates::WaitForTakeoff(_) => state::StateData::WaitForTakeoff, RocketStates::Ascent(_) => state::StateData::Ascent, diff --git a/boards/recovery/src/state_machine/states/terminal_descent.rs b/boards/recovery/src/state_machine/states/terminal_descent.rs index 104e6ccd..b95b0a58 100644 --- a/boards/recovery/src/state_machine/states/terminal_descent.rs +++ b/boards/recovery/src/state_machine/states/terminal_descent.rs @@ -4,6 +4,8 @@ use crate::state_machine::{ RocketStates, State, StateMachineContext, TransitionInto, WaitForRecovery, }; use crate::{no_transition, transition}; +use atsamd_hal::prelude::_embedded_hal_timer_CountDown; +use atsamd_hal::timer_traits::InterruptDrivenTimer; use common_arm::spawn; use defmt::{write, Format, Formatter}; use rtic::mutex::Mutex; @@ -17,6 +19,14 @@ impl State for TerminalDescent { spawn!(fire_main)?; Ok(()) }); + context.shared_resources.recovery_timer.lock(|timer| { + timer.enable_interrupt(); + let duration_mins = atsamd_hal::fugit::MinutesDurationU32::minutes(1); + // timer requires specific duration format + let timer_duration: atsamd_hal::fugit::Duration = + duration_mins.convert(); + timer.start(timer_duration); + }); } fn step(&mut self, context: &mut StateMachineContext) -> Option { context.shared_resources.data_manager.lock(|data| { diff --git a/boards/recovery/src/state_machine/states/wait_for_recovery.rs b/boards/recovery/src/state_machine/states/wait_for_recovery.rs index 52d4a3aa..ddcef0b3 100644 --- a/boards/recovery/src/state_machine/states/wait_for_recovery.rs +++ b/boards/recovery/src/state_machine/states/wait_for_recovery.rs @@ -3,6 +3,7 @@ use crate::app::monotonics; use crate::no_transition; use crate::state_machine::{RocketStates, State, StateMachineContext, TransitionInto}; use crate::types::COM_ID; +use atsamd_hal::timer_traits::InterruptDrivenTimer; use defmt::{write, Format, Formatter}; use messages::command::{Command, PowerDown, RadioRate, RadioRateChange}; use messages::node::Node::SensorBoard; @@ -32,6 +33,9 @@ impl State for WaitForRecovery { }) }); } + context.shared_resources.recovery_timer.lock(|timer| { + timer.disable_interrupt(); + }) } fn step(&mut self, _context: &mut StateMachineContext) -> Option { no_transition!() // this is our final resting place. We should also powerdown this board.