From 51a62d5387455b328a545febeaf4ea12068209b6 Mon Sep 17 00:00:00 2001 From: Justin Beaurivage Date: Tue, 12 Dec 2023 19:27:57 -0500 Subject: [PATCH] Fix nasty bug in I2C-DMA transactions --- hal/src/sercom/i2c/async_api.rs | 8 +++++++- hal/src/sercom/i2c/flags.rs | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hal/src/sercom/i2c/async_api.rs b/hal/src/sercom/i2c/async_api.rs index 4c0548e7f448..c3a23c8d6d83 100644 --- a/hal/src/sercom/i2c/async_api.rs +++ b/hal/src/sercom/i2c/async_api.rs @@ -363,6 +363,13 @@ mod dma { .await .map_err(i2c::Error::Dma)?; + // Unfortunately, gotta take a polling approach here as there is no interrupt + // source that can notify us of an IDLE bus state. Fortunately, it's usually not + // long. 8-10 times around the loop will do the trick. + while !self.i2c.read_status().is_idle() { + core::hint::spin_loop(); + } + self.i2c.read_status().check_bus_error()?; Ok(()) } @@ -397,7 +404,6 @@ mod dma { read_buf: &mut [u8], ) -> Result<(), i2c::Error> { self.write(addr, write_buf).await?; - // TODO may need some sort of delay here?? self.read(addr, read_buf).await?; Ok(()) } diff --git a/hal/src/sercom/i2c/flags.rs b/hal/src/sercom/i2c/flags.rs index 9731424e6755..a5a3620d068f 100644 --- a/hal/src/sercom/i2c/flags.rs +++ b/hal/src/sercom/i2c/flags.rs @@ -70,6 +70,10 @@ impl Status { Ok(()) } } + + pub fn is_idle(self) -> bool { + self.busstate() == BusState::Idle + } } /// Errors available for I2C transactions