From e302f4f50bedbbdc3f0a8a25143186824614a4b0 Mon Sep 17 00:00:00 2001 From: Noah Sprenger Date: Tue, 12 Mar 2024 19:46:02 -0400 Subject: [PATCH] Setup Beacon Board --- Cargo.lock | 144 +++++++++++++++++- Cargo.toml | 5 + boards/beacon/Cargo.toml | 17 +++ boards/beacon/src/communication.rs | 1 + boards/beacon/src/data_manager.rs | 122 +++++++++++++++ boards/beacon/src/main.rs | 122 +++++++++++++++ boards/beacon/src/types.rs | 7 + boards/sensor_v2/Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../build.rs | 0 .../memory.x | 0 .../src/lib.rs | 0 libraries/common-arm-stm32l0/Cargo.toml | 9 ++ libraries/common-arm-stm32l0/build.rs | 37 +++++ libraries/common-arm-stm32l0/memory.x | 6 + libraries/common-arm-stm32l0/src/lib.rs | 6 + libraries/messages/src/sender.rs | 2 + 17 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 boards/beacon/Cargo.toml create mode 100644 boards/beacon/src/communication.rs create mode 100644 boards/beacon/src/data_manager.rs create mode 100644 boards/beacon/src/main.rs create mode 100644 boards/beacon/src/types.rs rename libraries/{common-arm-stm32 => common-arm-stm32h7}/Cargo.toml (87%) rename libraries/{common-arm-stm32 => common-arm-stm32h7}/build.rs (100%) rename libraries/{common-arm-stm32 => common-arm-stm32h7}/memory.x (100%) rename libraries/{common-arm-stm32 => common-arm-stm32h7}/src/lib.rs (100%) create mode 100644 libraries/common-arm-stm32l0/Cargo.toml create mode 100644 libraries/common-arm-stm32l0/build.rs create mode 100644 libraries/common-arm-stm32l0/memory.x create mode 100644 libraries/common-arm-stm32l0/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e1c52042..25177363 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -87,6 +96,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" +[[package]] +name = "beacon" +version = "0.1.0" +dependencies = [ + "common-arm", + "common-arm-stm32l0", + "cortex-m", + "cortex-m-rt", + "cortex-m-rtic", + "messages", + "postcard", + "stm32l0xx-hal", + "systick-monotonic", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -172,6 +196,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +dependencies = [ + "num-traits", +] + [[package]] name = "cipher" version = "0.3.0" @@ -224,7 +257,14 @@ dependencies = [ ] [[package]] -name = "common-arm-stm32" +name = "common-arm-stm32h7" +version = "0.1.0" +dependencies = [ + "common-arm", +] + +[[package]] +name = "common-arm-stm32l0" version = "0.1.0" dependencies = [ "common-arm", @@ -500,6 +540,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" +[[package]] +name = "embedded-time" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" +dependencies = [ + "num", +] + [[package]] name = "enum_dispatch" version = "0.3.12" @@ -767,6 +816,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -778,6 +849,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -1039,6 +1141,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rtcc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fbd0d5bed2b76e27a7ef872568b34072c1af94c277cd52c17a89d54673b3fe" +dependencies = [ + "chrono", +] + [[package]] name = "rtic-core" version = "1.0.0" @@ -1195,7 +1306,7 @@ name = "sensor_v2" version = "0.1.0" dependencies = [ "common-arm", - "common-arm-stm32", + "common-arm-stm32h7", "cortex-m", "cortex-m-rt", "cortex-m-rtic", @@ -1337,6 +1448,35 @@ dependencies = [ "void", ] +[[package]] +name = "stm32l0" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c35ac5e2c330137c257b7254eb4593e3e8312104dedc1880447654cb8dd50f" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "stm32l0xx-hal" +version = "0.10.0" +source = "git+https://github.com/stm32-rs/stm32l0xx-hal#7132578d4c1d92e8c7afa777c0ac2e29855a2bdd" +dependencies = [ + "as-slice", + "cast", + "cortex-m", + "cortex-m-rt", + "embedded-hal", + "embedded-time", + "nb 1.1.0", + "rtcc", + "stm32l0", + "void", +] + [[package]] name = "syn" version = "0.15.44" diff --git a/Cargo.toml b/Cargo.toml index fa2ef33e..84813068 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,11 @@ features = ["defmt", "rt", "stm32h735" ] git = "https://github.com/uorocketry/atsamd" features = ["same51j", "same51j-rt", "dma", "can"] +[workspace.dependencies.stm32l0xx-hal] +git = "https://github.com/stm32-rs/stm32l0xx-hal" +features = ["mcu-STM32L051K8Tx", "rt"] + + [workspace.dependencies.serde] version = "1.0.150" default-features = false diff --git a/boards/beacon/Cargo.toml b/boards/beacon/Cargo.toml new file mode 100644 index 00000000..064ce6b8 --- /dev/null +++ b/boards/beacon/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "beacon" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cortex-m = { workspace = true } +cortex-m-rt = "^0.7.0" +cortex-m-rtic = "1.1.3" +common-arm-stm32l0 = {path = "../../libraries/common-arm-stm32l0"} +common-arm = {path = "../../libraries/common-arm"} +stm32l0xx-hal = { workspace = true } +postcard = "1.0.2" +messages = { path = "../../libraries/messages" } +systick-monotonic = "1.0.1" \ No newline at end of file diff --git a/boards/beacon/src/communication.rs b/boards/beacon/src/communication.rs new file mode 100644 index 00000000..52a04d58 --- /dev/null +++ b/boards/beacon/src/communication.rs @@ -0,0 +1 @@ +//! Interface the SPI-based CAN device here. \ No newline at end of file diff --git a/boards/beacon/src/data_manager.rs b/boards/beacon/src/data_manager.rs new file mode 100644 index 00000000..86f320be --- /dev/null +++ b/boards/beacon/src/data_manager.rs @@ -0,0 +1,122 @@ +use messages::command::RadioRate; +use messages::state::StateData; +use messages::Message; + +#[derive(Clone)] +pub struct DataManager { + pub air: Option, + pub ekf_nav_1: Option, + pub ekf_nav_2: Option, + pub ekf_quat: Option, + pub imu_1: Option, + pub imu_2: Option, + pub utc_time: Option, + pub gps_vel: Option, + pub gps_pos_1: Option, + pub gps_pos_2: Option, + pub state: Option, + pub logging_rate: Option, +} + +impl DataManager { + pub fn new() -> Self { + Self { + air: None, + ekf_nav_1: None, + ekf_nav_2: None, + ekf_quat: None, + imu_1: None, + imu_2: None, + utc_time: None, + gps_vel: None, + gps_pos_1: None, + gps_pos_2: None, + state: None, + logging_rate: Some(RadioRate::Slow), // start slow. + } + } + + pub fn get_logging_rate(&mut self) -> RadioRate { + if let Some(rate) = self.logging_rate.take() { + let rate_cln = rate.clone(); + self.logging_rate = Some(rate); + return rate_cln; + } + self.logging_rate = Some(RadioRate::Slow); + return RadioRate::Slow; + } + + /// Do not clone instead take to reduce CPU load. + pub fn take_sensors(&mut self) -> [Option; 10] { + [ + self.air.take(), + self.ekf_nav_1.take(), + self.ekf_nav_2.take(), + self.ekf_quat.take(), + self.imu_1.take(), + self.imu_2.take(), + self.utc_time.take(), + self.gps_vel.take(), + self.gps_pos_1.take(), + self.gps_pos_2.take(), + ] + } + + pub fn clone_states(&self) -> [Option; 1] { + [self.state.clone()] + } + pub fn handle_data(&mut self, data: Message) { + match data.data { + messages::Data::Sensor(ref sensor) => match sensor.data { + messages::sensor::SensorData::Air(_) => { + self.air = Some(data); + } + messages::sensor::SensorData::EkfNav1(_) => { + self.ekf_nav_1 = Some(data); + } + messages::sensor::SensorData::EkfNav2(_) => { + self.ekf_nav_2 = Some(data); + } + messages::sensor::SensorData::EkfQuat(_) => { + self.ekf_quat = Some(data); + } + messages::sensor::SensorData::GpsVel(_) => { + self.gps_vel = Some(data); + } + messages::sensor::SensorData::Imu1(_) => { + self.imu_1 = Some(data); + } + messages::sensor::SensorData::Imu2(_) => { + self.imu_2 = Some(data); + } + messages::sensor::SensorData::UtcTime(_) => { + self.utc_time = Some(data); + } + messages::sensor::SensorData::GpsPos1(_) => { + self.gps_pos_1 = Some(data); + } + messages::sensor::SensorData::GpsPos2(_) => { + self.gps_pos_2 = Some(data); + } + }, + messages::Data::State(state) => { + self.state = Some(state.data); + } + messages::Data::Command(command) => match command.data { + messages::command::CommandData::RadioRateChange(command_data) => { + self.logging_rate = Some(command_data.rate); + } + messages::command::CommandData::DeployDrogue(_) => {} + messages::command::CommandData::DeployMain(_) => {} + messages::command::CommandData::PowerDown(_) => {} + }, + _ => {} + } + } +} + +impl Default for DataManager { + fn default() -> Self { + Self::new() + } +} diff --git a/boards/beacon/src/main.rs b/boards/beacon/src/main.rs new file mode 100644 index 00000000..5fb6b46a --- /dev/null +++ b/boards/beacon/src/main.rs @@ -0,0 +1,122 @@ +#![no_std] +#![no_main] + +mod communication; +mod data_manager; +mod types; + +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::*, + prelude::*, + rcc::Config, + gpio::{gpioa::{PA9, PA10}, Output, PushPull}, +}; + +use systick_monotonic::*; + +// use https://github.com/lora-rs/lora-rs.git + +/// Custom panic handler. +/// Reset the system if a panic occurs. +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + stm32l0xx_hal::pac::SCB::sys_reset(); +} + +// Add dispatchers +#[rtic::app(device = hal::pac, peripherals = true, dispatchers = [EXTI0_1, EXTI2_3, EXTI4_15])] +mod app { + + use super::*; + + #[shared] + struct Shared { + em: ErrorManager, + data_manager: DataManager, + } + + #[local] + struct Local { + // add leds + green_led: PA9>, + red_led: PA10>, + } + + #[monotonic(binds = SysTick, default = true)] + type SysMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let device = cx.device; + let core = cx.core; + + // configure the clock + let mut rcc = device.RCC.freeze(Config::hse(64_000_000u32.Hz())); + + // 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(); + + /* Monotonic clock */ + // implement the monotonic clock + let mono = Systick::new(core.SYST, rcc.clocks.sys_clk().0); + + ( + Shared { + em: ErrorManager::new(), + data_manager: DataManager::new(), + + }, + Local { + green_led, + red_led, + }, + init::Monotonics(mono), + ) + } + + /// Idle task for when no other tasks are running. + #[idle] + fn idle(_: idle::Context) -> ! { + loop {} + } + + /** + * Sends a message over CAN. + */ + #[task(capacity = 10, local = [counter: u16 = 0], shared = [&em])] + fn send_internal(cx: send_internal::Context, m: Message) { + todo!("Send messages over CAN"); + } + + #[task(capacity = 5)] + fn send_external(cx: send_external::Context, m: Message) { + todo!("Send messages over LORA"); + } + + /** + * Simple blink task to test the system. + * Acts as a heartbeat for the system. + */ + #[task(local = [green_led, red_led], shared = [&em])] + fn blink(cx: blink::Context) { + cx.shared.em.run(|| { + if cx.shared.em.has_error() { + cx.local.red_led.toggle().ok(); + spawn_after!(blink, ExtU64::millis(200))?; + } else { + cx.local.green_led.toggle().ok(); // doesn't matter if an LED fails to blink + spawn_after!(blink, ExtU64::secs(1))?; + } + Ok(()) + }); + } +} diff --git a/boards/beacon/src/types.rs b/boards/beacon/src/types.rs new file mode 100644 index 00000000..d2fccd10 --- /dev/null +++ b/boards/beacon/src/types.rs @@ -0,0 +1,7 @@ +use messages::sender::Sender; +use messages::sender::Sender::BeaconBoard; + +// ------- +// Sender ID +// ------- +pub static COM_ID: Sender = BeaconBoard; \ No newline at end of file diff --git a/boards/sensor_v2/Cargo.toml b/boards/sensor_v2/Cargo.toml index 53704102..4c0710e9 100644 --- a/boards/sensor_v2/Cargo.toml +++ b/boards/sensor_v2/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" cortex-m = { workspace = true } cortex-m-rt = "^0.7.0" cortex-m-rtic = "1.1.3" -common-arm-stm32 = {path = "../../libraries/common-arm-stm32"} +common-arm-stm32h7 = {path = "../../libraries/common-arm-stm32h7"} common-arm = {path = "../../libraries/common-arm"} stm32h7xx-hal = { workspace = true } postcard = "1.0.2" diff --git a/libraries/common-arm-stm32/Cargo.toml b/libraries/common-arm-stm32h7/Cargo.toml similarity index 87% rename from libraries/common-arm-stm32/Cargo.toml rename to libraries/common-arm-stm32h7/Cargo.toml index 4d5b556c..f2ae377d 100644 --- a/libraries/common-arm-stm32/Cargo.toml +++ b/libraries/common-arm-stm32h7/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "common-arm-stm32" +name = "common-arm-stm32h7" version = "0.1.0" edition = "2021" diff --git a/libraries/common-arm-stm32/build.rs b/libraries/common-arm-stm32h7/build.rs similarity index 100% rename from libraries/common-arm-stm32/build.rs rename to libraries/common-arm-stm32h7/build.rs diff --git a/libraries/common-arm-stm32/memory.x b/libraries/common-arm-stm32h7/memory.x similarity index 100% rename from libraries/common-arm-stm32/memory.x rename to libraries/common-arm-stm32h7/memory.x diff --git a/libraries/common-arm-stm32/src/lib.rs b/libraries/common-arm-stm32h7/src/lib.rs similarity index 100% rename from libraries/common-arm-stm32/src/lib.rs rename to libraries/common-arm-stm32h7/src/lib.rs diff --git a/libraries/common-arm-stm32l0/Cargo.toml b/libraries/common-arm-stm32l0/Cargo.toml new file mode 100644 index 00000000..0e5b6476 --- /dev/null +++ b/libraries/common-arm-stm32l0/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "common-arm-stm32l0" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +common-arm = { path = "../common-arm" } diff --git a/libraries/common-arm-stm32l0/build.rs b/libraries/common-arm-stm32l0/build.rs new file mode 100644 index 00000000..2fd894d6 --- /dev/null +++ b/libraries/common-arm-stm32l0/build.rs @@ -0,0 +1,37 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + // set the linker script to the one provided by cortex-m-rt + println!("cargo:rustc-link-arg=-Tlink.x"); + + // we can also set our defmt script + println!("cargo:rustc-link-arg=-Tdefmt.x"); +} diff --git a/libraries/common-arm-stm32l0/memory.x b/libraries/common-arm-stm32l0/memory.x new file mode 100644 index 00000000..bbf5f123 --- /dev/null +++ b/libraries/common-arm-stm32l0/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /*STM32L051K8T6TR*/ + FLASH : ORIGIN = 0x08000000, LENGTH = 64K + RAM : ORIGIN = 0x20000000, LENGTH = 8K +} diff --git a/libraries/common-arm-stm32l0/src/lib.rs b/libraries/common-arm-stm32l0/src/lib.rs new file mode 100644 index 00000000..a27a97d5 --- /dev/null +++ b/libraries/common-arm-stm32l0/src/lib.rs @@ -0,0 +1,6 @@ +#![no_std] +#![no_main] +//! +//! This crate contains common code for HYDRA. Any code that is not board specific but is STM-32 specific should be put in +//! here. +//! diff --git a/libraries/messages/src/sender.rs b/libraries/messages/src/sender.rs index 5707f274..4318c4ad 100644 --- a/libraries/messages/src/sender.rs +++ b/libraries/messages/src/sender.rs @@ -19,6 +19,7 @@ pub enum Sender { CommunicationBoard, PowerBoard, CameraBoard, + BeaconBoard, } impl From for u16 { @@ -30,6 +31,7 @@ impl From for u16 { Sender::CommunicationBoard => 3, Sender::PowerBoard => 4, Sender::CameraBoard => 5, + Sender::BeaconBoard => 6, } } }