From 52daa62adababb54aab1a1aceedb0723d5c68c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 17 Jul 2024 12:33:27 +0000 Subject: [PATCH] serial-settings: async platform --- Cargo.lock | 1 + serial-settings/Cargo.toml | 1 + serial-settings/src/lib.rs | 94 ++++++++++++++++++++++---------------- src/hardware/setup.rs | 8 ++-- src/settings.rs | 36 +++++++++------ 5 files changed, 83 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 429d47071..d49a3c686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1203,6 +1203,7 @@ dependencies = [ name = "serial-settings" version = "0.1.0" dependencies = [ + "embassy-futures", "embedded-io", "heapless 0.8.0", "log", diff --git a/serial-settings/Cargo.toml b/serial-settings/Cargo.toml index c081b88eb..d94274b51 100644 --- a/serial-settings/Cargo.toml +++ b/serial-settings/Cargo.toml @@ -13,3 +13,4 @@ embedded-io = "0.6" yafnv = "3.0" postcard = "1" log = { version = "0.4", features = ["max_level_trace", "release_max_level_info"] } +embassy-futures = { version = "0.1", default-features = false } diff --git a/serial-settings/src/lib.rs b/serial-settings/src/lib.rs index d4223d348..302612e97 100644 --- a/serial-settings/src/lib.rs +++ b/serial-settings/src/lib.rs @@ -47,7 +47,9 @@ //! Currently, there is a hardcoded limit of 64-bytes on the settings path. This is arbitrary and //! can be changed if needed. #![no_std] +#![allow(async_fn_in_trait)] +use embassy_futures::block_on; use embedded_io::{ErrorType, Read, ReadReady, Write}; use heapless::String; use miniconf::{JsonCoreSlash, Path, Postcard, Traversal, TreeKey}; @@ -82,14 +84,14 @@ pub trait Platform { type Settings: Settings; /// Fetch a value from persisten storage - fn fetch<'a>( + async fn fetch<'a>( &mut self, buf: &'a mut [u8], key: &[u8], ) -> Result, Self::Error>; /// Store a value to persistent storage - fn store( + async fn store( &mut self, buf: &mut [u8], key: &[u8], @@ -97,10 +99,14 @@ pub trait Platform { ) -> Result<(), Self::Error>; /// Remove a key from storage. - fn clear(&mut self, buf: &mut [u8], key: &[u8]) -> Result<(), Self::Error>; + async fn clear( + &mut self, + buf: &mut [u8], + key: &[u8], + ) -> Result<(), Self::Error>; /// Execute a platform specific command. - fn cmd(&mut self, cmd: &str); + async fn cmd(&mut self, cmd: &str); /// Return a mutable reference to the `Interface`. fn interface_mut(&mut self) -> &mut Self::Interface; @@ -121,7 +127,7 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { _settings: &mut P::Settings, ) { let key = menu::argument_finder(item, args, "cmd").unwrap().unwrap(); - interface.platform.cmd(key) + block_on(interface.platform.cmd(key)) } fn iter_root( @@ -237,14 +243,11 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { .unwrap(); // Get stored and compare - match interface.platform.fetch(interface.buffer, key.as_bytes()) - { - Err(e) => write!( - interface, - " [fetch error: {e:?}]" - ), - Ok(None) => - write!(interface, " [not stored]"), + match block_on( + interface.platform.fetch(interface.buffer, key.as_bytes()), + ) { + Err(e) => write!(interface, " [fetch error: {e:?}]"), + Ok(None) => write!(interface, " [not stored]"), Ok(Some(stored)) => { let slic = postcard::de_flavors::Slice::new(stored); // Use defaults as scratch space for postcard->json conversion @@ -253,29 +256,35 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { interface, " [stored deserialize error: {e}]" ), - Ok(_rest) => - match defaults.get_json_by_key(&key, interface.buffer) { - Err(e) => write!( - interface, - " [stored serialization error: {e}]" - ), - Ok(len) => { - if yafnv::fnv1a::(&interface.buffer[..len]) != check { + Ok(_rest) => match defaults + .get_json_by_key(&key, interface.buffer) + { + Err(e) => write!( + interface, + " [stored serialization error: {e}]" + ), + Ok(len) => { + if yafnv::fnv1a::( + &interface.buffer[..len], + ) != check + { write!( interface.platform.interface_mut(), " [stored: {}]", - core::str::from_utf8(&interface.buffer[..len]).unwrap()) - } else { - write!( - interface, - " [stored]" + core::str::from_utf8( + &interface.buffer[..len] ) - } - }, + .unwrap() + ) + } else { + write!(interface, " [stored]") + } } - } + }, + } } - }.unwrap(); + } + .unwrap(); writeln!(interface).unwrap(); }, ); @@ -363,8 +372,9 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { } // Check for stored - match interface.platform.fetch(interface.buffer, key.as_bytes()) - { + match block_on( + interface.platform.fetch(interface.buffer, key.as_bytes()), + ) { Err(e) => { writeln!( interface, @@ -375,10 +385,11 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { } Ok(None) => {} // Clear stored - Ok(Some(_stored)) => match interface - .platform - .clear(interface.buffer, key.as_bytes()) - { + Ok(Some(_stored)) => match block_on( + interface + .platform + .clear(interface.buffer, key.as_bytes()), + ) { Ok(()) => { writeln!(interface, "Clear stored `{}`", *key) } @@ -438,8 +449,9 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { }; // Get stored value checksum - match interface.platform.fetch(interface.buffer, key.as_bytes()) - { + match block_on( + interface.platform.fetch(interface.buffer, key.as_bytes()), + ) { Ok(None) => {} Ok(Some(stored)) => { let stored = yafnv::fnv1a::(stored); @@ -491,7 +503,11 @@ impl<'a, P: Platform, const Y: usize> Interface<'a, P, Y> { let (value, rest) = interface.buffer.split_at_mut(len); // Store - match interface.platform.store(rest, key.as_bytes(), value) { + match block_on(interface.platform.store( + rest, + key.as_bytes(), + value, + )) { Ok(_) => writeln!(interface, "`{}` stored", *key), Err(e) => { writeln!(interface, "Failed to store `{}`: {e:?}", *key) diff --git a/src/hardware/setup.rs b/src/hardware/setup.rs index aa9d07ddd..71404e247 100644 --- a/src/hardware/setup.rs +++ b/src/hardware/setup.rs @@ -644,9 +644,11 @@ where }; let mut settings = C::new(NetSettings::new(mac_addr)); - crate::settings::SerialSettingsPlatform::load( - &mut settings, - &mut flash, + embassy_futures::block_on( + crate::settings::SerialSettingsPlatform::load( + &mut settings, + &mut flash, + ), ); (flash, settings) }; diff --git a/src/settings.rs b/src/settings.rs index 919ac85d4..63570403a 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -24,7 +24,6 @@ //! storage sharing. use crate::hardware::{flash::Flash, metadata::ApplicationMetadata, platform}; use core::fmt::Write; -use embassy_futures::block_on; use embedded_io::Write as EioWrite; use heapless::{String, Vec}; use miniconf::{JsonCoreSlash, Path, Postcard, Tree}; @@ -34,7 +33,6 @@ use sequential_storage::{ }; use serial_settings::{BestEffortInterface, Platform, Settings}; use smoltcp_nal::smoltcp::wire::EthernetAddress; -use stm32h7xx_hal::flash::LockedFlashBank; /// Settings that are used for configuring the network interface to Stabilizer. #[derive(Clone, Debug, Tree)] @@ -117,20 +115,22 @@ impl SerialSettingsPlatform where C: for<'d> JsonCoreSlash<'d, Y>, { - pub fn load(structure: &mut C, storage: &mut Flash) { + pub async fn load(structure: &mut C, storage: &mut Flash) { // Loop over flash and read settings let mut buffer = [0u8; 512]; for path in C::nodes::, '/'>>() { let (path, _node) = path.unwrap(); // Try to fetch the setting from flash. - let value: &[u8] = match block_on(fetch_item( + let value: &[u8] = match fetch_item( storage, storage.range(), &mut NoCache::new(), &mut buffer, SettingsKey(Vec::try_from(path.as_bytes()).unwrap()), - )) { + ) + .await + { Err(e) => { log::warn!( "Failed to fetch `{}` from flash: {e:?}", @@ -168,47 +168,53 @@ where type Interface = BestEffortInterface; type Settings = C; type Error = sequential_storage::Error< - ::Error, + ::Error, >; - fn fetch<'a>( + async fn fetch<'a>( &mut self, buf: &'a mut [u8], key: &[u8], ) -> Result, Self::Error> { let range = self.storage.range(); - block_on(fetch_item( + fetch_item( &mut self.storage, range, &mut NoCache::new(), buf, SettingsKey(Vec::try_from(key).unwrap()), - )) + ) + .await .map(|v| v.filter(|v: &&[u8]| !v.is_empty())) } - fn store( + async fn store( &mut self, buf: &mut [u8], key: &[u8], value: &[u8], ) -> Result<(), Self::Error> { let range = self.storage.range(); - block_on(store_item( + store_item( &mut self.storage, range, &mut NoCache::new(), buf, SettingsKey(Vec::try_from(key).unwrap()), &value, - )) + ) + .await } - fn clear(&mut self, buf: &mut [u8], key: &[u8]) -> Result<(), Self::Error> { - self.store(buf, key, b"") + async fn clear( + &mut self, + buf: &mut [u8], + key: &[u8], + ) -> Result<(), Self::Error> { + self.store(buf, key, b"").await } - fn cmd(&mut self, cmd: &str) { + async fn cmd(&mut self, cmd: &str) { match cmd { "reboot" => cortex_m::peripheral::SCB::sys_reset(), "dfu" => platform::start_dfu_reboot(),