Skip to content

Commit

Permalink
supply: reset STUSB4500 when BQ25713 fails
Browse files Browse the repository at this point in the history
When BQ25713 has no I2C communication, this is often
caused by STUSB4500 blocking the I2C bus. Therefore,
reset the STUSB4500 in this case.
  • Loading branch information
surban committed Jun 18, 2024
1 parent 7238995 commit e5d68fd
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 7 deletions.
8 changes: 6 additions & 2 deletions openemc-firmware/src/bq25713.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,11 +708,15 @@ where
}

/// Call this periodically (approx. every second) to handle communication with the device.
pub fn periodic(&mut self, i2c: &mut I2C, chrg_ok: bool) {
if let Err(err) = self.do_periodic(i2c, chrg_ok) {
pub fn periodic(&mut self, i2c: &mut I2C, chrg_ok: bool) -> Result<()> {
let res = self.do_periodic(i2c, chrg_ok);

if let Err(err) = &res {
defmt::warn!("BQ25713 failed: {}", err);
self.initialized = false;
}

res
}

/// Update status and measurements without programming charger.
Expand Down
19 changes: 17 additions & 2 deletions openemc-firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ mod app {

// Check that battery voltage is sufficient.
if let (Some(bq25713), Some(i2c2)) = (&mut bq25713, &mut i2c2) {
bq25713.periodic(i2c2, board.check_bq25713_chrg_ok());
let _ = bq25713.periodic(i2c2, board.check_bq25713_chrg_ok());

watchman.force_pet();
let v_bat = loop {
Expand Down Expand Up @@ -910,6 +910,16 @@ mod app {
defmt::unwrap!(stusb4500_periodic::spawn_after(500u64.millis()));
}

/// STUSB4500 reset task.
#[task(shared = [stusb4500])]
fn stusb4500_reset(mut cx: stusb4500_reset::Context) {
cx.shared.stusb4500.lock(|stusb4500| {
if let Some(stusb4500) = stusb4500.as_mut() {
stusb4500.reset();
}
});
}

/// Updates the power supply status.
#[task(
shared = [i2c2, stusb4500, max14636, bq25713, power_supply, irq, board, &power_mode],
Expand Down Expand Up @@ -1023,7 +1033,12 @@ mod app {
|i2c2, bq25713, battery, irq, board| {
if let Some(bq25713) = bq25713.as_mut() {
let i2c2 = defmt::unwrap!(i2c2.as_mut());
bq25713.periodic(i2c2, board.check_bq25713_chrg_ok());
let res = bq25713.periodic(i2c2, board.check_bq25713_chrg_ok());

if let Err(bq25713::Error::I2c) = &res {
defmt::warn!("Resetting STUSB4500 due to BQ25713 I2C error");
let _ = stusb4500_reset::spawn();
}

let mut ac = false;
if let Some(status) = bq25713.status().cloned() {
Expand Down
7 changes: 7 additions & 0 deletions openemc-firmware/src/supply/stusb4500/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,13 @@ where
pub fn reset_pin_level(&self) -> bool {
matches!(self.reset, ResetState::PinResetHigh(_))
}

/// Initiates a reset.
pub fn reset(&mut self) {
defmt::info!("Initiating STUSB4500 reset by request");
self.reset = ResetState::None;
self.start_pin_reset();
}
}

// Register definitions.
Expand Down
9 changes: 6 additions & 3 deletions openemc-firmware/src/supply/stusb4500/nvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ where
I2C: i2c::Write<i2c::SevenBitAddress> + i2c::WriteRead<i2c::SevenBitAddress>,
{
/// Mask of programmable bits within NVM.
#[rustfmt::skip]
pub const NVM_PROGRAMABLE: [u8; 40] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];

/// Read I2C register(s).
Expand Down

0 comments on commit e5d68fd

Please sign in to comment.