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 <sean@xobs.io>
This commit is contained in:
Sean Cross 2023-07-16 15:32:10 +08:00
parent 539ca0cb56
commit 80ce69e018
3 changed files with 46 additions and 41 deletions

View file

@ -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<u64> {
self.expiry
}

View file

@ -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);
}
}

View file

@ -35,7 +35,8 @@ fn i2c_thread(i2c_sid: xous::SID, power_csr_raw: u32, wfi_state: Arc::<AtomicBoo
let xns = xous_names::XousNames::new().unwrap();
let handler_conn = xous::connect(i2c_sid).expect("couldn't make handler connection for i2c");
let mut i2c = i2c::I2cStateMachine::new(handler_conn, power_csr_raw as *mut u32, wfi_state);
let mut i2c = Box::new(i2c::I2cStateMachine::new(handler_conn, power_csr_raw as *mut u32, wfi_state));
i2c.setup();
// register a suspend/resume listener
let self_cid = xous::connect(i2c_sid).expect("couldn't create suspend callback connection");
@ -250,7 +251,8 @@ fn main() -> ! {
// 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);