From 80ce69e01899ee2fe53c866fd00c2b5e389f9682 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 16 Jul 2023 15:32:10 +0800 Subject: [PATCH] llio: don't install interrupt handler in `::new()` Wait until after the struct is created. This will cause it to be placed in a fixed address, which works around an issue that appeared in 1.71.0. Signed-off-by: Sean Cross --- services/llio/src/i2c/hardware.rs | 29 +++++++++-------- services/llio/src/llio_hw.rs | 52 +++++++++++++++---------------- services/llio/src/main.rs | 6 ++-- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/services/llio/src/i2c/hardware.rs b/services/llio/src/i2c/hardware.rs index 2bcf236f2..3415844dd 100644 --- a/services/llio/src/i2c/hardware.rs +++ b/services/llio/src/i2c/hardware.rs @@ -117,34 +117,37 @@ impl I2cStateMachine { // disable interrupt, just in case it's enabled from e.g. a warm boot i2c.i2c_csr.wfo(utra::i2c::EV_ENABLE_TXRX_DONE, 0); + i2c + } + + pub fn setup(&mut self) { xous::claim_interrupt( utra::i2c::I2C_IRQ, handle_i2c_irq, - (&mut i2c) as *mut I2cStateMachine as *mut usize, + self as *mut I2cStateMachine as *mut usize, ) .expect("couldn't claim I2C irq"); - i2c.i2c_csr.wfo(utra::i2c::CORE_RESET_RESET, 1); - i2c.ticktimer.sleep_ms(10).ok(); + self.i2c_csr.wfo(utra::i2c::CORE_RESET_RESET, 1); + self.ticktimer.sleep_ms(10).ok(); // initialize i2c clocks // set the prescale assuming 100MHz cpu operation: 100MHz / ( 5 * 100kHz ) - 1 = 199 let clkcode = (utralib::LITEX_CONFIG_CLOCK_FREQUENCY as u32) / (5 * 100_000) - 1; - i2c.i2c_csr.wfo(utra::i2c::PRESCALE_PRESCALE, clkcode & 0xFFFF); + self.i2c_csr.wfo(utra::i2c::PRESCALE_PRESCALE, clkcode & 0xFFFF); // enable the block - i2c.i2c_csr.rmwf(utra::i2c::CONTROL_EN, 1); + self.i2c_csr.rmwf(utra::i2c::CONTROL_EN, 1); // clear any interrupts pending, just in case something went pear-shaped during initialization - i2c.i2c_csr.wo(utra::i2c::EV_PENDING, i2c.i2c_csr.r(utra::i2c::EV_PENDING)); + self.i2c_csr.wo(utra::i2c::EV_PENDING, self.i2c_csr.r(utra::i2c::EV_PENDING)); // now enable interrupts - i2c.i2c_csr.wfo(utra::i2c::EV_ENABLE_TXRX_DONE, 1); + self.i2c_csr.wfo(utra::i2c::EV_ENABLE_TXRX_DONE, 1); // setup suspend/resume manager - i2c.i2c_susres.push(RegOrField::Field(utra::i2c::PRESCALE_PRESCALE), None); - i2c.i2c_susres.push(RegOrField::Reg(utra::i2c::CONTROL), None); - i2c.i2c_susres.push_fixed_value(RegOrField::Reg(utra::i2c::EV_PENDING), 0xFFFF_FFFF); // clear pending interrupts - i2c.i2c_susres.push(RegOrField::Reg(utra::i2c::EV_ENABLE), None); - - i2c + self.i2c_susres.push(RegOrField::Field(utra::i2c::PRESCALE_PRESCALE), None); + self.i2c_susres.push(RegOrField::Reg(utra::i2c::CONTROL), None); + self.i2c_susres.push_fixed_value(RegOrField::Reg(utra::i2c::EV_PENDING), 0xFFFF_FFFF); // clear pending interrupts + self.i2c_susres.push(RegOrField::Reg(utra::i2c::EV_ENABLE), None); } + pub fn get_expiry(&self) -> Option { self.expiry } diff --git a/services/llio/src/llio_hw.rs b/services/llio/src/llio_hw.rs index 48118008a..ba422f323 100644 --- a/services/llio/src/llio_hw.rs +++ b/services/llio/src/llio_hw.rs @@ -121,7 +121,7 @@ impl Llio { let ticktimer = ticktimer_server::Ticktimer::new().expect("Couldn't connect to Ticktimer"); - let mut xl = Llio { + Llio { gpio_csr: CSR::new(gpio_base), gpio_susres: RegManager::new(gpio_base), info_csr: CSR::new(info_csr.as_mut_ptr() as *mut u32), @@ -136,54 +136,55 @@ impl Llio { activity_period: 24_000_000, // 2 second interval initially destruct_armed: false, uartmux_cache: BOOT_UART.into(), - }; + } + } + pub(crate) fn init(&mut self) { xous::claim_interrupt( utra::btevents::BTEVENTS_IRQ, handle_event_irq, - (&mut xl) as *mut Llio as *mut usize, + self as *mut Llio as *mut usize, ) .expect("couldn't claim BtEvents irq"); xous::claim_interrupt( utra::gpio::GPIO_IRQ, handle_gpio_irq, - (&mut xl) as *mut Llio as *mut usize, + self as *mut Llio as *mut usize, ) .expect("couldn't claim GPIO irq"); xous::claim_interrupt( utra::power::POWER_IRQ, handle_power_irq, - (&mut xl) as *mut Llio as *mut usize, + self as *mut Llio as *mut usize, ) .expect("couldn't claim Power irq"); - xl.gpio_susres.push(RegOrField::Reg(utra::gpio::DRIVE), None); - xl.gpio_susres.push(RegOrField::Reg(utra::gpio::OUTPUT), None); - xl.gpio_susres.push(RegOrField::Reg(utra::gpio::INTPOL), None); - xl.gpio_susres.push(RegOrField::Reg(utra::gpio::INTENA), None); - xl.gpio_susres.push_fixed_value(RegOrField::Reg(utra::gpio::EV_PENDING), 0xFFFF_FFFF); - xl.gpio_susres.push(RegOrField::Reg(utra::gpio::EV_ENABLE), None); - xl.gpio_susres.push(RegOrField::Field(utra::gpio::UARTSEL_UARTSEL), None); + self.gpio_susres.push(RegOrField::Reg(utra::gpio::DRIVE), None); + self.gpio_susres.push(RegOrField::Reg(utra::gpio::OUTPUT), None); + self.gpio_susres.push(RegOrField::Reg(utra::gpio::INTPOL), None); + self.gpio_susres.push(RegOrField::Reg(utra::gpio::INTENA), None); + self.gpio_susres.push_fixed_value(RegOrField::Reg(utra::gpio::EV_PENDING), 0xFFFF_FFFF); + self.gpio_susres.push(RegOrField::Reg(utra::gpio::EV_ENABLE), None); + self.gpio_susres.push(RegOrField::Field(utra::gpio::UARTSEL_UARTSEL), None); - xl.event_susres.push_fixed_value(RegOrField::Reg(utra::btevents::EV_PENDING), 0xFFFF_FFFF); - xl.event_susres.push(RegOrField::Reg(utra::btevents::EV_ENABLE), None); + self.event_susres.push_fixed_value(RegOrField::Reg(utra::btevents::EV_PENDING), 0xFFFF_FFFF); + self.event_susres.push(RegOrField::Reg(utra::btevents::EV_ENABLE), None); - xl.power_csr.rmwf(utra::power::POWER_CRYPTO_ON, 0); // save power on crypto block - xl.power_susres.push(RegOrField::Reg(utra::power::POWER), None); - xl.power_susres.push(RegOrField::Reg(utra::power::VIBE), None); + self.power_csr.rmwf(utra::power::POWER_CRYPTO_ON, 0); // save power on crypto block + self.power_susres.push(RegOrField::Reg(utra::power::POWER), None); + self.power_susres.push(RegOrField::Reg(utra::power::VIBE), None); - xl.power_csr.wfo(utra::power::SAMPLING_PERIOD_SAMPLE_PERIOD, xl.activity_period); // 2 second sampling intervals - xl.power_susres.push(RegOrField::Reg(utra::power::SAMPLING_PERIOD), None); - xl.power_csr.wfo(utra::power::EV_PENDING_ACTIVITY_UPDATE, 1); - xl.power_csr.rmwf(utra::power::EV_ENABLE_ACTIVITY_UPDATE, 1); + self.power_csr.wfo(utra::power::SAMPLING_PERIOD_SAMPLE_PERIOD, self.activity_period); // 2 second sampling intervals + self.power_susres.push(RegOrField::Reg(utra::power::SAMPLING_PERIOD), None); + self.power_csr.wfo(utra::power::EV_PENDING_ACTIVITY_UPDATE, 1); + self.power_csr.rmwf(utra::power::EV_ENABLE_ACTIVITY_UPDATE, 1); - xl.power_susres.push_fixed_value(RegOrField::Reg(utra::power::EV_PENDING), 0xFFFF_FFFF); - xl.power_susres.push(RegOrField::Reg(utra::power::EV_ENABLE), None); - - xl + self.power_susres.push_fixed_value(RegOrField::Reg(utra::power::EV_PENDING), 0xFFFF_FFFF); + self.power_susres.push(RegOrField::Reg(utra::power::EV_ENABLE), None); } + pub(crate) fn get_power_csr_raw(&self) -> *mut u32 { self.power_csr_raw } @@ -448,4 +449,3 @@ impl Llio { self.power_csr.rmwf(utra::power::EV_ENABLE_USB_ATTACH, value); } } - diff --git a/services/llio/src/main.rs b/services/llio/src/main.rs index 60bc054c7..4afd5d61f 100644 --- a/services/llio/src/main.rs +++ b/services/llio/src/main.rs @@ -35,7 +35,8 @@ fn i2c_thread(i2c_sid: xous::SID, power_csr_raw: u32, wfi_state: Arc:: ! { // Create a new llio object let handler_conn = xous::connect(llio_sid).expect("can't create IRQ handler connection"); - let mut llio = Llio::new(handler_conn, gpio_base); + let mut llio = Box::new(Llio::new(handler_conn, gpio_base)); + llio.init(); llio.ec_power_on(); // ensure this is set correctly; if we're on, we always want the EC on. log::debug!("registered I2C thread with NS -- {:?}", i2c_sid);