diff --git a/README.md b/README.md index c348ea7..a9174e1 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,11 @@ chip. It currently contains three primary crates: abstraction, and routes events from ISRs to the app. - `ui-tauri`: Code to instantiate the app in a Tauri webview +## `cortex-m-stack` + +The `cortex-m-stack` crate contains some basic tools for measuring stack usage +on STM32, leveraging the stack painting feature in the `cortex-m-rt` crate. + ## CMOX The `cmox` directory contains crates that enable the use of the STM diff --git a/ui-app/Cargo.toml b/ui-app/Cargo.toml index 4464129..360941e 100644 --- a/ui-app/Cargo.toml +++ b/ui-app/Cargo.toml @@ -9,3 +9,4 @@ defmt = { version = "1.0.1", default-features = false } embedded-graphics = "0.8.1" embedded-graphics-core = { version = "0.4.0", default-features = false } heapless = "0.9.1" +hex = { version = "0.4.3", default-features = false } diff --git a/ui-app/src/lib.rs b/ui-app/src/lib.rs index b1495f1..e6b7677 100644 --- a/ui-app/src/lib.rs +++ b/ui-app/src/lib.rs @@ -12,6 +12,7 @@ use embedded_graphics::{ text::Text, }; use heapless::String; +use hex::ToHex; #[derive(Copy, Clone, Debug, PartialEq, Format)] pub enum Key { @@ -190,10 +191,16 @@ pub trait NetTx { fn write(&mut self, to_net: &ToNet); } +pub trait Eeprom { + fn read(&mut self, data: &mut [u8; 256]); + fn write(&mut self, data: &[u8; 256]); +} + pub trait Outputs { fn status_led(&mut self) -> &mut impl Led; fn screen(&mut self) -> &mut impl DrawTarget; fn net_tx(&mut self) -> &mut impl NetTx; + fn eeprom(&mut self) -> impl Eeprom; fn log(&mut self, message: &str); } @@ -221,6 +228,20 @@ impl App { // Extinguish the status LED out.status_led().set_color(Color::Black); + // Read the EEPROM, XOR with 0xFF, write it, then read it back + let mut eeprom_data = [0u8; 256]; + out.eeprom().read(&mut eeprom_data); + let hex: heapless::String<1024> = eeprom_data.encode_hex(); + defmt::info!("eeprom before {}", hex); + + eeprom_data.iter_mut().for_each(|x| *x ^= 0xff); + out.eeprom().write(&eeprom_data); + + eeprom_data.fill(0); + out.eeprom().read(&mut eeprom_data); + let hex: heapless::String<1024> = eeprom_data.encode_hex(); + defmt::info!("eeprom after {}", hex); + // Draw a test pattern to the screen let rect = out.screen().bounding_box(); diff --git a/ui-app/tests/integration.rs b/ui-app/tests/integration.rs index 181c466..9885837 100644 --- a/ui-app/tests/integration.rs +++ b/ui-app/tests/integration.rs @@ -49,11 +49,32 @@ impl NetTx for MockNetTx { } } +struct MockEeprom { + data: [u8; 256], +} + +impl Default for MockEeprom { + fn default() -> Self { + Self { data: [0; 256] } + } +} + +impl Eeprom for &mut MockEeprom { + fn read(&mut self, data: &mut [u8; 256]) { + data.copy_from_slice(&self.data); + } + + fn write(&mut self, data: &[u8; 256]) { + self.data.copy_from_slice(data); + } +} + #[derive(Default)] struct MockOutputs { status_led: MockLed, screen: MockScreen, net_tx: MockNetTx, + eeprom: MockEeprom, last_message: String, } @@ -70,6 +91,10 @@ impl Outputs for MockOutputs { &mut self.net_tx } + fn eeprom(&mut self) -> impl Eeprom { + &mut self.eeprom + } + fn log(&mut self, message: &str) { self.last_message = message.into(); } diff --git a/ui-stm32/Cargo.toml b/ui-stm32/Cargo.toml index 62f416e..84a5b2f 100644 --- a/ui-stm32/Cargo.toml +++ b/ui-stm32/Cargo.toml @@ -21,7 +21,7 @@ defmt-rtt = "1.0.0" embassy-executor = { version = "0.8.0", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-futures = { version = "0.1.1", features = ["defmt"] } embassy-stm32 = { version = "0.3.0", features = ["defmt", "stm32f405rg", "memory-x", "time-driver-tim1", "exti", "chrono"] } -embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-time = { version = "0.5.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } panic-probe = { version = "1.0.0", features = ["print-defmt"] } embassy-sync = { version = "0.7.1", features = ["defmt"] } num_enum = { version = "0.7.4", default-features = false } @@ -34,6 +34,7 @@ display-interface = "0.5.0" embedded-graphics-core = { version = "0.4.0", default-features = false } bitmap-font = "0.3.0" embedded-graphics = "0.8.1" +embedded-hal = { version = "1.0.0", default-features = false } [profile.release] debug = 2 diff --git a/ui-stm32/src/board/ev12.rs b/ui-stm32/src/board/ev12.rs index 48f79a2..ef129d2 100644 --- a/ui-stm32/src/board/ev12.rs +++ b/ui-stm32/src/board/ev12.rs @@ -1,9 +1,10 @@ -use super::{Button, Keyboard, NetTx, StatusLed}; +use super::{Button, Eeprom, Keyboard, NetTx, StatusLed}; use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; use embassy_stm32::{ bind_interrupts, exti::ExtiInput, gpio::{Input, Level, Output, Pull, Speed}, + i2c::{mode::Master, I2c}, mode::{Async, Blocking}, peripherals, spi::{Spi, Word}, @@ -65,7 +66,8 @@ impl DisplayData { &mut self, iter: &mut dyn Iterator, ) -> Result<(), DisplayError> { - const CHUNK_SIZE: usize = 128; + // 1kb of render buffer + const CHUNK_SIZE: usize = 512; // XXX(RLB) Very C-style iteration, could probably write this in a way that would optimize // better. @@ -73,7 +75,7 @@ impl DisplayData { let mut n = 0; for (i, x) in iter.enumerate() { data[i % CHUNK_SIZE] = x; - n = i + 1; + n += 1; if n > 0 && n % CHUNK_SIZE == 0 { self.spi.blocking_write(&data).unwrap(); @@ -102,6 +104,7 @@ pub struct Board { status_led: StatusLed, screen: Ili9341>, net_tx: NetTx>, + i2c: I2c<'static, Blocking, Master>, pub button_a: Option