stm32/i2c: remove DMA generic params.

This commit is contained in:
Dario Nieuwenhuis 2024-04-15 23:40:12 +02:00
parent 2eab099b85
commit 913bb19a34
8 changed files with 312 additions and 395 deletions

View File

@ -14,9 +14,10 @@ use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")]
use embassy_time::{Duration, Instant};
use crate::dma::NoDma;
use crate::dma::ChannelAndRequest;
use crate::gpio::{AFType, Pull};
use crate::interrupt::typelevel::Interrupt;
use crate::mode::{Async, Blocking, Mode};
use crate::time::Hertz;
use crate::{interrupt, peripherals};
@ -71,17 +72,16 @@ impl Default for Config {
}
/// I2C driver.
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
pub struct I2c<'d, T: Instance, M: Mode> {
_peri: PeripheralRef<'d, T>,
#[allow(dead_code)]
tx_dma: PeripheralRef<'d, TXDMA>,
#[allow(dead_code)]
rx_dma: PeripheralRef<'d, RXDMA>,
tx_dma: Option<ChannelAndRequest<'d>>,
rx_dma: Option<ChannelAndRequest<'d>>,
#[cfg(feature = "time")]
timeout: Duration,
_phantom: PhantomData<M>,
}
impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance> I2c<'d, T, Async> {
/// Create a new I2C driver.
pub fn new(
peri: impl Peripheral<P = T> + 'd,
@ -90,12 +90,40 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
_irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
+ interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
+ 'd,
tx_dma: impl Peripheral<P = TXDMA> + 'd,
rx_dma: impl Peripheral<P = RXDMA> + 'd,
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
freq: Hertz,
config: Config,
) -> Self {
into_ref!(peri, scl, sda, tx_dma, rx_dma);
Self::new_inner(peri, scl, sda, new_dma!(tx_dma), new_dma!(rx_dma), freq, config)
}
}
impl<'d, T: Instance> I2c<'d, T, Blocking> {
/// Create a new blocking I2C driver.
pub fn new_blocking(
peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
freq: Hertz,
config: Config,
) -> Self {
Self::new_inner(peri, scl, sda, None, None, freq, config)
}
}
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
/// Create a new I2C driver.
fn new_inner(
peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
tx_dma: Option<ChannelAndRequest<'d>>,
rx_dma: Option<ChannelAndRequest<'d>>,
freq: Hertz,
config: Config,
) -> Self {
into_ref!(peri, scl, sda);
T::enable_and_reset();
@ -125,6 +153,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
rx_dma,
#[cfg(feature = "time")]
timeout: config.timeout,
_phantom: PhantomData,
};
this.init(freq, config);
@ -249,7 +278,7 @@ foreach_peripheral!(
};
);
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> {
type Error = Error;
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
@ -257,7 +286,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> {
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> {
type Error = Error;
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
@ -265,7 +294,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> {
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> {
type Error = Error;
fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@ -289,11 +318,11 @@ impl embedded_hal_1::i2c::Error for Error {
}
}
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> {
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(address, read)
}
@ -315,7 +344,7 @@ impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> {
}
}
impl<'d, T: Instance, TXDMA: TxDma<T>, RXDMA: RxDma<T>> embedded_hal_async::i2c::I2c for I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for I2c<'d, T, Async> {
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.read(address, read).await
}

View File

@ -13,7 +13,7 @@ use embassy_hal_internal::drop::OnDrop;
use embedded_hal_1::i2c::Operation;
use super::*;
use crate::dma::Transfer;
use crate::mode::Mode as PeriMode;
use crate::pac::i2c;
// /!\ /!\
@ -41,7 +41,7 @@ pub unsafe fn on_interrupt<T: Instance>() {
});
}
impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
T::regs().cr1().modify(|reg| {
reg.set_pe(false);
@ -326,11 +326,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
w.set_itevten(true);
});
}
}
async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
impl<'d, T: Instance> I2c<'d, T, Async> {
async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
T::regs().cr2().modify(|w| {
// Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
// reception.
@ -415,9 +414,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// this address from the memory after each TxE event.
let dst = T::regs().dr().as_ptr() as *mut u8;
let ch = &mut self.tx_dma;
let request = ch.request();
Transfer::new_write(ch, request, write, dst, Default::default())
self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
};
// Wait for bytes to be sent, or an error to occur.
@ -479,10 +476,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
}
/// Write.
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
.await?;
@ -490,20 +484,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
}
/// Read.
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
.await?;
Ok(())
}
async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> {
if buffer.is_empty() {
return Err(Error::Overrun);
}
@ -623,9 +611,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
// from this address from the memory after each RxE event.
let src = T::regs().dr().as_ptr() as *mut u8;
let ch = &mut self.rx_dma;
let request = ch.request();
Transfer::new_read(ch, request, src, buffer, Default::default())
self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
};
// Wait for bytes to be received, or an error to occur.
@ -664,11 +650,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
}
/// Write, restart, read.
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
TXDMA: crate::i2c::TxDma<T>,
{
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
// Check empty read buffer before starting transaction. Otherwise, we would not generate the
// stop condition below.
if read.is_empty() {
@ -684,11 +666,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
/// Consecutive operations of same type are merged. See [transaction contract] for details.
///
/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
TXDMA: crate::i2c::TxDma<T>,
{
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
for (op, frame) in operation_frames(operations)? {
match op {
Operation::Read(read) => self.read_frame(addr, read, frame).await?,
@ -700,7 +678,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
}
}
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance, M: PeriMode> Drop for I2c<'d, T, M> {
fn drop(&mut self) {
T::disable();
}
@ -806,7 +784,7 @@ impl Timings {
}
}
impl<'d, T: Instance> SetConfig for I2c<'d, T> {
impl<'d, T: Instance, M: PeriMode> SetConfig for I2c<'d, T, M> {
type Config = Hertz;
type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {

View File

@ -7,7 +7,6 @@ use embassy_hal_internal::drop::OnDrop;
use embedded_hal_1::i2c::Operation;
use super::*;
use crate::dma::Transfer;
use crate::pac::i2c;
pub(crate) unsafe fn on_interrupt<T: Instance>() {
@ -24,7 +23,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
});
}
impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
T::regs().cr1().modify(|reg| {
reg.set_pe(false);
@ -302,276 +301,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
result
}
async fn write_dma_internal(
&mut self,
address: u8,
write: &[u8],
first_slice: bool,
last_slice: bool,
timeout: Timeout,
) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
let total_len = write.len();
let dma_transfer = unsafe {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_txdmaen(true);
if first_slice {
w.set_tcie(true);
}
});
let dst = regs.txdr().as_ptr() as *mut u8;
let ch = &mut self.tx_dma;
let request = ch.request();
Transfer::new_write(ch, request, write, dst, Default::default())
};
let state = T::state();
let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| {
let regs = T::regs();
regs.cr1().modify(|w| {
if last_slice {
w.set_txdmaen(false);
}
w.set_tcie(false);
})
});
poll_fn(|cx| {
state.waker.register(cx.waker());
let isr = T::regs().isr().read();
if remaining_len == total_len {
if first_slice {
Self::master_write(
address,
total_len.min(255),
Stop::Software,
(total_len > 255) || !last_slice,
timeout,
)?;
} else {
Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
T::regs().cr1().modify(|w| w.set_tcie(true));
}
} else if !(isr.tcr() || isr.tc()) {
// poll_fn was woken without an interrupt present
return Poll::Pending;
} else if remaining_len == 0 {
return Poll::Ready(Ok(()));
} else {
let last_piece = (remaining_len <= 255) && last_slice;
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
return Poll::Ready(Err(e));
}
T::regs().cr1().modify(|w| w.set_tcie(true));
}
remaining_len = remaining_len.saturating_sub(255);
Poll::Pending
})
.await?;
dma_transfer.await;
if last_slice {
// This should be done already
self.wait_tc(timeout)?;
self.master_stop();
}
drop(on_drop);
Ok(())
}
async fn read_dma_internal(
&mut self,
address: u8,
buffer: &mut [u8],
restart: bool,
timeout: Timeout,
) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
let total_len = buffer.len();
let dma_transfer = unsafe {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_rxdmaen(true);
w.set_tcie(true);
});
let src = regs.rxdr().as_ptr() as *mut u8;
let ch = &mut self.rx_dma;
let request = ch.request();
Transfer::new_read(ch, request, src, buffer, Default::default())
};
let state = T::state();
let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_rxdmaen(false);
w.set_tcie(false);
})
});
poll_fn(|cx| {
state.waker.register(cx.waker());
let isr = T::regs().isr().read();
if remaining_len == total_len {
Self::master_read(
address,
total_len.min(255),
Stop::Software,
total_len > 255,
restart,
timeout,
)?;
} else if !(isr.tcr() || isr.tc()) {
// poll_fn was woken without an interrupt present
return Poll::Pending;
} else if remaining_len == 0 {
return Poll::Ready(Ok(()));
} else {
let last_piece = remaining_len <= 255;
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
return Poll::Ready(Err(e));
}
T::regs().cr1().modify(|w| w.set_tcie(true));
}
remaining_len = remaining_len.saturating_sub(255);
Poll::Pending
})
.await?;
dma_transfer.await;
// This should be done already
self.wait_tc(timeout)?;
self.master_stop();
drop(on_drop);
Ok(())
}
// =========================
// Async public API
/// Write.
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
let timeout = self.timeout();
if write.is_empty() {
self.write_internal(address, write, true, timeout)
} else {
timeout
.with(self.write_dma_internal(address, write, true, true, timeout))
.await
}
}
/// Write multiple buffers.
///
/// The buffers are concatenated in a single write transaction.
pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
where
TXDMA: crate::i2c::TxDma<T>,
{
let timeout = self.timeout();
if write.is_empty() {
return Err(Error::ZeroLengthTransfer);
}
let mut iter = write.iter();
let mut first = true;
let mut current = iter.next();
while let Some(c) = current {
let next = iter.next();
let is_last = next.is_none();
let fut = self.write_dma_internal(address, c, first, is_last, timeout);
timeout.with(fut).await?;
first = false;
current = next;
}
Ok(())
}
/// Read.
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
{
let timeout = self.timeout();
if buffer.is_empty() {
self.read_internal(address, buffer, false, timeout)
} else {
let fut = self.read_dma_internal(address, buffer, false, timeout);
timeout.with(fut).await
}
}
/// Write, restart, read.
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
where
TXDMA: super::TxDma<T>,
RXDMA: super::RxDma<T>,
{
let timeout = self.timeout();
if write.is_empty() {
self.write_internal(address, write, false, timeout)?;
} else {
let fut = self.write_dma_internal(address, write, true, true, timeout);
timeout.with(fut).await?;
}
if read.is_empty() {
self.read_internal(address, read, true, timeout)?;
} else {
let fut = self.read_dma_internal(address, read, true, timeout);
timeout.with(fut).await?;
}
Ok(())
}
/// Transaction with operations.
///
/// Consecutive operations of same type are merged. See [transaction contract] for details.
///
/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error>
where
RXDMA: crate::i2c::RxDma<T>,
TXDMA: crate::i2c::TxDma<T>,
{
let _ = addr;
let _ = operations;
todo!()
}
// =========================
// Blocking public API
@ -684,7 +413,252 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
}
}
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
impl<'d, T: Instance> I2c<'d, T, Async> {
async fn write_dma_internal(
&mut self,
address: u8,
write: &[u8],
first_slice: bool,
last_slice: bool,
timeout: Timeout,
) -> Result<(), Error> {
let total_len = write.len();
let dma_transfer = unsafe {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_txdmaen(true);
if first_slice {
w.set_tcie(true);
}
});
let dst = regs.txdr().as_ptr() as *mut u8;
self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
};
let state = T::state();
let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| {
let regs = T::regs();
regs.cr1().modify(|w| {
if last_slice {
w.set_txdmaen(false);
}
w.set_tcie(false);
})
});
poll_fn(|cx| {
state.waker.register(cx.waker());
let isr = T::regs().isr().read();
if remaining_len == total_len {
if first_slice {
Self::master_write(
address,
total_len.min(255),
Stop::Software,
(total_len > 255) || !last_slice,
timeout,
)?;
} else {
Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
T::regs().cr1().modify(|w| w.set_tcie(true));
}
} else if !(isr.tcr() || isr.tc()) {
// poll_fn was woken without an interrupt present
return Poll::Pending;
} else if remaining_len == 0 {
return Poll::Ready(Ok(()));
} else {
let last_piece = (remaining_len <= 255) && last_slice;
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
return Poll::Ready(Err(e));
}
T::regs().cr1().modify(|w| w.set_tcie(true));
}
remaining_len = remaining_len.saturating_sub(255);
Poll::Pending
})
.await?;
dma_transfer.await;
if last_slice {
// This should be done already
self.wait_tc(timeout)?;
self.master_stop();
}
drop(on_drop);
Ok(())
}
async fn read_dma_internal(
&mut self,
address: u8,
buffer: &mut [u8],
restart: bool,
timeout: Timeout,
) -> Result<(), Error> {
let total_len = buffer.len();
let dma_transfer = unsafe {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_rxdmaen(true);
w.set_tcie(true);
});
let src = regs.rxdr().as_ptr() as *mut u8;
self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
};
let state = T::state();
let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| {
let regs = T::regs();
regs.cr1().modify(|w| {
w.set_rxdmaen(false);
w.set_tcie(false);
})
});
poll_fn(|cx| {
state.waker.register(cx.waker());
let isr = T::regs().isr().read();
if remaining_len == total_len {
Self::master_read(
address,
total_len.min(255),
Stop::Software,
total_len > 255,
restart,
timeout,
)?;
} else if !(isr.tcr() || isr.tc()) {
// poll_fn was woken without an interrupt present
return Poll::Pending;
} else if remaining_len == 0 {
return Poll::Ready(Ok(()));
} else {
let last_piece = remaining_len <= 255;
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
return Poll::Ready(Err(e));
}
T::regs().cr1().modify(|w| w.set_tcie(true));
}
remaining_len = remaining_len.saturating_sub(255);
Poll::Pending
})
.await?;
dma_transfer.await;
// This should be done already
self.wait_tc(timeout)?;
self.master_stop();
drop(on_drop);
Ok(())
}
// =========================
// Async public API
/// Write.
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
let timeout = self.timeout();
if write.is_empty() {
self.write_internal(address, write, true, timeout)
} else {
timeout
.with(self.write_dma_internal(address, write, true, true, timeout))
.await
}
}
/// Write multiple buffers.
///
/// The buffers are concatenated in a single write transaction.
pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
let timeout = self.timeout();
if write.is_empty() {
return Err(Error::ZeroLengthTransfer);
}
let mut iter = write.iter();
let mut first = true;
let mut current = iter.next();
while let Some(c) = current {
let next = iter.next();
let is_last = next.is_none();
let fut = self.write_dma_internal(address, c, first, is_last, timeout);
timeout.with(fut).await?;
first = false;
current = next;
}
Ok(())
}
/// Read.
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
let timeout = self.timeout();
if buffer.is_empty() {
self.read_internal(address, buffer, false, timeout)
} else {
let fut = self.read_dma_internal(address, buffer, false, timeout);
timeout.with(fut).await
}
}
/// Write, restart, read.
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
let timeout = self.timeout();
if write.is_empty() {
self.write_internal(address, write, false, timeout)?;
} else {
let fut = self.write_dma_internal(address, write, true, true, timeout);
timeout.with(fut).await?;
}
if read.is_empty() {
self.read_internal(address, read, true, timeout)?;
} else {
let fut = self.read_dma_internal(address, read, true, timeout);
timeout.with(fut).await?;
}
Ok(())
}
/// Transaction with operations.
///
/// Consecutive operations of same type are merged. See [transaction contract] for details.
///
/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
let _ = addr;
let _ = operations;
todo!()
}
}
impl<'d, T: Instance, M: Mode> Drop for I2c<'d, T, M> {
fn drop(&mut self) {
T::disable();
}
@ -814,7 +788,7 @@ impl Timings {
}
}
impl<'d, T: Instance> SetConfig for I2c<'d, T> {
impl<'d, T: Instance, M: Mode> SetConfig for I2c<'d, T, M> {
type Config = Hertz;
type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {

View File

@ -3,35 +3,19 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::dma::NoDma;
use embassy_stm32::i2c::{Error, I2c};
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, i2c, peripherals};
use {defmt_rtt as _, panic_probe as _};
const ADDRESS: u8 = 0x5F;
const WHOAMI: u8 = 0x0F;
bind_interrupts!(struct Irqs {
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Hello world!");
let p = embassy_stm32::init(Default::default());
let mut i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
Irqs,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
let mut data = [0u8; 1];

View File

@ -3,33 +3,17 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::dma::NoDma;
use embassy_stm32::i2c::I2c;
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, i2c, peripherals};
use {defmt_rtt as _, panic_probe as _};
const ADDRESS: u8 = 0x5F;
const WHOAMI: u8 = 0x0F;
bind_interrupts!(struct Irqs {
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let mut i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
Irqs,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
let mut data = [0u8; 1];
unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));

View File

@ -4,34 +4,18 @@
use defmt::*;
use embassy_embedded_hal::adapter::BlockingAsync;
use embassy_executor::Spawner;
use embassy_stm32::dma::NoDma;
use embassy_stm32::i2c::I2c;
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, i2c, peripherals};
use embedded_hal_async::i2c::I2c as I2cTrait;
use {defmt_rtt as _, panic_probe as _};
const ADDRESS: u8 = 0x5F;
const WHOAMI: u8 = 0x0F;
bind_interrupts!(struct Irqs {
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
Irqs,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
let mut i2c = BlockingAsync::new(i2c);
let mut data = [0u8; 1];

View File

@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
pub type SpeInt = exti::ExtiInput<'static>;
pub type SpeRst = Output<'static>;
pub type Adin1110T = ADIN1110<SpeSpiCs>;
pub type TempSensI2c = I2c<'static, peripherals::I2C3, peripherals::DMA1_CH6, peripherals::DMA1_CH7>;
pub type TempSensI2c = I2c<'static, peripherals::I2C3, Async>;
static TEMP: AtomicI32 = AtomicI32::new(0);

View File

@ -3,33 +3,17 @@
use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_stm32::dma::NoDma;
use embassy_stm32::i2c::I2c;
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, i2c, peripherals};
use {defmt_rtt as _, panic_probe as _};
const HTS221_ADDRESS: u8 = 0x5F;
const WHOAMI: u8 = 0x0F;
bind_interrupts!(struct Irqs {
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let mut i2c = I2c::new(
p.I2C2,
p.PH4,
p.PH5,
Irqs,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let mut i2c = I2c::new_blocking(p.I2C2, p.PH4, p.PH5, Hertz(100_000), Default::default());
let mut data = [0u8; 1];
unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data));