Skip to content

Commit

Permalink
Updating chunks handling for 0 byte write and read
Browse files Browse the repository at this point in the history
  • Loading branch information
akshat2112 committed Mar 4, 2025
1 parent 62d4d17 commit a4eb019
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 28 deletions.
13 changes: 9 additions & 4 deletions examples/rt685s-evk/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
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]
target = "thumbv8m.main-none-eabihf" # Cortex-M33

[env]
DEFMT_LOG = "trace"
EMBASSY_EXECUTOR_TASK_ARENA_SIZE = "16384"
25 changes: 15 additions & 10 deletions examples/rt685s-evk/src/bin/i2c-loopback-largebuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> = Address::new(ADDR);

bind_interrupts!(struct Irqs {
Expand All @@ -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() {
Expand All @@ -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) => {
Expand Down Expand Up @@ -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() {
Expand All @@ -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]
Expand Down
40 changes: 28 additions & 12 deletions src/i2c/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -832,27 +856,19 @@ impl<A: embedded_hal_1::i2c::AddressMode + Into<u16>> embedded_hal_1::i2c::I2c<A

impl<A: embedded_hal_1::i2c::AddressMode + Into<u16>> embedded_hal_async::i2c::I2c<A> 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
}

Expand Down
2 changes: 1 addition & 1 deletion src/i2c/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/i2c/slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Response> {
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) => {
Expand Down

0 comments on commit a4eb019

Please sign in to comment.