Write state to flash

This commit is contained in:
Mona Mayrhofer 2025-06-27 22:39:25 +02:00
parent 700bc71bf6
commit b828cc4bde
No known key found for this signature in database
GPG key ID: 3E2BDA732A957188
5 changed files with 239 additions and 53 deletions

View file

@ -1,14 +1,15 @@
[target.riscv32imc-unknown-none-elf] [target.riscv32imc-unknown-none-elf]
runner = "espflash flash --monitor --chip esp32c3" runner = "espflash flash --monitor --chip esp32c3 --partition-table ./partitions.csv"
[env] [env]
ESP_LOG="info" ESP_LOG = "info"
[build] [build]
rustflags = [ rustflags = [
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
# NOTE: May negatively impact performance of produced code # NOTE: May negatively impact performance of produced code
"-C", "force-frame-pointers", "-C",
"force-frame-pointers",
] ]
target = "riscv32imc-unknown-none-elf" target = "riscv32imc-unknown-none-elf"

168
Cargo.lock generated
View file

@ -8,6 +8,15 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
@ -111,7 +120,7 @@ dependencies = [
"embedded-io", "embedded-io",
"embedded-io-async", "embedded-io-async",
"futures-intrusive", "futures-intrusive",
"heapless", "heapless 0.8.0",
] ]
[[package]] [[package]]
@ -147,6 +156,15 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror",
]
[[package]] [[package]]
name = "critical-section" name = "critical-section"
version = "1.2.0" version = "1.2.0"
@ -266,7 +284,7 @@ dependencies = [
"embassy-time", "embassy-time",
"embedded-io-async", "embedded-io-async",
"embedded-nal-async", "embedded-nal-async",
"heapless", "heapless 0.8.0",
"managed", "managed",
"smoltcp", "smoltcp",
] ]
@ -288,7 +306,7 @@ dependencies = [
"embedded-io-async", "embedded-io-async",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"heapless", "heapless 0.8.0",
] ]
[[package]] [[package]]
@ -302,7 +320,7 @@ dependencies = [
"embedded-io-async", "embedded-io-async",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"heapless", "heapless 0.8.0",
] ]
[[package]] [[package]]
@ -338,7 +356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83"
dependencies = [ dependencies = [
"embassy-executor", "embassy-executor",
"heapless", "heapless 0.8.0",
] ]
[[package]] [[package]]
@ -487,6 +505,17 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "esp-build"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "837020ff95fbf4c15c206541dda7994f1bbe6e1505e36a6a5ecb51fdb61656d7"
dependencies = [
"quote",
"syn 2.0.104",
"termcolor",
]
[[package]] [[package]]
name = "esp-config" name = "esp-config"
version = "0.3.1" version = "0.3.1"
@ -520,10 +549,10 @@ dependencies = [
"embedded-io", "embedded-io",
"embedded-io-async", "embedded-io-async",
"enumset", "enumset",
"esp-build", "esp-build 0.2.0",
"esp-config", "esp-config",
"esp-hal-procmacros", "esp-hal-procmacros",
"esp-metadata", "esp-metadata 0.6.0",
"esp-riscv-rt", "esp-riscv-rt",
"esp32c3", "esp32c3",
"fugit", "fugit",
@ -555,11 +584,11 @@ dependencies = [
"embassy-time", "embassy-time",
"embassy-time-driver", "embassy-time-driver",
"embassy-time-queue-utils", "embassy-time-queue-utils",
"esp-build", "esp-build 0.2.0",
"esp-config", "esp-config",
"esp-hal", "esp-hal",
"esp-hal-procmacros", "esp-hal-procmacros",
"esp-metadata", "esp-metadata 0.6.0",
"portable-atomic", "portable-atomic",
"static_cell", "static_cell",
] ]
@ -592,6 +621,18 @@ dependencies = [
"strum 0.26.3", "strum 0.26.3",
] ]
[[package]]
name = "esp-metadata"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0154d59933c2419ef25a01938517cc6969f47b6af53ebb34c279393aa20d9654"
dependencies = [
"anyhow",
"basic-toml",
"serde",
"strum 0.27.1",
]
[[package]] [[package]]
name = "esp-println" name = "esp-println"
version = "0.13.1" version = "0.13.1"
@ -599,7 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960703930f9f3c899ddedd122ea27a09d6a612c22323157e524af5b18876448e" checksum = "960703930f9f3c899ddedd122ea27a09d6a612c22323157e524af5b18876448e"
dependencies = [ dependencies = [
"critical-section", "critical-section",
"esp-build", "esp-build 0.2.0",
"log", "log",
"portable-atomic", "portable-atomic",
] ]
@ -615,6 +656,19 @@ dependencies = [
"riscv-rt-macros", "riscv-rt-macros",
] ]
[[package]]
name = "esp-storage"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b6502654e5750e8162e66512d7e8d84f7eb51d17ec6aa7e0da95cd102769425"
dependencies = [
"critical-section",
"document-features",
"embedded-storage",
"esp-build 0.3.0",
"esp-metadata 0.7.0",
]
[[package]] [[package]]
name = "esp-wifi" name = "esp-wifi"
version = "0.13.0" version = "0.13.0"
@ -631,12 +685,12 @@ dependencies = [
"embedded-io-async", "embedded-io-async",
"enumset", "enumset",
"esp-alloc", "esp-alloc",
"esp-build", "esp-build 0.2.0",
"esp-config", "esp-config",
"esp-hal", "esp-hal",
"esp-metadata", "esp-metadata 0.6.0",
"esp-wifi-sys", "esp-wifi-sys",
"heapless", "heapless 0.8.0",
"libm", "libm",
"log", "log",
"num-derive", "num-derive",
@ -758,6 +812,15 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]] [[package]]
name = "hash32" name = "hash32"
version = "0.3.1" version = "0.3.1"
@ -773,13 +836,27 @@ version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32 0.2.1",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]] [[package]]
name = "heapless" name = "heapless"
version = "0.8.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [ dependencies = [
"hash32", "hash32 0.3.1",
"portable-atomic", "portable-atomic",
"stable_deref_trait", "stable_deref_trait",
] ]
@ -894,14 +971,18 @@ dependencies = [
"embassy-time", "embassy-time",
"embedded-io", "embedded-io",
"embedded-io-async", "embedded-io-async",
"embedded-storage",
"esp-alloc", "esp-alloc",
"esp-hal", "esp-hal",
"esp-hal-embassy", "esp-hal-embassy",
"esp-println", "esp-println",
"esp-storage",
"esp-wifi", "esp-wifi",
"heapless", "heapless 0.8.0",
"libm", "libm",
"log", "log",
"postcard",
"serde",
"smart-leds", "smart-leds",
"smoltcp", "smoltcp",
"static_cell", "static_cell",
@ -1015,6 +1096,17 @@ dependencies = [
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "postcard"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a"
dependencies = [
"cobs",
"heapless 0.7.17",
"serde",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.3.0" version = "3.3.0"
@ -1150,6 +1242,15 @@ dependencies = [
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.21" version = "1.0.21"
@ -1162,6 +1263,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.219" version = "1.0.219"
@ -1218,10 +1325,19 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"byteorder", "byteorder",
"cfg-if", "cfg-if",
"heapless", "heapless 0.8.0",
"managed", "managed",
] ]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@ -1318,6 +1434,26 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.23" version = "0.8.23"

View file

@ -67,6 +67,10 @@ ws2812-spi = "0.5.0"
embassy-futures = "0.1.1" embassy-futures = "0.1.1"
embassy-sync = "0.7.0" embassy-sync = "0.7.0"
libm = "0.2.15" libm = "0.2.15"
esp-storage = { version = "0.6.0", features = ["esp32c3"] }
embedded-storage = "0.3.1"
postcard = { version = "1.1.2", features = [] }
serde = { version = "1.0.219", features = ["derive"], default-features = false }
[profile.dev] [profile.dev]
# Rust debug is too slow. # Rust debug is too slow.

8
partitions.csv Normal file
View file

@ -0,0 +1,8 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
# TODO Keep in sync with main.rs APP_DATA_OFFSET
app_store,0x40, 0x01, 0x10000, 0x10000,
factory, app, factory, 0x20000, 1M,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 # TODO Keep in sync with main.rs APP_DATA_OFFSET
6 app_store,0x40, 0x01, 0x10000, 0x10000,
7 factory, app, factory, 0x20000, 1M,

View file

@ -1,29 +1,28 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use alloc::boxed::Box;
use core::ops::BitXor;
use core::ops::Rem;
use core::pin::Pin;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_futures::select::{Either, select}; use embassy_futures::select::select;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::channel::{Channel, Sender}; use embassy_sync::channel::{Channel, Sender};
use embassy_sync::mutex::Mutex; use embassy_sync::mutex::Mutex;
use embassy_sync::watch::{self, Watch}; use embassy_time::Timer;
use embassy_time::{Duration, Instant, Timer, WithTimeout}; use embedded_storage::nor_flash::NorFlash;
use embedded_storage::nor_flash::ReadNorFlash;
use esp_hal::Blocking;
use esp_hal::clock::CpuClock; use esp_hal::clock::CpuClock;
use esp_hal::gpio::{DriveMode, Input, InputConfig, Pull}; use esp_hal::gpio::{Input, InputConfig, Pull};
use esp_hal::peripherals::GPIO;
use esp_hal::rng;
use esp_hal::spi::master::{Config, Spi}; use esp_hal::spi::master::{Config, Spi};
use esp_hal::time::Rate; use esp_hal::time::Rate;
use esp_hal::timer::systimer::SystemTimer; use esp_hal::timer::systimer::SystemTimer;
use esp_hal::timer::timg::TimerGroup; use esp_hal::timer::timg::TimerGroup;
use esp_hal::{Async, Blocking, DriverMode}; use esp_storage::FlashStorage;
use libm::sin;
use log::info; use log::info;
use postcard::from_bytes;
use postcard::to_vec;
use serde::Deserialize;
use serde::Serialize;
use smart_leds::RGB8; use smart_leds::RGB8;
use smart_leds::SmartLedsWrite; use smart_leds::SmartLedsWrite;
use static_cell::StaticCell; use static_cell::StaticCell;
@ -36,17 +35,14 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
extern crate alloc; extern crate alloc;
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
struct TargetState { struct State {
enabled: [bool; 12], pub count: u8,
} }
impl Default for TargetState { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
fn default() -> Self { struct TargetState {
TargetState { enabled: [bool; 12],
enabled: [false; 12],
}
}
} }
static CHANNEL: StaticCell<Channel<NoopRawMutex, i32, 2>> = StaticCell::new(); static CHANNEL: StaticCell<Channel<NoopRawMutex, i32, 2>> = StaticCell::new();
@ -56,11 +52,12 @@ static STATE: Mutex<CriticalSectionRawMutex, TargetState> = Mutex::new(TargetSta
const ORDER: [usize; 12] = [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11]; const ORDER: [usize; 12] = [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11];
//Keep in syn with partitions.csv
const APP_DATA_OFFSET: u32 = 0x10_000;
#[esp_hal_embassy::main] #[esp_hal_embassy::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let channel = CHANNEL.init(Channel::new()); let channel = CHANNEL.init(Channel::new());
//let state_watch = STATE.init(Arc::new(Mutex::new(TargetState::default())));
// generator version: 0.3.1
esp_println::logger::init_logger_from_env(); esp_println::logger::init_logger_from_env();
@ -74,6 +71,21 @@ async fn main(spawner: Spawner) {
info!("Embassy initialized!"); info!("Embassy initialized!");
let mut flash = FlashStorage::new();
info!("Flash: {flash:?}");
let mut state = {
let mut bytes = [0; 128];
flash.read(APP_DATA_OFFSET, &mut bytes[..]).unwrap();
info!("{bytes:x?}");
if let Ok(data) = from_bytes::<State>(&bytes[..]) {
info!("Successfully restored data.");
data
} else {
State { count: 0 }
}
};
let timer1 = TimerGroup::new(peripherals.TIMG0); let timer1 = TimerGroup::new(peripherals.TIMG0);
let _init = esp_wifi::init( let _init = esp_wifi::init(
timer1.timer0, timer1.timer0,
@ -107,19 +119,36 @@ async fn main(spawner: Spawner) {
.unwrap(); .unwrap();
spawner.spawn(render_gems(led_strip)).unwrap(); spawner.spawn(render_gems(led_strip)).unwrap();
let mut state = TargetState::default();
let mut cnt = 0;
loop { loop {
let delta = channel.receive().await; // Process State
cnt = (cnt + delta).clamp(0, 12); let mut target_state = TargetState {
enabled: [false; 12],
state.enabled = [false; 12]; };
for i in (0..12) { for i in 0..12 {
state.enabled[ORDER[i]] = (cnt > i as i32); target_state.enabled[ORDER[i]] = (state.count > i as u8);
} }
{ {
let mut state_lock = STATE.lock().await; let mut state_lock = STATE.lock().await;
*state_lock = state.clone(); *state_lock = target_state.clone();
}
//Wait for updates
let delta = channel.receive().await;
state.count = state.count.saturating_add_signed(delta as i8).clamp(0, 12);
//Write Updated state
let mut d = [10u8; 128];
postcard::to_slice(&state, d.as_mut_slice()).unwrap();
info!("{d:x?}");
let r = flash.erase(APP_DATA_OFFSET, APP_DATA_OFFSET + (4 << 10));
info!("{r:?}");
let r = flash.write(APP_DATA_OFFSET, d.as_slice());
info!("{r:?}");
{
let mut bytes = [0; 128];
flash.read(APP_DATA_OFFSET, &mut bytes[..]).unwrap();
info!("Write -> Reaa: {bytes:x?}");
} }
} }
@ -161,6 +190,8 @@ async fn render_gems(
for i in (0..12) { for i in (0..12) {
if target.enabled[i] && !last_state.enabled[i] { if target.enabled[i] && !last_state.enabled[i] {
temp[i] = 3.0; temp[i] = 3.0;
} else if !target.enabled[i] && last_state.enabled[i] {
temp[i] = -1.0;
} else { } else {
let trg = if target.enabled[i] { 1.0 } else { 0.0 }; let trg = if target.enabled[i] { 1.0 } else { 0.0 };
let speed = ((temp[i] - trg).abs() * 0.2).clamp(0.1, 0.5); let speed = ((temp[i] - trg).abs() * 0.2).clamp(0.1, 0.5);
@ -196,6 +227,12 @@ async fn render_gems(
g: (50.0 + (255.0 - 50.0) * (temp - 1.0)) as u8, g: (50.0 + (255.0 - 50.0) * (temp - 1.0)) as u8,
b: (255.0 * (temp - 1.0)) as u8, b: (255.0 * (temp - 1.0)) as u8,
} }
} else if temp < 0.0 {
RGB8 {
r: 0u8,
g: (green_tint * temp.abs()) as u8,
b: (20.0 + (255.0 - 20.0) * (temp.abs())) as u8,
}
} else { } else {
RGB8 { RGB8 {
r: (255.0 * temp) as u8, r: (255.0 * temp) as u8,