Skip to content

Commit

Permalink
bump embassy for static task alloc, add wheel, constify
Browse files Browse the repository at this point in the history
  • Loading branch information
jr1221 committed Sep 7, 2024
1 parent 915e26e commit 58498c7
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 31 deletions.
21 changes: 10 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[workspace]
members = ["msb-fw-rs", "cerberus", "crates/*"]
members = ["msb-fw-rs", "cerberus", "wheel", "crates/*"]
resolver = "2"

[workspace.dependencies]
embassy-stm32 = { version = "0.1.0", features = ["defmt", "stm32f405rg", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] }
embassy-stm32 = { version = "0.1.0", features = ["defmt", "stm32f405rg", "unstable-pac", "memory-x", "time", "time-driver-any", "exti"] }
embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.0", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
embassy-executor = { version = "0.6.0", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "generic-queue"] }
embassy-embedded-hal = { version = "0.2.0", features = ["defmt"] }
embassy-futures = { version = "0.1.1", features = ["defmt"] }
Expand All @@ -20,21 +20,20 @@ embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] }
embedded-io = { version = "0.6.0", features = ["defmt-03"] }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures-util = { version = "0.3.30", default-features = false }
heapless = { version = "0.8", default-features = false }
static_cell = "2.1.0"
chrono = { version = "^0.4", default-features = false}
#chrono = { version = "^0.4", default-features = false}
embedded-hal-async = {version = "1.0.0", features = ["defmt-03"] }
bitfield = "^0.13.2"


[patch.crates-io]
embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "f0a86070512ad739641cee7d9fa39d63f5c8a9f6"}
embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}
embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}
embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}
embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}
embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}
embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "1cf778904d597a5bc01a4b7862f965681636faf1"}



Expand Down
1 change: 1 addition & 0 deletions cerberus/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![feature(const_option)]
#![feature(impl_trait_in_assoc_type)]

pub mod bms;
pub mod can_handler;
Expand Down
1 change: 1 addition & 0 deletions cerberus/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![no_main]
#![feature(impl_trait_in_assoc_type)]

use core::{
fmt::Write,
Expand Down
5 changes: 4 additions & 1 deletion msb-fw-rs/src/can_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Receiver};

use crate::DeviceLocation;

const CAN_BITRATE: u32 = 500_000;


#[embassy_executor::task]
pub async fn can_handler(
mut can: Can<'static>,
recv: Receiver<'static, ThreadModeRawMutex, Frame, 25>,
loc: DeviceLocation,
) {
can.set_bitrate(500_000);
can.set_bitrate(CAN_BITRATE);
can.enable().await;

loop {
Expand Down
6 changes: 4 additions & 2 deletions msb-fw-rs/src/controllers.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use embassy_stm32::gpio::Output;
use embassy_time::Timer;
use embassy_time::{Duration, Timer};

use crate::DeviceLocation;

const LED_REFRESH_TIME: Duration = Duration::from_secs(2);

#[embassy_executor::task]
pub async fn control_leds(
mut led1: Output<'static>,
mut led2: Output<'static>,
device_loc: DeviceLocation,
) {
loop {
Timer::after_secs(2).await;
Timer::after(LED_REFRESH_TIME).await;
match device_loc {
DeviceLocation::FrontLeft => {
led1.set_high();
Expand Down
2 changes: 2 additions & 0 deletions msb-fw-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![no_std]
#![feature(impl_trait_in_assoc_type)]
#![feature(const_option)]

// declare all files in this project except main
pub mod can_handler;
Expand Down
1 change: 1 addition & 0 deletions msb-fw-rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![no_main]
#![feature(impl_trait_in_assoc_type)]

use core::fmt::Write;

Expand Down
47 changes: 31 additions & 16 deletions msb-fw-rs/src/readers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ use embassy_stm32::{
peripherals::ADC1,
};
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Sender};
use embassy_time::{Delay, Timer};
use embassy_time::{Delay, Duration, Timer};
use sht3x_ner::Repeatability;

use crate::SharedI2c3;

const TEMPERATURE_REFRESH_TIME: Duration = Duration::from_millis(500);
const TEMPERATURE_SEND_MSG_ID: StandardId = StandardId::new(0x602).expect("Could not parse ID");

#[embassy_executor::task]
pub async fn temperature_reader(
i2c: &'static SharedI2c3,
Expand All @@ -20,7 +23,7 @@ pub async fn temperature_reader(
let mut sht30 = sht3x_ner::Sht3x::new(i2c_dev, sht3x_ner::Address::High);

loop {
Timer::after_millis(500).await;
Timer::after(TEMPERATURE_REFRESH_TIME).await;
let Ok(res) = sht30
.measure(
sht3x_ner::ClockStretch::Disabled,
Expand All @@ -38,19 +41,24 @@ pub async fn temperature_reader(
bits[..2].copy_from_slice(&temp);
bits[2..].copy_from_slice(&humidity);

let frame = Frame::new_data(unwrap!(StandardId::new(0x602)), &bits)
.expect("Could not create frame");
let frame =
Frame::new_data(TEMPERATURE_SEND_MSG_ID, &bits).expect("Could not create frame");
can_send.send(frame).await;
}
}

const LSM6DSO_ADDR: u8 = 0x6A;
const IMU_REFRESH_TIME: Duration = Duration::from_millis(500);
const IMU_SEND_MSG_ID: StandardId = StandardId::new(0x603).expect("Could not parse ID");
const GYRO_SEND_MSG_ID: StandardId = StandardId::new(0x604).expect("Could not parse ID");

#[embassy_executor::task]
pub async fn imu_reader(
i2c: &'static SharedI2c3,
can_send: Sender<'static, ThreadModeRawMutex, Frame, 25>,
) {
let i2c_dev = I2cDevice::new(i2c);
let Ok(mut lsm6dso) = lsm6dso_ner::Lsm6dso::new(i2c_dev, 0x6A).await else {
let Ok(mut lsm6dso) = lsm6dso_ner::Lsm6dso::new(i2c_dev, LSM6DSO_ADDR).await else {
warn!("Could not initialize lsm6dso!");
return;
};
Expand All @@ -59,7 +67,7 @@ pub async fn imu_reader(
let mut gyro_bits: [u8; 6] = [0; 6];

loop {
Timer::after_millis(500).await;
Timer::after(IMU_REFRESH_TIME).await;
let Ok(accel) = lsm6dso.read_accelerometer().await else {
warn!("Could not read lsm6dso accel");
continue;
Expand All @@ -73,21 +81,24 @@ pub async fn imu_reader(
accel_bits[2..4].copy_from_slice(&(((accel.1 * 1000.0) as i16).to_be_bytes()));
accel_bits[4..].copy_from_slice(&(((accel.2 * 1000.0) as i16).to_be_bytes()));

let accel_frame = Frame::new_data(unwrap!(StandardId::new(0x603)), &accel_bits)
.expect("Could not create frame");
let accel_frame =
Frame::new_data(IMU_SEND_MSG_ID, &accel_bits).expect("Could not create frame");

gyro_bits[0..2].copy_from_slice(&(((gyro.0 * 1000.0) as i16).to_be_bytes()));
gyro_bits[2..4].copy_from_slice(&(((gyro.1 * 1000.0) as i16).to_be_bytes()));
gyro_bits[4..].copy_from_slice(&(((gyro.2 * 1000.0) as i16).to_be_bytes()));

let gyro_frame = Frame::new_data(unwrap!(StandardId::new(0x604)), &gyro_bits)
.expect("Could not create frame");
let gyro_frame =
Frame::new_data(GYRO_SEND_MSG_ID, &gyro_bits).expect("Could not create frame");

can_send.send(accel_frame).await;
can_send.send(gyro_frame).await;
}
}

const TOF_REFRESH_TIME: Duration = Duration::from_millis(500);
const TOF_SEND_MSG_ID: StandardId = StandardId::new(0x607).expect("Could not parse ID");

#[embassy_executor::task]
pub async fn tof_reader(
i2c: &'static SharedI2c3,
Expand All @@ -106,13 +117,17 @@ pub async fn tof_reader(
};
let range_bits = rng.to_be_bytes();
can_send
.send(unwrap!(Frame::new_standard(0x607, &range_bits)))
.send(unwrap!(Frame::new_data(TOF_SEND_MSG_ID, &range_bits)))
.await;

Timer::after_millis(500).await;
Timer::after(TOF_REFRESH_TIME).await;
}
}

const ADC_REFRESH_TIME: Duration = Duration::from_millis(250);
const STRAIN_SEND_MSG_ID: StandardId = StandardId::new(0x606).expect("Could not parse ID");
const SHOCKPOT_SEND_MSG_ID: StandardId = StandardId::new(0x605).expect("Could not parse ID");

#[embassy_executor::task]
pub async fn adc1_reader(
mut adc1: RingBufferedAdc<'static, ADC1>,
Expand All @@ -129,20 +144,20 @@ pub async fn adc1_reader(
strain_bits[0..2].copy_from_slice(&measurements[1].to_be_bytes());
strain_bits[2..4].copy_from_slice(&measurements[2].to_be_bytes());
can_send
.send(unwrap!(Frame::new_standard(
0x606,
.send(unwrap!(Frame::new_data(
STRAIN_SEND_MSG_ID,
&measurements[0].to_be_bytes()
)))
.await;
can_send
.send(unwrap!(Frame::new_standard(0x605, &strain_bits)))
.send(unwrap!(Frame::new_data(SHOCKPOT_SEND_MSG_ID, &strain_bits)))
.await;
}
Err(_) => {
warn!("DMA overrun");
continue;
}
}
Timer::after_millis(250).await;
Timer::after(ADC_REFRESH_TIME).await;
}
}
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The channel key should match the nightly rust-toolchain.toml in the embassy repo
[toolchain]
channel = "nightly-2024-07-16"
channel = "nightly-2024-09-06"
components = [ "rust-src", "rustfmt", "llvm-tools", "miri", "rust-analyzer-preview" ]
targets = [ "thumbv7em-none-eabi" ]
19 changes: 19 additions & 0 deletions wheel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
edition = "2021"
name = "wheel"
version = "0.1.0"

[dependencies]
cortex-m.workspace = true
cortex-m-rt.workspace = true
defmt.workspace = true
defmt-rtt.workspace = true
embassy-embedded-hal.workspace = true
embassy-executor.workspace = true
embassy-stm32.workspace = true
embassy-sync.workspace = true
embassy-time.workspace = true
embassy-futures.workspace = true
heapless.workspace = true
panic-probe.workspace = true
#static_cell.workspace = true
108 changes: 108 additions & 0 deletions wheel/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#![no_std]
#![no_main]
#![feature(impl_trait_in_assoc_type)]
#![feature(const_option)]

use cortex_m::peripheral::SCB;
use cortex_m_rt::{exception, ExceptionFrame};
use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_futures::select::select_array;
use embassy_stm32::{
bind_interrupts,
can::{
Can, Frame, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId,
TxInterruptHandler,
},
exti::ExtiInput,
gpio::Level,
peripherals::CAN1,
};
use embassy_stm32::{
peripherals,
usart::{self},
Config,
};
use {defmt_rtt as _, panic_probe as _};

// here are our interrupts. Embassy is interrupt by default

bind_interrupts!(struct IrqsCAN {
CAN1_RX0 => Rx0InterruptHandler<CAN1>;
CAN1_RX1 => Rx1InterruptHandler<CAN1>;
CAN1_SCE => SceInterruptHandler<CAN1>;
CAN1_TX => TxInterruptHandler<CAN1>;
});

bind_interrupts!(struct IrqsUsart {
USART2 => usart::InterruptHandler<peripherals::USART2>;
});

const SEND_MSG_ID: StandardId = StandardId::new(0x680).expect("Could not parse ID");

// main should be where the peripheral object is used, and then peripherals are init-ed and sent to the threads
// periph. obj sent to threads should not be mut, they can be edited in threads
// the loop at the end of main should be to refresh the watchdog, however main can return if needed
// put the obj used in the thread immediately before the thread instantiation
#[embassy_executor::main]
async fn main(_spawner: Spawner) -> ! {
info!("Initializing wheel...");
// initialize the project, ensure we can debug during sleep
let p = embassy_stm32::init(Config::default());

// embassy enforces pin mappings to their correct functions for the most at compile time
let mut can = Can::new(p.CAN1, p.PA11, p.PA12, IrqsCAN);
can.set_bitrate(500_000);
can.enable().await;

// let mut usart = Uart::new(
// p.USART2,
// p.PA3,
// p.PA2,
// IrqsUsart,
// p.DMA1_CH6,
// p.DMA1_CH5,
// usart::Config::default(),
// )
// .unwrap();
// let mut s: String<128> = String::new();
// core::write!(&mut s, "Hello DMA World!\r\n",).unwrap();
// unwrap!(usart.write(s.as_bytes()).await);

let mut button1 = ExtiInput::new(p.PA1, p.EXTI1, embassy_stm32::gpio::Pull::Up);
let mut button2 = ExtiInput::new(p.PA2, p.EXTI2, embassy_stm32::gpio::Pull::Up);
let mut button3 = ExtiInput::new(p.PA3, p.EXTI3, embassy_stm32::gpio::Pull::Up);
let mut button4 = ExtiInput::new(p.PA4, p.EXTI4, embassy_stm32::gpio::Pull::Up);
let mut button5 = ExtiInput::new(p.PC5, p.EXTI5, embassy_stm32::gpio::Pull::Up);
let mut button6 = ExtiInput::new(p.PC6, p.EXTI6, embassy_stm32::gpio::Pull::Up);

loop {
select_array([
button1.wait_for_falling_edge(),
button2.wait_for_falling_edge(),
button3.wait_for_falling_edge(),
button4.wait_for_falling_edge(),
button5.wait_for_falling_edge(),
button6.wait_for_falling_edge(),
])
.await;

let but1_val = (button1.get_level() == Level::Low) as u8;
let but2_val = (button2.get_level() == Level::Low) as u8;
let but3_val = (button3.get_level() == Level::Low) as u8;
let but4_val = (button4.get_level() == Level::Low) as u8;
let but5_val = (button5.get_level() == Level::Low) as u8;
let but6_val = (button6.get_level() == Level::Low) as u8;

can.write(&unwrap!(Frame::new_data(
SEND_MSG_ID,
&[but1_val, but2_val, but3_val, but4_val, but5_val, but6_val]
)))
.await;
}
}

#[exception]
unsafe fn HardFault(_frame: &ExceptionFrame) -> ! {
SCB::sys_reset() // <- you could do something other than reset
}

0 comments on commit 58498c7

Please sign in to comment.