Added node comms

This commit is contained in:
Zachary Sunforge
2024-06-22 22:49:15 -07:00
parent a95cb64941
commit 9e6acfee70
7 changed files with 66 additions and 6 deletions

View File

@ -9,7 +9,7 @@ members = [
]
[workspace.package]
version = "0.3.0"
version = "0.3.1"
edition = "2021"
repository = "https://git.bfpower.io/BFPOWER/physical"
readme = "README.md"
@ -76,6 +76,9 @@ version = "0.1.*"
[workspace.dependencies.embassy-executor]
version = "0.5.*"
features = ["defmt", "arch-cortex-m", "integrated-timers", "executor-interrupt", "executor-thread"]
[workspace.dependencies.embassy-usb]
version = "0.2.*"
features = ["defmt"]
[workspace.dependencies.embassy-stm32]
version = "0.1.*"
features = ["defmt", "unstable-pac"]

View File

@ -19,8 +19,5 @@ The main concepts of Physical are:
* Node: A node hosts peripherals. A node can have a commander but does not need one. A node can ignore or even override
commands from the commander. In a complex system, nodes are intended to be kept simple, less likely to
encounter an error than the commander, and in some cases should check for obvious problems in commands from the
commander.
* Commander: A commander hosts nodes. It is possible for a device to be both a node and a commander at the same time,
although it may not be the best idea to make such a setup. There is no concept of nesting commanders built into
Physical. If some kind of abstraction for a computer that commands multiple commanders, which command nodes, is
necessary, it should be made for that specific application.
commander. Node can also communicate with other nodes.
* Commander: A commander hosts nodes. It performs long running computations and directs nodes based on the results.

View File

@ -7,6 +7,11 @@ repository.workspace = true
readme.workspace = true
license.workspace = true
[features]
comms = []
usb = ["embassy-usb"]
stm32 = ["embassy-stm32", "physical/stm32"]
[dependencies.physical]
path = ".."
[dependencies.embedded-hal]
@ -17,3 +22,9 @@ workspace = true
workspace = true
[dependencies.uom]
workspace = true
[dependencies.embassy-stm32]
workspace = true
optional = true
[dependencies.embassy-usb]
workspace = true
optional = true

17
node/src/comms.rs Normal file
View File

@ -0,0 +1,17 @@
pub trait Sender {
async fn send(&mut self, msg: &[u8]) -> Result<(), Reset>;
}
pub trait Receiver {
async fn receive(&mut self, buffer: &mut [u8]) -> Result<(), Reset>;
}
//TODO: Replace with !
pub struct Never;
/// Communication errors indicates either:
/// Our connection was already disconnected, in which case we should reset and wait for new connection to made.
/// or
/// There was an unexpected, irrecoverable error in communication, in which case we don't want to enter a terminal error
/// safe mode, because there is no indication the actual control is broken, so all we can really do is reset the connection.
pub struct Reset;

View File

@ -1,3 +1,8 @@
#![no_std]
#[cfg(feature = "comms")]
pub mod comms;
#[cfg(feature = "stm32")]
pub mod stm32;
pub use physical::CriticalError;

2
node/src/stm32/mod.rs Normal file
View File

@ -0,0 +1,2 @@
#[cfg(feature = "usb")]
pub mod usb;

25
node/src/stm32/usb.rs Normal file
View File

@ -0,0 +1,25 @@
use crate::comms;
use embassy_stm32::peripherals::USB_OTG_FS;
use embassy_stm32::usb_otg::{Driver, Endpoint, In, Out};
use embassy_usb::driver::{EndpointIn, EndpointOut};
use embassy_usb::UsbDevice;
pub type TypedUSB = UsbDevice<'static, Driver<'static, USB_OTG_FS>>;
pub type TypedInterIn = Endpoint<'static, USB_OTG_FS, In>;
pub type TypedInterOut = Endpoint<'static, USB_OTG_FS, Out>;
impl comms::Sender for TypedInterIn {
async fn send(&mut self, msg: &[u8]) -> Result<(), comms::Reset> {
self.write(msg).await.map_err(|_| comms::Reset)
}
}
impl comms::Receiver for TypedInterOut {
async fn receive(&mut self, buffer: &mut [u8]) -> Result<(), comms::Reset> {
// This should be OK because all our messages are smaller than a single packet.
self.read(buffer)
.await
.map(|_| ())
.map_err(|_| comms::Reset)
}
}