stm32/i2c: expose all functionality as inherent methods.

This commit is contained in:
Dario Nieuwenhuis 2022-01-14 23:31:10 +01:00
parent c949519714
commit 97ab859f00
4 changed files with 99 additions and 64 deletions

View file

@ -3,9 +3,6 @@ use crate::time::Hertz;
use core::marker::PhantomData; use core::marker::PhantomData;
use embassy::util::Unborrow; use embassy::util::Unborrow;
use embassy_hal_common::unborrow; use embassy_hal_common::unborrow;
use embedded_hal::blocking::i2c::Read;
use embedded_hal::blocking::i2c::Write;
use embedded_hal::blocking::i2c::WriteRead;
use crate::pac::i2c; use crate::pac::i2c;
@ -179,12 +176,8 @@ impl<'d, T: Instance> I2c<'d, T> {
let value = T::regs().dr().read().dr(); let value = T::regs().dr().read().dr();
Ok(value) Ok(value)
} }
}
impl<'d, T: Instance> Read for I2c<'d, T> { pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
type Error = Error;
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
if let Some((last, buffer)) = buffer.split_last_mut() { if let Some((last, buffer)) = buffer.split_last_mut() {
// Send a START condition and set ACK bit // Send a START condition and set ACK bit
unsafe { unsafe {
@ -248,12 +241,8 @@ impl<'d, T: Instance> Read for I2c<'d, T> {
Err(Error::Overrun) Err(Error::Overrun)
} }
} }
}
impl<'d, T: Instance> Write for I2c<'d, T> { pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
unsafe { unsafe {
self.write_bytes(addr, bytes)?; self.write_bytes(addr, bytes)?;
// Send a STOP condition // Send a STOP condition
@ -267,16 +256,41 @@ impl<'d, T: Instance> Write for I2c<'d, T> {
// Fallthrough is success // Fallthrough is success
Ok(()) Ok(())
} }
pub fn blocking_write_read(
&mut self,
addr: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
unsafe { self.write_bytes(addr, bytes)? };
self.blocking_read(addr, buffer)?;
Ok(())
}
} }
impl<'d, T: Instance> WriteRead for I2c<'d, T> { impl<'d, T: Instance> embedded_hal::blocking::i2c::Read for I2c<'d, T> {
type Error = Error;
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(addr, buffer)
}
}
impl<'d, T: Instance> embedded_hal::blocking::i2c::Write for I2c<'d, T> {
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(addr, bytes)
}
}
impl<'d, T: Instance> embedded_hal::blocking::i2c::WriteRead for I2c<'d, T> {
type Error = Error; type Error = Error;
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
unsafe { self.write_bytes(addr, bytes)? }; self.blocking_write_read(addr, bytes, buffer)
self.read(addr, buffer)?;
Ok(())
} }
} }

View file

@ -10,9 +10,6 @@ use embassy::util::Unborrow;
use embassy::waitqueue::AtomicWaker; use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::unborrow; use embassy_hal_common::unborrow;
use embedded_hal::blocking::i2c::Read;
use embedded_hal::blocking::i2c::Write;
use embedded_hal::blocking::i2c::WriteRead;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::dma::NoDma; use crate::dma::NoDma;
@ -300,7 +297,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
} }
fn read(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { fn read_internal(
&mut self,
address: u8,
buffer: &mut [u8],
restart: bool,
) -> Result<(), Error> {
let completed_chunks = buffer.len() / 255; let completed_chunks = buffer.len() / 255;
let total_chunks = if completed_chunks * 255 == buffer.len() { let total_chunks = if completed_chunks * 255 == buffer.len() {
completed_chunks completed_chunks
@ -339,7 +341,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
Ok(()) Ok(())
} }
fn write(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { fn write_internal(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> {
let completed_chunks = bytes.len() / 255; let completed_chunks = bytes.len() / 255;
let total_chunks = if completed_chunks * 255 == bytes.len() { let total_chunks = if completed_chunks * 255 == bytes.len() {
completed_chunks completed_chunks
@ -568,14 +570,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
Ok(()) Ok(())
} }
pub async fn write_dma(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> // =========================
// Async public API
pub async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
{ {
self.write_dma_internal(address, bytes, true, true).await self.write_dma_internal(address, bytes, true, true).await
} }
pub async fn write_dma_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> pub async fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error>
where where
TXDMA: crate::i2c::TxDma<T>, TXDMA: crate::i2c::TxDma<T>,
{ {
@ -597,19 +602,52 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
Ok(()) Ok(())
} }
pub async fn read_dma( pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
&mut self,
address: u8,
buffer: &mut [u8],
restart: bool,
) -> Result<(), Error>
where where
RXDMA: crate::i2c::RxDma<T>, RXDMA: crate::i2c::RxDma<T>,
{ {
self.read_dma_internal(address, buffer, restart).await self.read_dma_internal(address, buffer, false).await
} }
pub fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { pub async fn write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error>
where
TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>,
{
self.write_dma_internal(address, bytes, true, true).await?;
self.read_dma_internal(address, buffer, true).await?;
Ok(())
}
// =========================
// Blocking public API
pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
self.read_internal(address, buffer, false)
// Automatic Stop
}
pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
self.write_internal(address, bytes, true)
}
pub fn blocking_write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
self.write_internal(address, bytes, false)?;
self.read_internal(address, buffer, true)
// Automatic Stop
}
pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> {
if bytes.is_empty() { if bytes.is_empty() {
return Err(Error::ZeroLengthTransfer); return Err(Error::ZeroLengthTransfer);
} }
@ -679,24 +717,23 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
} }
} }
impl<'d, T: Instance> Read for I2c<'d, T> { impl<'d, T: Instance> embedded_hal::blocking::i2c::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> {
self.read(address, buffer, false) self.blocking_read(address, buffer)
// Automatic Stop
} }
} }
impl<'d, T: Instance> Write for I2c<'d, T> { impl<'d, T: Instance> embedded_hal::blocking::i2c::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> {
self.write(address, bytes, true) self.blocking_write(address, bytes)
} }
} }
impl<'d, T: Instance> WriteRead for I2c<'d, T> { impl<'d, T: Instance> embedded_hal::blocking::i2c::WriteRead for I2c<'d, T> {
type Error = Error; type Error = Error;
fn write_read( fn write_read(
@ -705,9 +742,7 @@ 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> {
self.write(address, bytes, false)?; self.blocking_write_read(address, bytes, buffer)
self.read(address, buffer, true)
// Automatic Stop
} }
} }
@ -715,7 +750,7 @@ impl<'d, T: Instance> WriteRead for I2c<'d, T> {
/// ///
/// Peripheral options for generating the STOP condition /// Peripheral options for generating the STOP condition
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum Stop { enum Stop {
/// Software end mode: Must write register to generate STOP condition /// Software end mode: Must write register to generate STOP condition
Software, Software,
/// Automatic end mode: A STOP condition is automatically generated once the /// Automatic end mode: A STOP condition is automatically generated once the
@ -860,32 +895,23 @@ impl<'d, T: Instance, TXDMA: super::TxDma<T>, RXDMA: super::RxDma<T>> I2cTrait<u
type WriteFuture<'a> type WriteFuture<'a>
where where
'd: 'a, Self: 'a,
T: 'a,
TXDMA: 'a,
RXDMA: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a; = impl Future<Output = Result<(), Self::Error>> + 'a;
type ReadFuture<'a> type ReadFuture<'a>
where where
'd: 'a, Self: 'a,
T: 'a,
TXDMA: 'a,
RXDMA: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a; = impl Future<Output = Result<(), Self::Error>> + 'a;
type WriteReadFuture<'a> type WriteReadFuture<'a>
where where
'd: 'a, Self: 'a,
T: 'a,
TXDMA: 'a,
RXDMA: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a; = impl Future<Output = Result<(), Self::Error>> + 'a;
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
self.read_dma(address, buffer, false) self.read(address, buffer)
} }
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
self.write_dma(address, bytes) self.write(address, bytes)
} }
fn write_read<'a>( fn write_read<'a>(
@ -894,9 +920,6 @@ impl<'d, T: Instance, TXDMA: super::TxDma<T>, RXDMA: super::RxDma<T>> I2cTrait<u
bytes: &'a [u8], bytes: &'a [u8],
buffer: &'a mut [u8], buffer: &'a mut [u8],
) -> Self::WriteReadFuture<'a> { ) -> Self::WriteReadFuture<'a> {
async move { self.write_read(address, bytes, buffer)
self.write_dma(address, bytes).await?;
self.read_dma(address, buffer, true).await
}
} }
} }

View file

@ -11,7 +11,6 @@ use embassy_stm32::i2c::I2c;
use embassy_stm32::interrupt; use embassy_stm32::interrupt;
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::Peripherals; use embassy_stm32::Peripherals;
use embedded_hal::blocking::i2c::WriteRead;
use example_common::{info, unwrap}; use example_common::{info, unwrap};
const ADDRESS: u8 = 0x5F; const ADDRESS: u8 = 0x5F;
@ -23,6 +22,6 @@ async fn main(_spawner: Spawner, p: Peripherals) -> ! {
let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000)); let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000));
let mut data = [0u8; 1]; let mut data = [0u8; 1];
unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data)); unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
info!("Whoami: {}", data[0]); info!("Whoami: {}", data[0]);
} }

View file

@ -6,7 +6,6 @@
mod example_common; mod example_common;
use embassy::executor::Spawner; use embassy::executor::Spawner;
use embassy::traits::i2c::I2c as I2cTrait;
use embassy_stm32::i2c::I2c; use embassy_stm32::i2c::I2c;
use embassy_stm32::interrupt; use embassy_stm32::interrupt;
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;