Skip to content

Commit

Permalink
Use flash-backed config
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-summers committed Nov 10, 2023
1 parent 41ba825 commit f4b312f
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 66 deletions.
5 changes: 3 additions & 2 deletions src/bin/dual-iir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ mod app {
let clock = SystemTimer::new(|| monotonics::now().ticks() as u32);

// Configure the microcontroller
let (stabilizer, _pounder) = hardware::setup::setup(
let (mut stabilizer, _pounder) = hardware::setup::setup(
c.core,
c.device,
clock,
Expand All @@ -222,7 +222,8 @@ mod app {
clock,
env!("CARGO_BIN_NAME"),
stabilizer.net.mac_address,
option_env!("BROKER").unwrap_or("mqtt"),
stabilizer.usb_serial.flash().fetch_item("broker"),
stabilizer.usb_serial.flash().fetch_item("id"),
);

let generator = network.configure_streaming(StreamFormat::AdcDacData);
Expand Down
3 changes: 2 additions & 1 deletion src/bin/lockin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ mod app {
clock,
env!("CARGO_BIN_NAME"),
stabilizer.net.mac_address,
option_env!("BROKER").unwrap_or("mqtt"),
stabilizer.usb_serial.flash().fetch_item("broker"),
stabilizer.usb_serial.flash().fetch_item("id"),
);

let generator = network.configure_streaming(StreamFormat::AdcDacData);
Expand Down
62 changes: 46 additions & 16 deletions src/hardware/flash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use stm32h7xx_hal::flash::{UnlockedFlashBank, LockedFlashBank};
use embedded_storage::nor_flash::NorFlash;
use stm32h7xx_hal::flash::{LockedFlashBank, UnlockedFlashBank};
#[derive(Debug)]
pub enum StorageError {
JsonDe(serde_json_core::de::Error),
Expand All @@ -22,11 +22,21 @@ impl sequential_storage::map::StorageItemError for StorageError {
fn is_buffer_too_small(&self) -> bool {
match self {
Self::JsonSer(serde_json_core::ser::Error::BufferFull) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingString) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingList) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingObject) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingNumber) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingValue) => true,
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingString) => {
true
}
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingList) => {
true
}
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingObject) => {
true
}
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingNumber) => {
true
}
Self::JsonDe(serde_json_core::de::Error::EofWhileParsingValue) => {
true
}
_ => false,
}
}
Expand All @@ -40,22 +50,27 @@ macro_rules! storage_item {
type Key = &'static str;
type Error = StorageError;

fn serialize_into(&self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
fn serialize_into(
&self,
buffer: &mut [u8],
) -> Result<usize, Self::Error> {
Ok(serde_json_core::to_slice(&self.0, buffer)?)
}

fn deserialize_from(buffer: &[u8]) -> Result<(Self, usize), Self::Error> {
Ok(serde_json_core::from_slice(buffer).map(|(item, size)| (Self(item), size))?)
fn deserialize_from(
buffer: &[u8],
) -> Result<(Self, usize), Self::Error> {
Ok(serde_json_core::from_slice(buffer)
.map(|(item, size)| (Self(item), size))?)
}

fn key(&self) -> Self::Key {
$key
}
}
}
};
}


storage_item!(23, "id", MqttIdentifier);
storage_item!(255, "broker", BrokerAddress);

Expand All @@ -68,15 +83,30 @@ impl FlashSettings {
Self { flash }
}

pub fn store_item(&mut self, item: impl sequential_storage::map::StorageItem) {
pub fn store_item(
&mut self,
item: impl sequential_storage::map::StorageItem,
) {
let mut bank = self.flash.unlocked();
let range = (bank.address() as u32)..((bank.address() + bank.len()) as u32);
sequential_storage::map::store_item::<_, _, { <UnlockedFlashBank as NorFlash>::ERASE_SIZE } >(&mut bank, range, item).unwrap();
let range =
(bank.address() as u32)..((bank.address() + bank.len()) as u32);
sequential_storage::map::store_item::<
_,
_,
{ <UnlockedFlashBank as NorFlash>::ERASE_SIZE },
>(&mut bank, range, item)
.unwrap();
}

pub fn fetch_item<I: sequential_storage::map::StorageItem<Key=&'static str>>(&mut self, key: &'static str) -> Option<I> {
pub fn fetch_item<
I: sequential_storage::map::StorageItem<Key = &'static str>,
>(
&mut self,
key: &'static str,
) -> Option<I> {
let mut bank = self.flash.unlocked();
let range = (bank.address() as u32)..((bank.address() + bank.len()) as u32);
let range =
(bank.address() as u32)..((bank.address() + bank.len()) as u32);
sequential_storage::map::fetch_item(&mut bank, range, key).unwrap()
}
}
2 changes: 1 addition & 1 deletion src/hardware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ pub mod cpu_temp_sensor;
pub mod dac;
pub mod delay;
pub mod design_parameters;
pub mod flash;
pub mod input_stamper;
pub mod pounder;
pub mod serial_terminal;
pub mod setup;
pub mod shared_adc;
pub mod signal_generator;
pub mod timers;
pub mod flash;

mod eeprom;

Expand Down
44 changes: 33 additions & 11 deletions src/hardware/serial_terminal.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::UsbBus;
use crate::hardware::flash::{BrokerAddress, FlashSettings, MqttIdentifier};
use core::fmt::Write;
use crate::hardware::flash::{MqttIdentifier, BrokerAddress, FlashSettings};

struct Context {
output: OutputBuffer,
Expand Down Expand Up @@ -91,7 +91,9 @@ fn handle_property_read(
args: &[&str],
context: &mut Context,
) {
let props: heapless::Vec<&'_ str, 2> = if let Some(prop) = menu::argument_finder(item, args, "property").unwrap() {
let props: heapless::Vec<&'_ str, 2> = if let Some(prop) =
menu::argument_finder(item, args, "property").unwrap()
{
heapless::Vec::from_slice(&[prop]).unwrap()
} else {
heapless::Vec::from_slice(&["id", "broker"]).unwrap()
Expand All @@ -101,12 +103,20 @@ fn handle_property_read(
write!(&mut context.output, "{prop}: ").unwrap();
match prop {
"id" => {
let value = context.flash.fetch_item::<MqttIdentifier>("mqtt-id").unwrap().0;
let value = context
.flash
.fetch_item::<MqttIdentifier>("mqtt-id")
.map(|inner| inner.0)
.unwrap_or_else(|| "<unset>".into());
writeln!(&mut context.output, "{value}").unwrap();
}

"broker" => {
let value = context.flash.fetch_item::<BrokerAddress>("broker").unwrap().0;
let value = context
.flash
.fetch_item::<BrokerAddress>("broker")
.map(|inner| inner.0)
.unwrap_or_else(|| "mqtt".into());
writeln!(&mut context.output, "{value}").unwrap();
}

Expand All @@ -132,8 +142,12 @@ fn handle_property_write(
// Now, write the new value into memory.
// TODO: Validate it first?
match property {
"id" => context.flash.store_item(MqttIdentifier(heapless::String::from(value))),
"broker" => context.flash.store_item(BrokerAddress(heapless::String::from(value))),
"id" => context
.flash
.store_item(MqttIdentifier(heapless::String::from(value))),
"broker" => context
.flash
.store_item(BrokerAddress(heapless::String::from(value))),
other => {
writeln!(&mut context.output, "Unknown property: {other}").unwrap();
return;
Expand Down Expand Up @@ -163,7 +177,8 @@ impl SerialTerminal {
) -> Self {
let (producer, consumer) = OUTPUT_BUFFER.try_split().unwrap();

let input_buffer = cortex_m::singleton!(: [u8; 255] = [0; 255]).unwrap();
let input_buffer =
cortex_m::singleton!(: [u8; 255] = [0; 255]).unwrap();
let context = Context {
output: OutputBuffer { producer },
flash,
Expand All @@ -176,6 +191,10 @@ impl SerialTerminal {
}
}

pub fn flash(&mut self) -> &mut FlashSettings {
&mut self.menu.context.flash
}

fn flush(&mut self) {
let read = match self.output.read() {
Ok(grant) => grant,
Expand Down Expand Up @@ -215,10 +234,13 @@ impl SerialTerminal {
Err(usbd_serial::UsbError::WouldBlock) => {}
Err(_) => {
self.menu.prompt(true);
self.output.read().map(|grant| {
let len = grant.buf().len();
grant.release(len);
}).ok();
self.output
.read()
.map(|grant| {
let len = grant.buf().len();
grant.release(len);
})
.ok();
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/hardware/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ use smoltcp_nal::smoltcp;

use super::{
adc, afe, cpu_temp_sensor::CpuTempSensor, dac, delay, design_parameters,
eeprom, input_stamper::InputStamper, pounder,
eeprom, flash::FlashSettings, input_stamper::InputStamper, pounder,
pounder::dds_output::DdsOutput, serial_terminal::SerialTerminal,
shared_adc::SharedAdc, timers, DigitalInput0, DigitalInput1,
EemDigitalInput0, EemDigitalInput1, EemDigitalOutput0, EemDigitalOutput1,
EthernetPhy, NetworkStack, SystemTimer, Systick, UsbBus, AFE0, AFE1,
flash::FlashSettings,
};

const NUM_TCP_SOCKETS: usize = 4;
Expand Down Expand Up @@ -1062,7 +1061,11 @@ pub fn setup(
usb_bus.as_ref().unwrap(),
usb_device::device::UsbVidPid(0x1209, 0x392F),
)
.strings(&[usb_device::device::StringDescriptors::default().manufacturer("ARTIQ/Sinara").product("Stabilizer").serial_number(serial_number.as_ref().unwrap())]).unwrap()
.strings(&[usb_device::device::StringDescriptors::default()
.manufacturer("ARTIQ/Sinara")
.product("Stabilizer")
.serial_number(serial_number.as_ref().unwrap())])
.unwrap()
.device_class(usbd_serial::USB_CLASS_CDC)
.build();

Expand Down
56 changes: 24 additions & 32 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ pub mod data_stream;
pub mod network_processor;
pub mod telemetry;

use crate::hardware::{EthernetPhy, NetworkManager, NetworkStack, SystemTimer};
use crate::hardware::{
flash::{BrokerAddress, MqttIdentifier},
EthernetPhy, NetworkManager, NetworkStack, SystemTimer,
};
use data_stream::{DataStream, FrameGenerator};
use network_processor::NetworkProcessor;
use telemetry::TelemetryClient;
Expand Down Expand Up @@ -95,23 +98,34 @@ where
clock: SystemTimer,
app: &str,
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
broker: &str,
broker: Option<BrokerAddress>,
id: Option<MqttIdentifier>,
) -> Self {
let stack_manager =
cortex_m::singleton!(: NetworkManager = NetworkManager::new(stack))
.unwrap();

let id = if let Some(id) = id {
id.0
} else {
let mut id: String<23> = String::new();
write!(&mut id, "{mac}").unwrap();
id
};

let broker = broker.map(|b| b.0).unwrap_or_else(|| "mqtt".into());

let processor =
NetworkProcessor::new(stack_manager.acquire_stack(), phy);

let prefix = get_device_prefix(app, mac);
let prefix = get_device_prefix(app, &id);

let store =
cortex_m::singleton!(: MqttStorage = MqttStorage::default())
.unwrap();

let named_broker = miniconf::minimq::broker::NamedBroker::new(
broker,
&broker,
stack_manager.acquire_stack(),
)
.unwrap();
Expand All @@ -124,13 +138,13 @@ where
named_broker,
&mut store.settings,
)
.client_id(&get_client_id(app, "settings", mac))
.client_id(&id)
.unwrap(),
)
.unwrap();

let named_broker = minimq::broker::NamedBroker::new(
broker,
&broker,
stack_manager.acquire_stack(),
)
.unwrap();
Expand All @@ -141,7 +155,7 @@ where
// The telemetry client doesn't receive any messages except MQTT control packets.
// As such, we don't need much of the buffer for RX.
.rx_buffer(minimq::config::BufferConfig::Maximum(100))
.client_id(&get_client_id(app, "tlm", mac))
.client_id(&id)
.unwrap(),
);

Expand Down Expand Up @@ -215,41 +229,19 @@ where
}
}

/// Get an MQTT client ID for a client.
///
/// # Args
/// * `app` - The name of the application
/// * `client` - The unique tag of the client
/// * `mac` - The MAC address of the device.
///
/// # Returns
/// A client ID that may be used for MQTT client identification.
fn get_client_id(
app: &str,
client: &str,
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
) -> String<64> {
let mut identifier = String::new();
write!(&mut identifier, "{app}-{mac}-{client}").unwrap();
identifier
}

/// Get the MQTT prefix of a device.
///
/// # Args
/// * `app` - The name of the application that is executing.
/// * `mac` - The ethernet MAC address of the device.
/// * `id` - The MQTT ID of the device.
///
/// # Returns
/// The MQTT prefix used for this device.
pub fn get_device_prefix(
app: &str,
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
) -> String<128> {
pub fn get_device_prefix(app: &str, id: &str) -> String<128> {
// Note(unwrap): The mac address + binary name must be short enough to fit into this string. If
// they are defined too long, this will panic and the device will fail to boot.
let mut prefix: String<128> = String::new();
write!(&mut prefix, "dt/sinara/{app}/{mac}").unwrap();
write!(&mut prefix, "dt/sinara/{app}/{id}").unwrap();

prefix
}

0 comments on commit f4b312f

Please sign in to comment.