i2c-v2: Support transfers with more than 255 bytes

This commit is contained in:
Thales Fragoso 2021-07-07 21:35:56 -03:00
parent 8a172ac123
commit 8c7f8a61e3

View File

@ -81,30 +81,40 @@ impl<'d, T: Instance> I2c<'d, T> {
} }
} }
fn master_read(&mut self, address: u8, length: usize, stop: Stop) { fn master_read(&mut self, address: u8, length: usize, stop: Stop, reload: bool, restart: bool) {
assert!(length < 256 && length > 0); assert!(length < 256 && length > 0);
// Wait for any previous address sequence to end if !restart {
// automatically. This could be up to 50% of a bus // Wait for any previous address sequence to end
// cycle (ie. up to 0.5/freq) // automatically. This could be up to 50% of a bus
while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} // cycle (ie. up to 0.5/freq)
while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {}
}
// Set START and prepare to receive bytes into // Set START and prepare to receive bytes into
// `buffer`. The START bit can be set even if the bus // `buffer`. The START bit can be set even if the bus
// is BUSY or I2C is in slave mode. // is BUSY or I2C is in slave mode.
let reload = if reload {
i2c::vals::Reload::NOTCOMPLETED
} else {
i2c::vals::Reload::COMPLETED
};
unsafe { unsafe {
T::regs().cr2().modify(|w| { T::regs().cr2().modify(|w| {
w.set_sadd((address << 1 | 0) as u16); w.set_sadd((address << 1 | 0) as u16);
w.set_add10(i2c::vals::Add::BIT7);
w.set_rd_wrn(i2c::vals::RdWrn::READ); w.set_rd_wrn(i2c::vals::RdWrn::READ);
w.set_nbytes(length as u8); w.set_nbytes(length as u8);
w.set_start(i2c::vals::Start::START); w.set_start(i2c::vals::Start::START);
w.set_autoend(stop.autoend()); w.set_autoend(stop.autoend());
w.set_reload(reload);
}); });
} }
} }
fn master_write(&mut self, address: u8, length: usize, stop: Stop) { fn master_write(&mut self, address: u8, length: usize, stop: Stop, reload: bool) {
assert!(length < 256 && length > 0); assert!(length < 256 && length > 0);
// Wait for any previous address sequence to end // Wait for any previous address sequence to end
@ -112,6 +122,12 @@ impl<'d, T: Instance> I2c<'d, T> {
// cycle (ie. up to 0.5/freq) // cycle (ie. up to 0.5/freq)
while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {}
let reload = if reload {
i2c::vals::Reload::NOTCOMPLETED
} else {
i2c::vals::Reload::COMPLETED
};
// Set START and prepare to send `bytes`. The // Set START and prepare to send `bytes`. The
// START bit can be set even if the bus is BUSY or // START bit can be set even if the bus is BUSY or
// I2C is in slave mode. // I2C is in slave mode.
@ -123,21 +139,24 @@ impl<'d, T: Instance> I2c<'d, T> {
w.set_nbytes(length as u8); w.set_nbytes(length as u8);
w.set_start(i2c::vals::Start::START); w.set_start(i2c::vals::Start::START);
w.set_autoend(stop.autoend()); w.set_autoend(stop.autoend());
w.set_reload(reload);
}); });
} }
} }
fn master_re_start(&mut self, address: u8, length: usize, stop: Stop) { fn master_continue(&mut self, length: usize, reload: bool) {
assert!(length < 256 && length > 0); assert!(length < 256 && length > 0);
let reload = if reload {
i2c::vals::Reload::NOTCOMPLETED
} else {
i2c::vals::Reload::COMPLETED
};
unsafe { unsafe {
T::regs().cr2().modify(|w| { T::regs().cr2().modify(|w| {
w.set_sadd((address << 1 | 1) as u16);
w.set_add10(i2c::vals::Add::BIT7);
w.set_rd_wrn(i2c::vals::RdWrn::READ);
w.set_nbytes(length as u8); w.set_nbytes(length as u8);
w.set_start(i2c::vals::Start::START); w.set_reload(reload);
w.set_autoend(stop.autoend());
}); });
} }
} }
@ -224,28 +243,82 @@ impl<'d, T: Instance> I2c<'d, T> {
} }
} }
} }
fn read(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> {
let last_chunk = (buffer.len() / 255).saturating_sub(1);
self.master_read(
address,
buffer.len().min(255),
Stop::Automatic,
last_chunk != 0,
restart,
);
for (number, chunk) in buffer.chunks_mut(255).enumerate() {
if number != 0 {
self.master_continue(chunk.len(), number != last_chunk);
}
for byte in chunk {
// Wait until we have received something
self.wait_rxne()?;
unsafe {
*byte = T::regs().rxdr().read().rxdata();
}
}
}
Ok(())
}
fn write(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> {
let last_chunk = (bytes.len() / 255).saturating_sub(1);
// I2C start
//
// ST SAD+W
self.master_write(
address,
bytes.len().min(255),
Stop::Software,
last_chunk != 0,
);
for (number, chunk) in bytes.chunks(255).enumerate() {
if number != 0 {
self.master_continue(chunk.len(), number != last_chunk);
}
for byte in chunk {
// Wait until we are allowed to send data
// (START has been ACKed or last byte when
// through)
self.wait_txe()?;
// Put byte on the wire
//self.i2c.txdr.write(|w| w.txdata().bits(*byte));
unsafe {
T::regs().txdr().write(|w| w.set_txdata(*byte));
}
}
}
// Wait until the write finishes
self.wait_tc()?;
if send_stop {
self.master_stop();
}
Ok(())
}
} }
impl<'d, T: Instance> Read for I2c<'d, T> { impl<'d, T: Instance> Read for I2c<'d, T> {
type Error = Error; type Error = Error;
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
assert!(buffer.len() < 256 && buffer.len() > 0); self.read(address, buffer, false)
// Automatic Stop
self.master_read(address, buffer.len(), Stop::Automatic);
for byte in buffer {
// Wait until we have received something
self.wait_rxne()?;
//*byte = self.i2c.rxdr.read().rxdata().bits();
unsafe {
*byte = T::regs().rxdr().read().rxdata();
}
}
// automatic STOP
Ok(())
} }
} }
@ -253,34 +326,7 @@ impl<'d, T: Instance> Write for I2c<'d, T> {
type Error = Error; type Error = Error;
fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
// TODO support transfers of more than 255 bytes self.write(address, bytes, true)
assert!(bytes.len() < 256 && bytes.len() > 0);
// I2C start
//
// ST SAD+W
self.master_write(address, bytes.len(), Stop::Software);
for byte in bytes {
// Wait until we are allowed to send data
// (START has been ACKed or last byte when
// through)
self.wait_txe()?;
// Put byte on the wire
//self.i2c.txdr.write(|w| w.txdata().bits(*byte));
unsafe {
T::regs().txdr().write(|w| w.set_txdata(*byte));
}
}
// Wait until the write finishes
self.wait_tc()?;
// Stop
self.master_stop();
Ok(())
} }
} }
@ -293,48 +339,9 @@ impl<'d, T: Instance> WriteRead for I2c<'d, T> {
bytes: &[u8], bytes: &[u8],
buffer: &mut [u8], buffer: &mut [u8],
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
// TODO support transfers of more than 255 bytes self.write(address, bytes, false)?;
assert!(bytes.len() < 256 && bytes.len() > 0); self.read(address, buffer, true)
assert!(buffer.len() < 256 && buffer.len() > 0); // Automatic Stop
// I2C start
//
// ST SAD+W
self.master_write(address, bytes.len(), Stop::Software);
for byte in bytes {
// Wait until we are allowed to send data
// (START has been ACKed or last byte went through)
self.wait_txe()?;
// Put byte on the wire
//self.i2c.txdr.write(|w| w.txdata().bits(*byte));
unsafe {
T::regs().txdr().write(|w| w.set_txdata(*byte));
}
}
// Wait until the write finishes before beginning to read.
self.wait_tc()?;
// I2C re-start
//
// SR SAD+R
self.master_re_start(address, buffer.len(), Stop::Automatic);
for byte in buffer {
// Wait until we have received something
self.wait_rxne()?;
//*byte = self.i2c.rxdr.read().rxdata().bits();
unsafe {
*byte = T::regs().rxdr().read().rxdata();
}
}
// automatic STOP
Ok(())
} }
} }