diff --git a/firmware/.cargo/config.toml b/firmware/.cargo/config.toml index a377130..2b80217 100644 --- a/firmware/.cargo/config.toml +++ b/firmware/.cargo/config.toml @@ -1,8 +1,12 @@ [target.thumbv7em-none-eabihf] runner = 'probe-rs run --chip STM32F411CEUx' +rustflags = ["-Clinker-plugin-lto"] [build] target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug" + +[unstable] +build-std = ["compiler_builtins", "core"] diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index af6d617..6eeecd3 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -769,7 +769,6 @@ dependencies = [ "base64", "cortex-m", "cortex-m-rt", - "critical-section", "defmt 1.0.1", "defmt-rtt", "embassy-executor", @@ -781,6 +780,7 @@ dependencies = [ "embedded-graphics", "embedded-hal-bus", "epd-waveshare", + "panic-abort", "panic-probe", "postcard", "serde", @@ -844,6 +844,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "panic-abort" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e20e6499bbbc412f280b04a42346b356c6fa0753d5fd22b7bd752ff34c778ee" + [[package]] name = "panic-probe" version = "1.0.0" diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index eaffa71..6f26520 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -10,7 +10,6 @@ cortex-m = { version = "0.7.7", features = [ "critical-section-single-core", ] } cortex-m-rt = "0.7.5" -critical-section = "1.2.0" defmt = "1.0.1" defmt-rtt = "1.1.0" embassy-executor = { version = "0.9.1", features = [ @@ -38,6 +37,7 @@ embassy-usb = { version = "0.5.1", features = ["defmt"] } embedded-graphics = { version = "0.8.1", features = ["defmt"] } embedded-hal-bus = { version = "0.3.0", features = ["async"] } epd-waveshare = "0.6.0" +panic-abort = "0.3.2" panic-probe = { version = "1.0.0", features = ["print-defmt"] } postcard = { version = "1.1.3", features = ["defmt"] } serde = { version = "1.0.228", default-features = false, features = ["derive"] } @@ -45,6 +45,8 @@ static_cell = "2.1.1" [profile.dev] opt-level = "s" +lto = "fat" [profile.release] -opt-level = "s" +opt-level = "z" +lto = "fat" diff --git a/firmware/src/app.rs b/firmware/src/app.rs index c082f90..0eeef35 100644 --- a/firmware/src/app.rs +++ b/firmware/src/app.rs @@ -140,7 +140,7 @@ impl App { async fn handle_get_identification(&mut self) { self.write_response(Response::GetIdentification { - serial: uid_base64(), + serial: uid_base64().await, model: DeviceType::BWRev1, }) .await; diff --git a/firmware/src/main.rs b/firmware/src/main.rs index e0a3305..951796f 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -6,6 +6,7 @@ use crate::{ epd::Epd, midi::{make_midi_class, make_usb_builder, usb_task}, }; + use defmt_rtt as _; use embassy_executor::{Spawner, main}; use embassy_stm32::{ @@ -14,6 +15,9 @@ use embassy_stm32::{ time::Hertz, usb::{self}, }; +#[cfg(not(debug_assertions))] +use panic_abort as _; +#[cfg(debug_assertions)] use panic_probe as _; macro_rules! static_ref { @@ -68,7 +72,7 @@ async fn main(spawner: Spawner) { peri.SPI1, peri.PA4, peri.PA5, peri.PA7, peri.PB10, peri.PB0, peri.PB1, ); - let mut usb_builder = make_usb_builder(peri.USB_OTG_FS, peri.PA12, peri.PA11); + let mut usb_builder = make_usb_builder(peri.USB_OTG_FS, peri.PA12, peri.PA11).await; let midi = make_midi_class(&mut usb_builder); spawner.must_spawn(usb_task(usb_builder)); diff --git a/firmware/src/midi.rs b/firmware/src/midi.rs index 3cab2bc..b22237c 100644 --- a/firmware/src/midi.rs +++ b/firmware/src/midi.rs @@ -1,4 +1,3 @@ -use defmt_rtt as _; use embassy_executor::task; use embassy_stm32::{ Peri, @@ -6,7 +5,6 @@ use embassy_stm32::{ usb::{self, DmPin, DpPin}, }; use embassy_usb::{UsbVersion, class::midi::MidiClass}; -use panic_probe as _; use static_cell::StaticCell; use crate::{Irqs, uid}; @@ -15,19 +13,19 @@ pub type UsbDriver = usb::Driver<'static, USB_OTG_FS>; pub type UsbBuilder = embassy_usb::Builder<'static, UsbDriver>; pub type UsbMidi = MidiClass<'static, UsbDriver>; -pub fn make_usb_builder( +pub async fn make_usb_builder( peri: Peri<'static, USB_OTG_FS>, dp: Peri<'static, impl DpPin>, dm: Peri<'static, impl DmPin>, ) -> UsbBuilder { - let ep_out_buffer = static_ref!([u8; 4096] = [0; 4096]); + let ep_out_buffer = static_ref!([u8; 256] = [0; 256]); let config_descriptor = static_ref!([u8; 256] = [0; 256]); let control_buf = static_ref!([u8; 256] = [0; 256]); let mut config = embassy_usb::Config::new(0x1209, 0xc9c9); config.manufacturer = Some("Project Daylily"); config.product = Some("Inkclip BW"); - config.serial_number = Some(uid::uid_base64()); + config.serial_number = Some(uid::uid_base64().await); config.bcd_usb = UsbVersion::Two; let usb_driver = usb::Driver::new_fs(peri, Irqs, dp, dm, ep_out_buffer, usb::Config::default()); diff --git a/firmware/src/uid.rs b/firmware/src/uid.rs index 3d38c31..5c541a0 100644 --- a/firmware/src/uid.rs +++ b/firmware/src/uid.rs @@ -1,20 +1,18 @@ use base64::prelude::*; use embassy_stm32::uid::uid; +use embassy_sync::once_lock::OnceLock; -pub fn uid_base64() -> &'static str { - unsafe { core::str::from_utf8_unchecked(uid_base64_bytes()) } +pub async fn uid_base64() -> &'static str { + unsafe { core::str::from_utf8_unchecked(uid_base64_bytes().await) } } -#[allow(static_mut_refs)] -pub fn uid_base64_bytes() -> &'static [u8; 16] { - static mut UID_BASE64: [u8; 16] = [0; 16]; - static mut LOADED: bool = false; - critical_section::with(|_| unsafe { - if !LOADED { - let uid = uid(); - BASE64_STANDARD.encode_slice(uid, &mut UID_BASE64).unwrap(); - LOADED = true; - } - }); - unsafe { &*core::ptr::addr_of!(UID_BASE64) } +pub async fn uid_base64_bytes() -> &'static [u8; 16] { + static UID_BASE64: OnceLock<[u8; 16]> = OnceLock::new(); + UID_BASE64.get_or_init(|| { + let mut b64 = [0u8; 16]; + BASE64_STANDARD + .encode_slice(uid(), &mut b64) + .expect("12-byte UID encoded to 16 bytes of base64"); + b64 + }) }