Merge pull request #2820 from embassy-rs/i2c-nodma
stm32/i2c: remove DMA generic params.
This commit is contained in:
commit
76bf3f733d
13 changed files with 417 additions and 438 deletions
|
@ -16,6 +16,9 @@ mod dmamux;
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
pub use dmamux::*;
|
pub use dmamux::*;
|
||||||
|
|
||||||
|
mod util;
|
||||||
|
pub(crate) use util::*;
|
||||||
|
|
||||||
pub(crate) mod ringbuffer;
|
pub(crate) mod ringbuffer;
|
||||||
pub mod word;
|
pub mod word;
|
||||||
|
|
||||||
|
|
60
embassy-stm32/src/dma/util.rs
Normal file
60
embassy-stm32/src/dma/util.rs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
use embassy_hal_internal::PeripheralRef;
|
||||||
|
|
||||||
|
use super::word::Word;
|
||||||
|
use super::{AnyChannel, Request, Transfer, TransferOptions};
|
||||||
|
|
||||||
|
/// Convenience wrapper, contains a channel and a request number.
|
||||||
|
///
|
||||||
|
/// Commonly used in peripheral drivers that own DMA channels.
|
||||||
|
pub(crate) struct ChannelAndRequest<'d> {
|
||||||
|
pub channel: PeripheralRef<'d, AnyChannel>,
|
||||||
|
pub request: Request,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> ChannelAndRequest<'d> {
|
||||||
|
pub unsafe fn read<'a, W: Word>(
|
||||||
|
&'a mut self,
|
||||||
|
peri_addr: *mut W,
|
||||||
|
buf: &'a mut [W],
|
||||||
|
options: TransferOptions,
|
||||||
|
) -> Transfer<'a> {
|
||||||
|
Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn read_raw<'a, W: Word>(
|
||||||
|
&'a mut self,
|
||||||
|
peri_addr: *mut W,
|
||||||
|
buf: *mut [W],
|
||||||
|
options: TransferOptions,
|
||||||
|
) -> Transfer<'a> {
|
||||||
|
Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn write<'a, W: Word>(
|
||||||
|
&'a mut self,
|
||||||
|
buf: &'a [W],
|
||||||
|
peri_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
|
) -> Transfer<'a> {
|
||||||
|
Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn write_raw<'a, W: Word>(
|
||||||
|
&'a mut self,
|
||||||
|
buf: *const [W],
|
||||||
|
peri_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
|
) -> Transfer<'a> {
|
||||||
|
Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn write_repeated<'a, W: Word>(
|
||||||
|
&'a mut self,
|
||||||
|
repeated: &'a W,
|
||||||
|
count: usize,
|
||||||
|
peri_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
|
) -> Transfer<'a> {
|
||||||
|
Transfer::new_write_repeated(&mut self.channel, self.request, repeated, count, peri_addr, options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,9 +14,10 @@ use embassy_sync::waitqueue::AtomicWaker;
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
use embassy_time::{Duration, Instant};
|
use embassy_time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::dma::NoDma;
|
use crate::dma::ChannelAndRequest;
|
||||||
use crate::gpio::{AFType, Pull};
|
use crate::gpio::{AFType, Pull};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
|
use crate::mode::{Async, Blocking, Mode};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{interrupt, peripherals};
|
use crate::{interrupt, peripherals};
|
||||||
|
|
||||||
|
@ -71,17 +72,16 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// I2C driver.
|
/// I2C driver.
|
||||||
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
|
pub struct I2c<'d, T: Instance, M: Mode> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
#[allow(dead_code)]
|
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
tx_dma: PeripheralRef<'d, TXDMA>,
|
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
#[allow(dead_code)]
|
|
||||||
rx_dma: PeripheralRef<'d, RXDMA>,
|
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
timeout: Duration,
|
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.
|
/// Create a new I2C driver.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
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>>
|
_irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
|
||||||
+ interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
|
+ interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
|
||||||
+ 'd,
|
+ 'd,
|
||||||
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> 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();
|
T::enable_and_reset();
|
||||||
|
|
||||||
|
@ -125,6 +153,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
rx_dma,
|
rx_dma,
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
timeout: config.timeout,
|
timeout: config.timeout,
|
||||||
|
_phantom: PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.init(freq, config);
|
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;
|
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> {
|
||||||
|
@ -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;
|
type Error = Error;
|
||||||
|
|
||||||
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::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;
|
type Error = Error;
|
||||||
|
|
||||||
fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::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;
|
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> {
|
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
self.blocking_read(address, read)
|
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> {
|
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
self.read(address, read).await
|
self.read(address, read).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use embassy_hal_internal::drop::OnDrop;
|
||||||
use embedded_hal_1::i2c::Operation;
|
use embedded_hal_1::i2c::Operation;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::dma::Transfer;
|
use crate::mode::Mode as PeriMode;
|
||||||
use crate::pac::i2c;
|
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) {
|
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
|
||||||
T::regs().cr1().modify(|reg| {
|
T::regs().cr1().modify(|reg| {
|
||||||
reg.set_pe(false);
|
reg.set_pe(false);
|
||||||
|
@ -326,11 +326,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
w.set_itevten(true);
|
w.set_itevten(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error>
|
impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||||
where
|
async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
|
||||||
TXDMA: crate::i2c::TxDma<T>,
|
|
||||||
{
|
|
||||||
T::regs().cr2().modify(|w| {
|
T::regs().cr2().modify(|w| {
|
||||||
// Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
|
// Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
|
||||||
// reception.
|
// 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.
|
// this address from the memory after each TxE event.
|
||||||
let dst = T::regs().dr().as_ptr() as *mut u8;
|
let dst = T::regs().dr().as_ptr() as *mut u8;
|
||||||
|
|
||||||
let ch = &mut self.tx_dma;
|
self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
|
||||||
let request = ch.request();
|
|
||||||
Transfer::new_write(ch, request, write, dst, Default::default())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wait for bytes to be sent, or an error to occur.
|
// 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.
|
/// Write.
|
||||||
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
|
pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
|
||||||
where
|
|
||||||
TXDMA: crate::i2c::TxDma<T>,
|
|
||||||
{
|
|
||||||
self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
|
self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -490,20 +484,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read.
|
/// Read.
|
||||||
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
|
pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
where
|
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
|
||||||
{
|
|
||||||
self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
|
self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error>
|
async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> {
|
||||||
where
|
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
|
||||||
{
|
|
||||||
if buffer.is_empty() {
|
if buffer.is_empty() {
|
||||||
return Err(Error::Overrun);
|
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.
|
// from this address from the memory after each RxE event.
|
||||||
let src = T::regs().dr().as_ptr() as *mut u8;
|
let src = T::regs().dr().as_ptr() as *mut u8;
|
||||||
|
|
||||||
let ch = &mut self.rx_dma;
|
self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
|
||||||
let request = ch.request();
|
|
||||||
Transfer::new_read(ch, request, src, buffer, Default::default())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wait for bytes to be received, or an error to occur.
|
// 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.
|
/// Write, restart, read.
|
||||||
pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
|
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>,
|
|
||||||
{
|
|
||||||
// Check empty read buffer before starting transaction. Otherwise, we would not generate the
|
// Check empty read buffer before starting transaction. Otherwise, we would not generate the
|
||||||
// stop condition below.
|
// stop condition below.
|
||||||
if read.is_empty() {
|
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.
|
/// Consecutive operations of same type are merged. See [transaction contract] for details.
|
||||||
///
|
///
|
||||||
/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
|
/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
|
||||||
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error>
|
pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
|
||||||
where
|
|
||||||
RXDMA: crate::i2c::RxDma<T>,
|
|
||||||
TXDMA: crate::i2c::TxDma<T>,
|
|
||||||
{
|
|
||||||
for (op, frame) in operation_frames(operations)? {
|
for (op, frame) in operation_frames(operations)? {
|
||||||
match op {
|
match op {
|
||||||
Operation::Read(read) => self.read_frame(addr, read, frame).await?,
|
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) {
|
fn drop(&mut self) {
|
||||||
T::disable();
|
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 Config = Hertz;
|
||||||
type ConfigError = ();
|
type ConfigError = ();
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||||
|
|
|
@ -7,7 +7,6 @@ use embassy_hal_internal::drop::OnDrop;
|
||||||
use embedded_hal_1::i2c::Operation;
|
use embedded_hal_1::i2c::Operation;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::dma::Transfer;
|
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
|
|
||||||
pub(crate) unsafe fn on_interrupt<T: Instance>() {
|
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) {
|
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
|
||||||
T::regs().cr1().modify(|reg| {
|
T::regs().cr1().modify(|reg| {
|
||||||
reg.set_pe(false);
|
reg.set_pe(false);
|
||||||
|
@ -302,276 +301,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||||
result
|
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
|
// 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) {
|
fn drop(&mut self) {
|
||||||
T::disable();
|
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 Config = Hertz;
|
||||||
type ConfigError = ();
|
type ConfigError = ();
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||||
|
|
|
@ -15,8 +15,8 @@ mod fmt;
|
||||||
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
mod macros;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
mod traits;
|
|
||||||
/// Operating modes for peripherals.
|
/// Operating modes for peripherals.
|
||||||
pub mod mode {
|
pub mod mode {
|
||||||
trait SealedMode {}
|
trait SealedMode {}
|
||||||
|
|
|
@ -73,8 +73,11 @@ macro_rules! dma_trait_impl {
|
||||||
macro_rules! new_dma {
|
macro_rules! new_dma {
|
||||||
($name:ident) => {{
|
($name:ident) => {{
|
||||||
let dma = $name.into_ref();
|
let dma = $name.into_ref();
|
||||||
let req = dma.request();
|
let request = dma.request();
|
||||||
Some((dma.map_into(), req))
|
Some(crate::dma::ChannelAndRequest {
|
||||||
|
channel: dma.map_into(),
|
||||||
|
request,
|
||||||
|
})
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use embassy_futures::join::join;
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||||
|
|
||||||
use crate::dma::{slice_ptr_parts, word, AnyChannel, Request, Transfer};
|
use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
|
||||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
||||||
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
||||||
use crate::pac::spi::{regs, vals, Spi as Regs};
|
use crate::pac::spi::{regs, vals, Spi as Regs};
|
||||||
|
@ -97,8 +97,8 @@ pub struct Spi<'d, T: Instance, M: PeriMode> {
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
_phantom: PhantomData<M>,
|
_phantom: PhantomData<M>,
|
||||||
current_word_size: word_impl::Config,
|
current_word_size: word_impl::Config,
|
||||||
}
|
}
|
||||||
|
@ -109,8 +109,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri);
|
into_ref!(peri);
|
||||||
|
@ -209,8 +209,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||||
sck,
|
sck,
|
||||||
mosi,
|
mosi,
|
||||||
miso,
|
miso,
|
||||||
txdma,
|
tx_dma,
|
||||||
rxdma,
|
rx_dma,
|
||||||
current_word_size: <u8 as SealedWord>::CONFIG,
|
current_word_size: <u8 as SealedWord>::CONFIG,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -479,8 +479,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
|
@ -488,8 +488,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||||
new_dma!(txdma),
|
new_dma!(tx_dma),
|
||||||
new_dma!(rxdma),
|
new_dma!(rx_dma),
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
|
@ -508,7 +508,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
None,
|
None,
|
||||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||||
None,
|
None,
|
||||||
new_dma!(rxdma),
|
new_dma!(rx_dma),
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -518,7 +518,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
|
@ -526,7 +526,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
None,
|
None,
|
||||||
new_dma!(txdma),
|
new_dma!(tx_dma),
|
||||||
None,
|
None,
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
|
@ -538,7 +538,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
pub fn new_txonly_nosck(
|
pub fn new_txonly_nosck(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
|
@ -546,7 +546,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
None,
|
None,
|
||||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||||
None,
|
None,
|
||||||
new_dma!(txdma),
|
new_dma!(tx_dma),
|
||||||
None,
|
None,
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
|
@ -556,8 +556,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
/// Useful for on chip peripherals like SUBGHZ which are hardwired.
|
/// Useful for on chip peripherals like SUBGHZ which are hardwired.
|
||||||
pub fn new_subghz(
|
pub fn new_subghz(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// see RM0453 rev 1 section 7.2.13 page 291
|
// see RM0453 rev 1 section 7.2.13 page 291
|
||||||
// The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
|
// The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
|
||||||
|
@ -569,17 +569,17 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
config.bit_order = BitOrder::MsbFirst;
|
config.bit_order = BitOrder::MsbFirst;
|
||||||
config.frequency = freq;
|
config.frequency = freq;
|
||||||
|
|
||||||
Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config)
|
Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn new_internal(
|
pub(crate) fn new_internal(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config)
|
Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI write, using DMA.
|
/// SPI write, using DMA.
|
||||||
|
@ -593,9 +593,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
w.set_spe(false);
|
w.set_spe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
|
||||||
let tx_dst = T::REGS.tx_ptr();
|
let tx_dst = T::REGS.tx_ptr();
|
||||||
let tx_f = unsafe { Transfer::new_write(txdma, *tx_request, data, tx_dst, Default::default()) };
|
let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
|
||||||
|
|
||||||
set_txdmaen(T::REGS, true);
|
set_txdmaen(T::REGS, true);
|
||||||
T::REGS.cr1().modify(|w| {
|
T::REGS.cr1().modify(|w| {
|
||||||
|
@ -632,22 +631,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
|
|
||||||
let clock_byte_count = data.len();
|
let clock_byte_count = data.len();
|
||||||
|
|
||||||
let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
|
|
||||||
let rx_src = T::REGS.rx_ptr();
|
let rx_src = T::REGS.rx_ptr();
|
||||||
let rx_f = unsafe { Transfer::new_read(rxdma, *rx_request, rx_src, data, Default::default()) };
|
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
|
||||||
|
|
||||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
|
||||||
let tx_dst = T::REGS.tx_ptr();
|
let tx_dst = T::REGS.tx_ptr();
|
||||||
let clock_byte = 0x00u8;
|
let clock_byte = 0x00u8;
|
||||||
let tx_f = unsafe {
|
let tx_f = unsafe {
|
||||||
Transfer::new_write_repeated(
|
self.tx_dma
|
||||||
txdma,
|
.as_mut()
|
||||||
*tx_request,
|
.unwrap()
|
||||||
&clock_byte,
|
.write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
|
||||||
clock_byte_count,
|
|
||||||
tx_dst,
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
set_txdmaen(T::REGS, true);
|
set_txdmaen(T::REGS, true);
|
||||||
|
@ -685,13 +678,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||||
|
|
||||||
set_rxdmaen(T::REGS, true);
|
set_rxdmaen(T::REGS, true);
|
||||||
|
|
||||||
let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
|
|
||||||
let rx_src = T::REGS.rx_ptr();
|
let rx_src = T::REGS.rx_ptr();
|
||||||
let rx_f = unsafe { Transfer::new_read_raw(rxdma, *rx_request, rx_src, read, Default::default()) };
|
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
|
||||||
|
|
||||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
|
||||||
let tx_dst = T::REGS.tx_ptr();
|
let tx_dst = T::REGS.tx_ptr();
|
||||||
let tx_f = unsafe { Transfer::new_write_raw(txdma, *tx_request, write, tx_dst, Default::default()) };
|
let tx_f = unsafe {
|
||||||
|
self.tx_dma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.write_raw(write, tx_dst, Default::default())
|
||||||
|
};
|
||||||
|
|
||||||
set_txdmaen(T::REGS, true);
|
set_txdmaen(T::REGS, true);
|
||||||
T::REGS.cr1().modify(|w| {
|
T::REGS.cr1().modify(|w| {
|
||||||
|
|
|
@ -3,35 +3,19 @@
|
||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::i2c::{Error, I2c};
|
use embassy_stm32::i2c::{Error, I2c};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
|
||||||
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
|
||||||
p.I2C2,
|
|
||||||
p.PB10,
|
|
||||||
p.PB11,
|
|
||||||
Irqs,
|
|
||||||
NoDma,
|
|
||||||
NoDma,
|
|
||||||
Hertz(100_000),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut data = [0u8; 1];
|
let mut data = [0u8; 1];
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,17 @@
|
||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
|
||||||
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
|
||||||
p.I2C2,
|
|
||||||
p.PB10,
|
|
||||||
p.PB11,
|
|
||||||
Irqs,
|
|
||||||
NoDma,
|
|
||||||
NoDma,
|
|
||||||
Hertz(100_000),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut data = [0u8; 1];
|
let mut data = [0u8; 1];
|
||||||
unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
|
unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
|
||||||
|
|
|
@ -4,34 +4,18 @@
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_embedded_hal::adapter::BlockingAsync;
|
use embassy_embedded_hal::adapter::BlockingAsync;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
|
||||||
use embedded_hal_async::i2c::I2c as I2cTrait;
|
use embedded_hal_async::i2c::I2c as I2cTrait;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x5F;
|
const ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
|
||||||
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let i2c = I2c::new(
|
let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
|
||||||
p.I2C2,
|
|
||||||
p.PB10,
|
|
||||||
p.PB11,
|
|
||||||
Irqs,
|
|
||||||
NoDma,
|
|
||||||
NoDma,
|
|
||||||
Hertz(100_000),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
let mut i2c = BlockingAsync::new(i2c);
|
let mut i2c = BlockingAsync::new(i2c);
|
||||||
|
|
||||||
let mut data = [0u8; 1];
|
let mut data = [0u8; 1];
|
||||||
|
|
|
@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
|
||||||
pub type SpeInt = exti::ExtiInput<'static>;
|
pub type SpeInt = exti::ExtiInput<'static>;
|
||||||
pub type SpeRst = Output<'static>;
|
pub type SpeRst = Output<'static>;
|
||||||
pub type Adin1110T = ADIN1110<SpeSpiCs>;
|
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);
|
static TEMP: AtomicI32 = AtomicI32::new(0);
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,17 @@
|
||||||
|
|
||||||
use defmt::{info, unwrap};
|
use defmt::{info, unwrap};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::{bind_interrupts, i2c, peripherals};
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
const HTS221_ADDRESS: u8 = 0x5F;
|
const HTS221_ADDRESS: u8 = 0x5F;
|
||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
|
||||||
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new_blocking(p.I2C2, p.PH4, p.PH5, Hertz(100_000), Default::default());
|
||||||
p.I2C2,
|
|
||||||
p.PH4,
|
|
||||||
p.PH5,
|
|
||||||
Irqs,
|
|
||||||
NoDma,
|
|
||||||
NoDma,
|
|
||||||
Hertz(100_000),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut data = [0u8; 1];
|
let mut data = [0u8; 1];
|
||||||
unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data));
|
unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data));
|
||||||
|
|
Loading…
Add table
Reference in a new issue