Changed to a cargo workspace

Added postcard protocol definitions
This commit is contained in:
Sebastian 2023-12-20 16:24:36 +01:00
parent 2cc6651aca
commit 833e4d5a56
8 changed files with 186 additions and 100 deletions

View File

@ -1,19 +0,0 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# TODO(2) replace `$CHIP` with your chip's name (see `probe-run --list-chips` output)
runner = "probe-run --chip STM32F103CB"
rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C", "link-arg=--nmagic",
]
[build]
target = "thumbv7m-none-eabi" # Cortex-M3
[alias]
rb = "run --bin"
rrb = "run --release --bin"

View File

@ -1,61 +1,8 @@
[package]
# TODO(1) fix `authors` and `name` if you didn't use `cargo-generate`
authors = ["sebastian <sebastian@sebastians-site.de>"]
name = "cheapsdp"
edition = "2018"
version = "0.1.0"
[workspace]
resolver = "2"
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
defmt = { version = "0.3", features = ["encoding-rzcobs"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
rtic = { version = "2.0.1", features = [ "thumbv7-backend" ] }
defmt-rtt = "0.4"
embedded-hal = "0.2.3"
stm32f1xx-hal = { version = "0.10.0", features = ["stm32f103", "rt", "medium"] }
nb = "1.0.0"
arrayvec = { version = "0.7.0", default-features = false }
systick-monotonic = "1.0.0"
rtic-monotonics = {version = "1.4.1", features = ["cortex-m-systick"] }
usb-device = "0.2.8"
usbd-serial = "0.1.1"
rtic-sync = {version = "1.1.1"}
ufmt = "0.2.0"
members = [
"firmware", "protocol",
]
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 'z' # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,50 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# TODO(2) replace `$CHIP` with your chip's name (see `probe-run --list-chips` output)
runner = "probe-run --chip STM32F103CB"
rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C", "link-arg=--nmagic",
]
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 'z' # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

27
firmware/Cargo.toml Normal file
View File

@ -0,0 +1,27 @@
cargo-features = ["per-package-target"]
[package]
# TODO(1) fix `authors` and `name` if you didn't use `cargo-generate`
authors = ["sebastian <sebastian@sebastians-site.de>"]
name = "cheapsdo-firmware"
edition = "2021"
version = "0.1.0"
default-target = "thumbv7m-none-eabi" # Cortex-M3
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
defmt = { version = "0.3", features = ["encoding-rzcobs"] }
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
rtic = { version = "2.0.1", features = [ "thumbv7-backend" ] }
defmt-rtt = "0.4"
embedded-hal = "0.2.3"
stm32f1xx-hal = { version = "0.10.0", features = ["stm32f103", "rt", "medium"] }
nb = "1.0.0"
systick-monotonic = "1.0.0"
rtic-monotonics = {version = "1.4.1", features = ["cortex-m-systick"] }
usb-device = "0.2.8"
usbd-serial = "0.1.1"
cheapsdo-protocol = { path = "../protocol" }
postcard = {version = "1.0.8", features = ["use-defmt"]}
heapless = {version = "0.8.0", features = ["defmt-03"]}

View File

@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(slice_split_once)]
use defmt_rtt as _; // global logger
use panic_probe as _;
@ -18,10 +19,7 @@ use rtic::app;
#[app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI3])]
mod app {
use core::fmt::Write;
use cortex_m::asm::delay;
use embedded_hal::digital::v2::OutputPin;
use rtic_monotonics::systick::*;
use stm32f1xx_hal::{
@ -37,6 +35,13 @@ mod app {
use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
use usb_device::prelude::*;
use heapless::Vec;
use postcard::{from_bytes_cobs, to_vec_cobs};
use cheapsdo_protocol::{*, DeviceMessage};
const USB_BUFFER_SIZE : usize = 64;
#[local]
struct Local {
board_led: gpioc::PC13<Output<PushPull>>,
@ -51,6 +56,7 @@ mod app {
serial: usbd_serial::SerialPort<'static, UsbBusType>,
current_freq: f64,
short_avg: f64,
buffer: Vec<u8, USB_BUFFER_SIZE>,
}
const TARGET_FREQ: f64 = 10.0f64;
@ -193,7 +199,6 @@ mod app {
.device_class(usbd_serial::USB_CLASS_CDC)
.build();
update_pwm::spawn().unwrap();
(
@ -202,6 +207,7 @@ mod app {
usb_dev,
current_freq: 0.0f64,
short_avg: 0.0f64,
buffer: Vec::new(),
},
Local {
board_led,
@ -212,6 +218,7 @@ mod app {
)
}
const WINDOW_LEN: usize = 100;
#[task(local=[tim2, tim3, pwm, board_led], shared=[current_freq, short_avg])]
@ -287,7 +294,6 @@ mod app {
*avg = short_avg;
});
let diff = (TARGET_FREQ - short_avg) * 1_000_000.0;
if diff > 1.0 || diff < -1.0 {
cur_pwm += diff as i32 * 15;
@ -307,52 +313,97 @@ mod app {
}
}
#[task(binds = USB_HP_CAN_TX, shared = [usb_dev, serial, current_freq, short_avg])]
#[task(binds = USB_HP_CAN_TX, shared = [usb_dev, serial, buffer, current_freq, short_avg])]
fn usb_tx(cx: usb_tx::Context) {
let mut usb_dev = cx.shared.usb_dev;
let mut serial = cx.shared.serial;
let mut buffer = cx.shared.buffer;
let mut current_freq = cx.shared.current_freq;
let mut short_avg = cx.shared.short_avg;
(&mut usb_dev, &mut serial, &mut current_freq, &mut short_avg).lock(|usb_dev, serial, current_freq, short_avg| {
usb_poll(usb_dev, serial, current_freq, short_avg);
});
(
&mut usb_dev,
&mut serial,
&mut buffer,
&mut current_freq,
&mut short_avg,
)
.lock(|usb_dev, serial, buffer, current_freq, short_avg| {
usb_poll(usb_dev, serial, buffer, current_freq, short_avg);
});
}
#[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, serial, current_freq, short_avg])]
#[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, serial, buffer, current_freq, short_avg])]
fn usb_rx0(cx: usb_rx0::Context) {
let mut usb_dev = cx.shared.usb_dev;
let mut serial = cx.shared.serial;
let mut buffer = cx.shared.buffer;
let mut current_freq = cx.shared.current_freq;
let mut short_avg = cx.shared.short_avg;
(&mut usb_dev, &mut serial, &mut current_freq, &mut short_avg).lock(|usb_dev, serial, current_freq, short_avg| {
usb_poll(usb_dev, serial, current_freq, short_avg);
});
(
&mut usb_dev,
&mut serial,
&mut buffer,
&mut current_freq,
&mut short_avg,
)
.lock(|usb_dev, serial, buffer, current_freq, short_avg| {
usb_poll(usb_dev, serial, buffer, current_freq, short_avg);
});
}
fn usb_poll<B: usb_device::bus::UsbBus>(
usb_dev: &mut usb_device::prelude::UsbDevice<'static, B>,
serial: &mut usbd_serial::SerialPort<'static, B>,
current_freq: &mut f64,
buffer: &mut Vec<u8, USB_BUFFER_SIZE>,
current_freq: &mut f64,
short_avg: &mut f64,
) {
if !usb_dev.poll(&mut [serial]) {
return;
}
let mut buf = [0u8; 8];
match serial.read(&mut buf) {
let mut tmp = [0u8; 16];
match serial.read(&mut tmp) {
Ok(count) if count > 0 => {
if buf[0] == b'?' {
let mut data = arrayvec::ArrayString::<32>::new();
write!(data, "{}|{}\n\r", current_freq, short_avg).unwrap();
serial.write(data.as_bytes()).unwrap();
};
if buffer.extend_from_slice(&tmp[0..count]).is_err() {
buffer.clear();
defmt::error!("Buffer overflow while waiting for the end of the packet");
}
}
_ => {}
}
loop {
if let Some((msg, rest)) = buffer.split_once(|&x| x == 0) {
let mut message = [0u8; 128];
message.clone_from_slice(msg);
let host_msg = from_bytes_cobs::<HostMessage>(&mut message);
match host_msg {
Ok(host_msg) => match host_msg {
HostMessage::RequestStatus => {
let device_msg = DeviceMessage::Status(StatusMessage{
measured_frequency: *current_freq,
average_frequency: *short_avg,
pwm: 0,
});
let bytes = to_vec_cobs::<DeviceMessage, USB_BUFFER_SIZE>(&device_msg).unwrap();
serial.write(bytes.as_slice()).unwrap();
},
HostMessage::SetPLLOutputs => {
defmt::error!("PLL output is not implemented yet")
}
}
Err(err) => defmt::error!("Unable to parse host message: {}", err),
};
*buffer = Vec::<u8, USB_BUFFER_SIZE>::from_slice(rest).unwrap();
} else {
break;
}
}
}
}

9
protocol/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "cheapsdo-protocol"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = {version = "1.0.193", default-features = false, features = ["derive"]}

21
protocol/src/lib.rs Normal file
View File

@ -0,0 +1,21 @@
#![no_std]
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub enum DeviceMessage {
Status(StatusMessage),
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub enum HostMessage {
RequestStatus,
SetPLLOutputs,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct StatusMessage {
pub measured_frequency: f64,
pub average_frequency: f64,
pub pwm: u16,
}