diff --git a/examples/rt685s-evk/.cargo/config.toml b/examples/rt685s-evk/.cargo/config.toml index db42be81..59c3a138 100644 --- a/examples/rt685s-evk/.cargo/config.toml +++ b/examples/rt685s-evk/.cargo/config.toml @@ -2,12 +2,16 @@ runner = 'probe-rs run --chip MIMXRT685SFVKB' rustflags = [ - "-C", "linker=flip-link", - "-C", "link-arg=-Tlink.x", - "-C", "link-arg=-Tdefmt.x", + "-C", + "linker=flip-link", + "-C", + "link-arg=-Tlink.x", + "-C", + "link-arg=-Tdefmt.x", # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 - "-C", "link-arg=--nmagic", + "-C", + "link-arg=--nmagic", ] [build] @@ -15,3 +19,4 @@ target = "thumbv8m.main-none-eabihf" # Cortex-M33 [env] DEFMT_LOG = "trace" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE = "16384" diff --git a/examples/rt685s-evk/src/bin/i2c-loopback-largebuf.rs b/examples/rt685s-evk/src/bin/i2c-loopback-largebuf.rs index 5f36f959..889e7310 100644 --- a/examples/rt685s-evk/src/bin/i2c-loopback-largebuf.rs +++ b/examples/rt685s-evk/src/bin/i2c-loopback-largebuf.rs @@ -12,11 +12,8 @@ use embassy_imxrt::{bind_interrupts, peripherals}; use embedded_hal_async::i2c::I2c; const ADDR: u8 = 0x20; -const MAX_I2C_CHUNK_SIZE: usize = 512; -const MASTER_BUFLEN: usize = 2000; -// slave buffer has to be 1 bigger than master buffer for each chunk -//because master does not handle end of read properly -const SLAVE_BUFLEN: usize = MASTER_BUFLEN + (MASTER_BUFLEN / MAX_I2C_CHUNK_SIZE) + 1; +const MAX_I2C_CHUNK_SIZE: usize = 1024; +const BUFLEN: usize = 2500; const SLAVE_ADDR: Option
= Address::new(ADDR); bind_interrupts!(struct Irqs { @@ -26,8 +23,8 @@ bind_interrupts!(struct Irqs { #[embassy_executor::task] async fn slave_service(mut slave: I2cSlave<'static, Async>) { - let mut r_buf = [0xAA; SLAVE_BUFLEN]; - let mut t_buf = [0xAA; SLAVE_BUFLEN]; + let mut r_buf = [0xAA; BUFLEN]; + let mut t_buf = [0xAA; BUFLEN]; // Initialize write buffer with increment numbers for (i, e) in t_buf.iter_mut().enumerate() { @@ -48,7 +45,7 @@ async fn slave_service(mut slave: I2cSlave<'static, Async>) { Command::Read => { info!("Read"); loop { - let end = (t_offset + MAX_I2C_CHUNK_SIZE + 1).min(t_buf.len()); + let end = (t_offset + MAX_I2C_CHUNK_SIZE).min(t_buf.len()); let t_chunk = &t_buf[t_offset..end]; match slave.respond_to_read(t_chunk).await.unwrap() { Response::Complete(n) => { @@ -93,8 +90,8 @@ async fn slave_service(mut slave: I2cSlave<'static, Async>) { async fn master_service(mut master: I2cMaster<'static, Async>) { const ADDR: u8 = 0x20; - let mut w_buf = [0xAA; MASTER_BUFLEN]; - let mut r_buf = [0xAA; MASTER_BUFLEN]; + let mut w_buf = [0xAA; BUFLEN]; + let mut r_buf = [0xAA; BUFLEN]; // Initialize write buffer with increment numbers for (i, e) in w_buf.iter_mut().enumerate() { @@ -108,6 +105,14 @@ async fn master_service(mut master: I2cMaster<'static, Async>) { let r_end = r_buf.len(); info!("i2cm read {} bytes", r_end); master.read(ADDR, &mut r_buf[0..r_end]).await.unwrap(); + + let tend = w_buf.len(); + let r_end = r_buf.len(); + info!("i2cm write {} bytes, read {} bytes", tend, r_end); + master + .write_read(ADDR, &w_buf[0..tend], &mut r_buf[0..r_end]) + .await + .unwrap(); } #[embassy_executor::main] diff --git a/src/i2c/master.rs b/src/i2c/master.rs index 2d34705e..469b73d2 100644 --- a/src/i2c/master.rs +++ b/src/i2c/master.rs @@ -761,6 +761,30 @@ impl<'a> I2cMaster<'a, Async> { ) .await } + + async fn write_chunks(&mut self, address: u16, write: &[u8]) -> Result<()> { + // write of 0 size is allowed according to i2c spec + if write.is_empty() { + self.write_no_stop(address, write).await?; + } + + for chunk in write.chunks(MAX_I2C_CHUNK_SIZE) { + self.write_no_stop(address, chunk).await?; + } + Ok(()) + } + + async fn read_chunks(&mut self, address: u16, read: &mut [u8]) -> Result<()> { + // read of 0 size is not allowed according to i2c spec + if read.is_empty() { + return Err(TransferError::OtherBusError.into()); + } + + for chunk in read.chunks_mut(MAX_I2C_CHUNK_SIZE) { + self.read_no_stop(address, chunk).await?; + } + Ok(()) + } } /// Error Types for I2C communication @@ -832,27 +856,19 @@ impl> embedded_hal_1::i2c::I2c> embedded_hal_async::i2c::I2c for I2cMaster<'_, Async> { async fn read(&mut self, address: A, read: &mut [u8]) -> Result<()> { - for chunk in read.chunks_mut(MAX_I2C_CHUNK_SIZE) { - self.read_no_stop(address.into(), chunk).await?; - } + self.read_chunks(address.into(), read).await?; self.stop().await } async fn write(&mut self, address: A, write: &[u8]) -> Result<()> { - for chunk in write.chunks(MAX_I2C_CHUNK_SIZE) { - self.write_no_stop(address.into(), chunk).await?; - } + self.write_chunks(address.into(), write).await?; self.stop().await } async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<()> { let address = address.into(); - for chunk in write.chunks(MAX_I2C_CHUNK_SIZE) { - self.write_no_stop(address, chunk).await?; - } - for chunk in read.chunks_mut(MAX_I2C_CHUNK_SIZE) { - self.read_no_stop(address, chunk).await?; - } + self.write_chunks(address, write).await?; + self.read_chunks(address, read).await?; self.stop().await } diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 7be4f7a1..e24defc3 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -126,7 +126,7 @@ impl_instance!(0, 1, 2, 3, 4, 5, 6, 7); const I2C_COUNT: usize = 8; static I2C_WAKERS: [AtomicWaker; I2C_COUNT] = [const { AtomicWaker::new() }; I2C_COUNT]; -const MAX_I2C_CHUNK_SIZE: usize = 512; +const MAX_I2C_CHUNK_SIZE: usize = 1024; /// Ten bit addresses start with first byte 0b11110XXX pub const TEN_BIT_PREFIX: u8 = 0b11110 << 3; diff --git a/src/i2c/slave.rs b/src/i2c/slave.rs index 14bb0466..08693249 100644 --- a/src/i2c/slave.rs +++ b/src/i2c/slave.rs @@ -600,7 +600,7 @@ impl I2cSlave<'_, Async> { /// we will get stuck in this function pub async fn respond_to_read(&mut self, buf: &[u8]) -> Result { let mut xfer_count = 0; - for chunk in buf.chunks(MAX_I2C_CHUNK_SIZE + 1) { + for chunk in buf.chunks(MAX_I2C_CHUNK_SIZE) { let result = self.respond_to_read_inner(chunk).await?; match result { Response::Complete(count) => {