190 lines
5.3 KiB
Rust
190 lines
5.3 KiB
Rust
#![macro_use]
|
|
|
|
use core::marker::PhantomData;
|
|
|
|
use crate::dma::NoDma;
|
|
use crate::interrupt;
|
|
|
|
#[cfg_attr(i2c_v1, path = "v1.rs")]
|
|
#[cfg_attr(i2c_v2, path = "v2.rs")]
|
|
mod _version;
|
|
pub use _version::*;
|
|
use embassy_sync::waitqueue::AtomicWaker;
|
|
|
|
use crate::peripherals;
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum Error {
|
|
Bus,
|
|
Arbitration,
|
|
Nack,
|
|
Timeout,
|
|
Crc,
|
|
Overrun,
|
|
ZeroLengthTransfer,
|
|
}
|
|
|
|
pub(crate) mod sealed {
|
|
use super::*;
|
|
|
|
pub struct State {
|
|
#[allow(unused)]
|
|
pub waker: AtomicWaker,
|
|
}
|
|
|
|
impl State {
|
|
pub const fn new() -> Self {
|
|
Self {
|
|
waker: AtomicWaker::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait Instance: crate::rcc::RccPeripheral {
|
|
fn regs() -> crate::pac::i2c::I2c;
|
|
fn state() -> &'static State;
|
|
}
|
|
}
|
|
|
|
pub trait Instance: sealed::Instance + 'static {
|
|
type EventInterrupt: interrupt::typelevel::Interrupt;
|
|
type ErrorInterrupt: interrupt::typelevel::Interrupt;
|
|
}
|
|
|
|
pin_trait!(SclPin, Instance);
|
|
pin_trait!(SdaPin, Instance);
|
|
dma_trait!(RxDma, Instance);
|
|
dma_trait!(TxDma, Instance);
|
|
|
|
/// Interrupt handler.
|
|
pub struct EventInterruptHandler<T: Instance> {
|
|
_phantom: PhantomData<T>,
|
|
}
|
|
|
|
impl<T: Instance> interrupt::typelevel::Handler<T::EventInterrupt> for EventInterruptHandler<T> {
|
|
unsafe fn on_interrupt() {
|
|
_version::on_interrupt::<T>()
|
|
}
|
|
}
|
|
|
|
pub struct ErrorInterruptHandler<T: Instance> {
|
|
_phantom: PhantomData<T>,
|
|
}
|
|
|
|
impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInterruptHandler<T> {
|
|
unsafe fn on_interrupt() {
|
|
_version::on_interrupt::<T>()
|
|
}
|
|
}
|
|
|
|
foreach_peripheral!(
|
|
(i2c, $inst:ident) => {
|
|
impl sealed::Instance for peripherals::$inst {
|
|
fn regs() -> crate::pac::i2c::I2c {
|
|
crate::pac::$inst
|
|
}
|
|
|
|
fn state() -> &'static sealed::State {
|
|
static STATE: sealed::State = sealed::State::new();
|
|
&STATE
|
|
}
|
|
}
|
|
|
|
impl Instance for peripherals::$inst {
|
|
type EventInterrupt = crate::_generated::peripheral_interrupts::$inst::EV;
|
|
type ErrorInterrupt = crate::_generated::peripheral_interrupts::$inst::ER;
|
|
}
|
|
};
|
|
);
|
|
|
|
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
|
|
type Error = Error;
|
|
|
|
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.blocking_read(address, buffer)
|
|
}
|
|
}
|
|
|
|
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> {
|
|
type Error = Error;
|
|
|
|
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
|
|
self.blocking_write(address, write)
|
|
}
|
|
}
|
|
|
|
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> {
|
|
type Error = Error;
|
|
|
|
fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.blocking_write_read(address, write, read)
|
|
}
|
|
}
|
|
|
|
impl embedded_hal_1::i2c::Error for Error {
|
|
fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
|
|
match *self {
|
|
Self::Bus => embedded_hal_1::i2c::ErrorKind::Bus,
|
|
Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
|
|
Self::Nack => {
|
|
embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown)
|
|
}
|
|
Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other,
|
|
Self::Crc => embedded_hal_1::i2c::ErrorKind::Other,
|
|
Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
|
|
Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> {
|
|
type Error = Error;
|
|
}
|
|
|
|
impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> {
|
|
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.blocking_read(address, read)
|
|
}
|
|
|
|
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
|
|
self.blocking_write(address, write)
|
|
}
|
|
|
|
fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.blocking_write_read(address, write, read)
|
|
}
|
|
|
|
fn transaction(
|
|
&mut self,
|
|
_address: u8,
|
|
_operations: &mut [embedded_hal_1::i2c::Operation<'_>],
|
|
) -> Result<(), Self::Error> {
|
|
todo!();
|
|
}
|
|
}
|
|
|
|
impl<'d, T: Instance, TXDMA: TxDma<T>, RXDMA: RxDma<T>> embedded_hal_async::i2c::I2c for I2c<'d, T, TXDMA, RXDMA> {
|
|
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.read(address, read).await
|
|
}
|
|
|
|
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
|
|
self.write(address, write).await
|
|
}
|
|
|
|
async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
|
self.write_read(address, write, read).await
|
|
}
|
|
|
|
async fn transaction(
|
|
&mut self,
|
|
address: u8,
|
|
operations: &mut [embedded_hal_1::i2c::Operation<'_>],
|
|
) -> Result<(), Self::Error> {
|
|
let _ = address;
|
|
let _ = operations;
|
|
todo!()
|
|
}
|
|
}
|