589: stm32/i2c: allow empty writes r=Dirbaio a=darkwater

The Senseair Sunrise CO2 sensor expects a wake-up packet in the form of (START, address, STOP), which looks like a `write(addr, &[])`, but this assertion prevents sending that.

I'm not sure why the assertion is there. Sending empty packets works fine in my limited testing, at least.

Co-authored-by: Sam Lakerveld <dark@dark.red>
This commit is contained in:
bors[bot] 2022-01-25 16:19:46 +00:00 committed by GitHub
commit cd36e3f733
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 8 deletions

View file

@ -130,7 +130,7 @@ mod transfers {
reg_addr: *mut W, reg_addr: *mut W,
buf: &'a mut [W], buf: &'a mut [W],
) -> impl Future<Output = ()> + 'a { ) -> impl Future<Output = ()> + 'a {
assert!(buf.len() <= 0xFFFF); assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
unborrow!(channel); unborrow!(channel);
unsafe { channel.start_read::<W>(request, reg_addr, buf) }; unsafe { channel.start_read::<W>(request, reg_addr, buf) };
@ -145,7 +145,7 @@ mod transfers {
buf: &'a [W], buf: &'a [W],
reg_addr: *mut W, reg_addr: *mut W,
) -> impl Future<Output = ()> + 'a { ) -> impl Future<Output = ()> + 'a {
assert!(buf.len() <= 0xFFFF); assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
unborrow!(channel); unborrow!(channel);
unsafe { channel.start_write::<W>(request, buf, reg_addr) }; unsafe { channel.start_write::<W>(request, buf, reg_addr) };

View file

@ -139,7 +139,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
unsafe fn master_read(address: u8, length: usize, stop: Stop, reload: bool, restart: bool) { unsafe fn master_read(address: u8, length: usize, stop: Stop, reload: bool, restart: bool) {
assert!(length < 256 && length > 0); assert!(length < 256);
if !restart { if !restart {
// Wait for any previous address sequence to end // Wait for any previous address sequence to end
@ -170,7 +170,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
unsafe fn master_write(address: u8, length: usize, stop: Stop, reload: bool) { unsafe fn master_write(address: u8, length: usize, stop: Stop, reload: bool) {
assert!(length < 256 && length > 0); assert!(length < 256);
// Wait for any previous address sequence to end // Wait for any previous address sequence to end
// automatically. This could be up to 50% of a bus // automatically. This could be up to 50% of a bus
@ -577,7 +577,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
{ {
self.write_dma_internal(address, bytes, true, true).await if bytes.is_empty() {
self.write_internal(address, bytes, true)
} else {
self.write_dma_internal(address, bytes, true, true).await
}
} }
pub async fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> pub async fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error>
@ -606,7 +610,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
where where
RXDMA: crate::i2c::RxDma<T>, RXDMA: crate::i2c::RxDma<T>,
{ {
self.read_dma_internal(address, buffer, false).await if buffer.is_empty() {
self.read_internal(address, buffer, false)
} else {
self.read_dma_internal(address, buffer, false).await
}
} }
pub async fn write_read( pub async fn write_read(
@ -619,8 +627,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
TXDMA: super::TxDma<T>, TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>, RXDMA: super::RxDma<T>,
{ {
self.write_dma_internal(address, bytes, true, true).await?; if bytes.is_empty() {
self.read_dma_internal(address, buffer, true).await?; self.write_internal(address, bytes, false)?;
} else {
self.write_dma_internal(address, bytes, true, true).await?;
}
if buffer.is_empty() {
self.read_internal(address, buffer, true)?;
} else {
self.read_dma_internal(address, buffer, true).await?;
}
Ok(()) Ok(())
} }