796: nrf/twim: allow zero length transfers. r=Dirbaio a=Dirbaio

bors r+

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
bors[bot] 2022-06-07 12:54:09 +00:00 committed by GitHub
commit bf09017032
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -60,8 +60,6 @@ impl Default for Config {
pub enum Error { pub enum Error {
TxBufferTooLong, TxBufferTooLong,
RxBufferTooLong, RxBufferTooLong,
TxBufferZeroLength,
RxBufferZeroLength,
Transmit, Transmit,
Receive, Receive,
DMABufferNotInDataMemory, DMABufferNotInDataMemory,
@ -159,9 +157,6 @@ impl<'d, T: Instance> Twim<'d, T> {
unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
if buffer.len() == 0 {
return Err(Error::TxBufferZeroLength);
}
if buffer.len() > EASY_DMA_SIZE { if buffer.len() > EASY_DMA_SIZE {
return Err(Error::TxBufferTooLong); return Err(Error::TxBufferTooLong);
} }
@ -193,9 +188,6 @@ impl<'d, T: Instance> Twim<'d, T> {
// NOTE: RAM slice check is not necessary, as a mutable // NOTE: RAM slice check is not necessary, as a mutable
// slice can only be built from data located in RAM. // slice can only be built from data located in RAM.
if buffer.len() == 0 {
return Err(Error::RxBufferZeroLength);
}
if buffer.len() > EASY_DMA_SIZE { if buffer.len() > EASY_DMA_SIZE {
return Err(Error::RxBufferTooLong); return Err(Error::RxBufferTooLong);
} }
@ -357,6 +349,10 @@ impl<'d, T: Instance> Twim<'d, T> {
// Start write operation. // Start write operation.
r.shorts.write(|w| w.lasttx_stop().enabled()); r.shorts.write(|w| w.lasttx_stop().enabled());
r.tasks_starttx.write(|w| unsafe { w.bits(1) }); r.tasks_starttx.write(|w| unsafe { w.bits(1) });
if buffer.len() == 0 {
// With a zero-length buffer, LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves.
r.tasks_stop.write(|w| unsafe { w.bits(1) });
}
Ok(()) Ok(())
} }
@ -384,6 +380,10 @@ impl<'d, T: Instance> Twim<'d, T> {
// Start read operation. // Start read operation.
r.shorts.write(|w| w.lastrx_stop().enabled()); r.shorts.write(|w| w.lastrx_stop().enabled());
r.tasks_startrx.write(|w| unsafe { w.bits(1) }); r.tasks_startrx.write(|w| unsafe { w.bits(1) });
if buffer.len() == 0 {
// With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STOP ourselves.
r.tasks_stop.write(|w| unsafe { w.bits(1) });
}
Ok(()) Ok(())
} }
@ -424,6 +424,12 @@ impl<'d, T: Instance> Twim<'d, T> {
w w
}); });
r.tasks_starttx.write(|w| unsafe { w.bits(1) }); r.tasks_starttx.write(|w| unsafe { w.bits(1) });
if wr_buffer.len() == 0 && rd_buffer.len() == 0 {
// With a zero-length buffer, LASTRX/LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves.
// TODO handle when only one of the buffers is zero length
r.tasks_stop.write(|w| unsafe { w.bits(1) });
}
Ok(()) Ok(())
} }
@ -800,8 +806,6 @@ mod eh1 {
match *self { match *self {
Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
Self::TxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other,
Self::RxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other,
Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other, Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other,
Self::Receive => embedded_hal_1::i2c::ErrorKind::Other, Self::Receive => embedded_hal_1::i2c::ErrorKind::Other,
Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other, Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other,