From 81a238ab55fd124e571e1a920efa1ee03680f231 Mon Sep 17 00:00:00 2001 From: ede1998 Date: Sat, 29 Aug 2026 15:44:33 +0200 Subject: [PATCH] Recover from init fail --- src/bin/main.rs | 59 ++++++++++++++++++++++++++----------- src/drivers/i2c_bus.rs | 20 ++++++------- src/drivers/spi_bus.rs | 4 +-- src/drivers/tertiary_lcd.rs | 10 +++---- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index a1a26b8..724a93a 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -64,32 +64,40 @@ async fn main(spawner: Spawner) { let timg0 = TimerGroup::new(peripherals.TIMG0); esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0); - let (primary, mut secondaries) = spi_bus::DisplayPinConfiguration { - spi_peripheral: peripherals.SPI2, - sck: peripherals.GPIO36, - mosi: peripherals.GPIO35, - miso: peripherals.GPIO37, - cs_primary: peripherals.GPIO11, - cs_secondary_1: peripherals.GPIO13, - cs_secondary_2: peripherals.GPIO14, - cs_secondary_3: peripherals.GPIO21, - reset_primary: peripherals.GPIO10, - reset_secondary: peripherals.GPIO47, - dc_pin: peripherals.GPIO12, - } - .build(); + let (primary, mut secondaries) = retry( + 5, + spi_bus::DisplayPinConfiguration { + spi_peripheral: peripherals.SPI2, + sck: peripherals.GPIO36, + mosi: peripherals.GPIO35, + miso: peripherals.GPIO37, + cs_primary: peripherals.GPIO11, + cs_secondary_1: peripherals.GPIO13, + cs_secondary_2: peripherals.GPIO14, + cs_secondary_3: peripherals.GPIO21, + reset_primary: peripherals.GPIO10, + reset_secondary: peripherals.GPIO47, + dc_pin: peripherals.GPIO12, + }, + spi_bus::DisplayPinConfiguration::build, + ); // Initialize the shared I2C bus using the refactored i2c_bus module. let shared_i2c = { - let config = I2cBusPinConfiguration { + use alloc::boxed::Box; + let bus = retry(5, I2cBusPinConfiguration { i2c_peripheral: peripherals.I2C0, scl: peripherals.GPIO18, sda: peripherals.GPIO17, - }; - config.build() + }, I2cBusPinConfiguration::build); + Box::leak(Box::new(bus)) }; - let mut lcd: TertiaryDisplay = TertiaryDisplayPinConfiguration { i2c: shared_i2c }.build(); + let mut lcd: TertiaryDisplay = retry( + 5, + TertiaryDisplayPinConfiguration { i2c: shared_i2c }, + TertiaryDisplayPinConfiguration::build, + ); lcd.load_charset(EXAMPLE).unwrap(); let h = EXAMPLE[HEART]; let e = EXAMPLE[EMPTY]; @@ -140,6 +148,7 @@ async fn main(spawner: Spawner) { log::info!("Setup complete, entering main loop"); spawner.spawn(navigation::run(inputs, outputs).expect("run task failed")); spawner.spawn(background_tasks::nfc_scanner(nfc_driver).expect("nfc scanner task failed")); + core::future::pending::<()>().await } fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { @@ -151,3 +160,17 @@ fn display_shit(oled: &mut SecondaryDisplay<'static>, text: &str) { .unwrap(); oled.flush().unwrap(); } + +fn retry Result>(repetitions: u32, input: T, mut action: F) -> U { + let mut initial_state = input; + for iteration in 0..repetitions { + log::debug!("Trying to initialize. Retries: {iteration}"); + + match action(initial_state) { + Ok(success) => return success, + Err(recovered_input) => initial_state = recovered_input, + } + } + + panic!("Init failed after {repetitions} retries.") +} diff --git a/src/drivers/i2c_bus.rs b/src/drivers/i2c_bus.rs index 23500ed..db4bec2 100644 --- a/src/drivers/i2c_bus.rs +++ b/src/drivers/i2c_bus.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use embedded_hal_bus::i2c::AtomicDevice; use embedded_hal_bus::util::AtomicCell; use esp_hal::gpio::interconnect::PeripheralInput; @@ -21,18 +20,19 @@ where SCL: PeripheralOutput<'a> + PeripheralInput<'a>, SDA: PeripheralOutput<'a> + PeripheralInput<'a>, { - pub fn build(self) -> I2cBus<'a> { + pub fn build(self) -> Result>, Self> { let config = Config::default().with_frequency(esp_hal::time::Rate::from_khz(400)); - let i2c = match I2c::new(self.i2c_peripheral, config) { - Ok(bus) => bus.with_sda(self.sda).with_scl(self.scl), + match I2c::new(self.i2c_peripheral, config) { + Ok(bus) => { + let i2c = bus.with_sda(self.sda).with_scl(self.scl); + log::info!("Shared I2C bus ready on GPIO17 (SDA) and GPIO18 (SCL)"); + Ok(AtomicCell::new(i2c)) + } Err(e) => { log::error!("Shared I2C bus initialization failed for GPIO17/GPIO18: {e:?}"); - panic!("Shared I2C bus initialization failed"); + unimplemented!("Partial move makes it impossible to retry."); + // Err(self) } - }; - let shared_i2c = Box::leak(Box::new(AtomicCell::new(i2c))); - log::info!("Shared I2C bus ready on GPIO17 (SDA) and GPIO18 (SCL)"); - - shared_i2c + } } } diff --git a/src/drivers/spi_bus.rs b/src/drivers/spi_bus.rs index 036b1a5..89ec939 100644 --- a/src/drivers/spi_bus.rs +++ b/src/drivers/spi_bus.rs @@ -135,7 +135,7 @@ where RES2: OutputPin + 'static, DC: OutputPin + 'static, { - pub fn build(self) -> (PrimaryDisplay<'static>, [SecondaryDisplay<'static>; 3]) { + pub fn build(self) -> Result<(PrimaryDisplay<'static>, [SecondaryDisplay<'static>; 3]), Self> { let spi = Spi::new( self.spi_peripheral, SpiConfig::default() @@ -178,7 +178,7 @@ where } .build(); - (primary, secondaries) + Ok((primary, secondaries)) } } diff --git a/src/drivers/tertiary_lcd.rs b/src/drivers/tertiary_lcd.rs index 36213f5..3c3df68 100644 --- a/src/drivers/tertiary_lcd.rs +++ b/src/drivers/tertiary_lcd.rs @@ -15,19 +15,20 @@ pub struct TertiaryDisplayPinConfiguration<'a> { } impl<'a> TertiaryDisplayPinConfiguration<'a> { - pub fn build(self) -> TertiaryDisplay<'a> { + pub fn build(self) -> Result, Self> { let device = AtomicDevice::new(self.i2c); let mut lcd = CharacterDisplayPCF8574T::new(device, LcdDisplayType::Lcd16x2, Delay::new()); match lcd.init() { Ok(()) => { log::info!("I2C tertiary LCD initialized on PCF8574T at address 0x27"); - TertiaryDisplay { + Ok(TertiaryDisplay { display: lcd, charset: create_custom_char_set!(), - } + }) } Err(e) => { - panic!("I2C tertiary LCD init failed on PCF8574T at address 0x27: {e}"); + log::error!("I2C tertiary LCD init failed on PCF8574T at address 0x27: {e}"); + Err(self) } } } @@ -407,4 +408,3 @@ pub const BOX: CharMap = [ ]; pub const EXAMPLE: CustomCharset = create_custom_char_set!(HEART, BOX, EMPTY); -