Skip to content
Snippets Groups Projects
Commit 83532a15 authored by Benjamin Koch's avatar Benjamin Koch
Browse files

implement recovery for bus errors

I don't expect that we will need it but it is good practice to do it.
parent 295829ec
No related branches found
No related tags found
No related merge requests found
......@@ -151,8 +151,35 @@ async fn i2c_write_zero_bytes<SCL: gpio::Pin, SDA: gpio::Pin, const FREQ : u64>(
scl.set_low();
Timer::after(delay).await;
if sda.is_low() || scl.is_low() {
return Err(Abort(ArbitrationLoss))
// abort if SCL is stuck low
handle_clock_stretching(&mut scl).await?;
// handle SDA being stuck low
// (This can happen for very simple I2C devices that only use SCL and don't have any other clocks that
// they can use to handle timeouts, e.g. simple port expanders.)
if sda.is_low() {
// I think I have read that DW_apb_i2c does nine clocks. This seems resonable so let's do the same.
for _ in 0..9 {
scl.set_as_output();
Timer::after(delay).await;
scl.set_as_input();
Timer::after(delay).await;
if sda.is_high() {
break;
}
}
if sda.is_low() || scl.is_low() {
// There is isn't much that we can do here. A start condition would reset the state but we cannot
// generate it while one of the lines is stuck low.
return Err(Abort(ArbitrationLoss))
}
// SDA is high, again. Good. We will generate a start condition soon. This should abort any
// partial transfers that some devices might think are ongoing. We have already waited for half
// a clock so we are good to go.
}
let result = i2c_write_zero_bytes_middle_part::<_, _, FREQ>(addr, delay, &mut scl, &mut sda).await;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment