stm32/i2c: add async, dual interrupt scaffolding.
This commit is contained in:
parent
e8ff5a2baf
commit
bc65b8f7ec
@ -58,7 +58,7 @@ rand_core = "0.6.3"
|
|||||||
sdio-host = "0.5.0"
|
sdio-host = "0.5.0"
|
||||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b" }
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f6d1ffc1a25f208b5cd6b1024bff246592da1949" }
|
||||||
vcell = "0.1.3"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = "1.0.36"
|
proc-macro2 = "1.0.36"
|
||||||
quote = "1.0.15"
|
quote = "1.0.15"
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b", default-features = false, features = ["metadata"]}
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f6d1ffc1a25f208b5cd6b1024bff246592da1949", default-features = false, features = ["metadata"]}
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -1138,6 +1138,23 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========
|
||||||
|
// Write peripheral_interrupts module.
|
||||||
|
let mut mt = TokenStream::new();
|
||||||
|
for p in METADATA.peripherals {
|
||||||
|
let mut pt = TokenStream::new();
|
||||||
|
|
||||||
|
for irq in p.interrupts {
|
||||||
|
let iname = format_ident!("{}", irq.interrupt);
|
||||||
|
let sname = format_ident!("{}", irq.signal);
|
||||||
|
pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;));
|
||||||
|
}
|
||||||
|
|
||||||
|
let pname = format_ident!("{}", p.name);
|
||||||
|
mt.extend(quote!(pub mod #pname { #pt }));
|
||||||
|
}
|
||||||
|
g.extend(quote!(#[allow(non_camel_case_types)] pub mod peripheral_interrupts { #mt }));
|
||||||
|
|
||||||
// ========
|
// ========
|
||||||
// Write foreach_foo! macrotables
|
// Write foreach_foo! macrotables
|
||||||
|
|
||||||
@ -1296,6 +1313,9 @@ fn main() {
|
|||||||
|
|
||||||
let mut m = String::new();
|
let mut m = String::new();
|
||||||
|
|
||||||
|
// DO NOT ADD more macros like these.
|
||||||
|
// These turned to be a bad idea!
|
||||||
|
// Instead, make build.rs generate the final code.
|
||||||
make_table(&mut m, "foreach_flash_region", &flash_regions_table);
|
make_table(&mut m, "foreach_flash_region", &flash_regions_table);
|
||||||
make_table(&mut m, "foreach_interrupt", &interrupts_table);
|
make_table(&mut m, "foreach_interrupt", &interrupts_table);
|
||||||
make_table(&mut m, "foreach_peripheral", &peripherals_table);
|
make_table(&mut m, "foreach_peripheral", &peripherals_table);
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
|
|
||||||
#[cfg_attr(i2c_v1, path = "v1.rs")]
|
#[cfg_attr(i2c_v1, path = "v1.rs")]
|
||||||
#[cfg_attr(i2c_v2, path = "v2.rs")]
|
#[cfg_attr(i2c_v2, path = "v2.rs")]
|
||||||
mod _version;
|
mod _version;
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
use crate::peripherals;
|
use crate::peripherals;
|
||||||
|
|
||||||
@ -23,6 +26,20 @@ pub enum Error {
|
|||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
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 {
|
pub trait Instance: crate::rcc::RccPeripheral {
|
||||||
fn regs() -> crate::pac::i2c::I2c;
|
fn regs() -> crate::pac::i2c::I2c;
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
@ -30,7 +47,8 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance: sealed::Instance + 'static {
|
pub trait Instance: sealed::Instance + 'static {
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type EventInterrupt: interrupt::typelevel::Interrupt;
|
||||||
|
type ErrorInterrupt: interrupt::typelevel::Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_trait!(SclPin, Instance);
|
pin_trait!(SclPin, Instance);
|
||||||
@ -38,21 +56,148 @@ pin_trait!(SdaPin, Instance);
|
|||||||
dma_trait!(RxDma, Instance);
|
dma_trait!(RxDma, Instance);
|
||||||
dma_trait!(TxDma, Instance);
|
dma_trait!(TxDma, Instance);
|
||||||
|
|
||||||
foreach_interrupt!(
|
/// Interrupt handler.
|
||||||
($inst:ident, i2c, $block:ident, EV, $irq:ident) => {
|
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 {
|
impl sealed::Instance for peripherals::$inst {
|
||||||
fn regs() -> crate::pac::i2c::I2c {
|
fn regs() -> crate::pac::i2c::I2c {
|
||||||
crate::pac::$inst
|
crate::pac::$inst
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state() -> &'static State {
|
fn state() -> &'static sealed::State {
|
||||||
static STATE: State = State::new();
|
static STATE: sealed::State = sealed::State::new();
|
||||||
&STATE
|
&STATE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance for peripherals::$inst {
|
impl Instance for peripherals::$inst {
|
||||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
type EventInterrupt = crate::_generated::peripheral_interrupts::$inst::EV;
|
||||||
|
type ErrorInterrupt = crate::_generated::peripheral_interrupts::$inst::ER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mod eh02 {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable-traits")]
|
||||||
|
mod eh1 {
|
||||||
|
use super::*;
|
||||||
|
use crate::dma::NoDma;
|
||||||
|
|
||||||
|
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!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||||
|
mod eha {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,21 +3,17 @@ use core::marker::PhantomData;
|
|||||||
use embassy_embedded_hal::SetConfig;
|
use embassy_embedded_hal::SetConfig;
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::dma::NoDma;
|
use crate::dma::NoDma;
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Pull;
|
use crate::gpio::Pull;
|
||||||
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{interrupt, Peripheral};
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
/// Interrupt handler.
|
pub unsafe fn on_interrupt<T: Instance>() {
|
||||||
pub struct InterruptHandler<T: Instance> {
|
// todo
|
||||||
_phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
|
||||||
unsafe fn on_interrupt() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -27,14 +23,6 @@ pub struct Config {
|
|||||||
pub scl_pullup: bool,
|
pub scl_pullup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
pub(crate) const fn new() -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
|
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -48,7 +36,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
|
||||||
|
+ interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
|
||||||
|
+ 'd,
|
||||||
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
@ -98,6 +88,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
reg.set_pe(true);
|
reg.set_pe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
unsafe { T::EventInterrupt::enable() };
|
||||||
|
unsafe { T::ErrorInterrupt::enable() };
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
tx_dma,
|
tx_dma,
|
||||||
@ -336,6 +329,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
||||||
self.blocking_write_read_timeout(addr, write, read, || Ok(()))
|
self.blocking_write_read_timeout(addr, write, read, || Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Async
|
||||||
|
|
||||||
|
pub async fn write(&mut self, _address: u8, _write: &[u8]) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
TXDMA: crate::i2c::TxDma<T>,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read(&mut self, _address: u8, _buffer: &mut [u8]) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
RXDMA: crate::i2c::RxDma<T>,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
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>,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
||||||
@ -344,77 +361,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
|
||||||
self.blocking_read(addr, read)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
self.blocking_write(addr, write)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
|
||||||
self.blocking_write_read(addr, write, read)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "unstable-traits")]
|
|
||||||
mod eh1 {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
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> embedded_hal_1::i2c::ErrorType for I2c<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T> {
|
|
||||||
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!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Fast,
|
Fast,
|
||||||
Standard,
|
Standard,
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_embedded_hal::SetConfig;
|
use embassy_embedded_hal::SetConfig;
|
||||||
use embassy_hal_internal::drop::OnDrop;
|
use embassy_hal_internal::drop::OnDrop;
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
use embassy_time::{Duration, Instant};
|
use embassy_time::{Duration, Instant};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::dma::{NoDma, Transfer};
|
use crate::dma::{NoDma, Transfer};
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Pull;
|
use crate::gpio::Pull;
|
||||||
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
@ -36,25 +34,18 @@ pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
|
|||||||
move || Ok(())
|
move || Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interrupt handler.
|
pub unsafe fn on_interrupt<T: Instance>() {
|
||||||
pub struct InterruptHandler<T: Instance> {
|
let regs = T::regs();
|
||||||
_phantom: PhantomData<T>,
|
let isr = regs.isr().read();
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
if isr.tcr() || isr.tc() {
|
||||||
unsafe fn on_interrupt() {
|
T::state().waker.wake();
|
||||||
let regs = T::regs();
|
|
||||||
let isr = regs.isr().read();
|
|
||||||
|
|
||||||
if isr.tcr() || isr.tc() {
|
|
||||||
T::state().waker.wake();
|
|
||||||
}
|
|
||||||
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
|
||||||
// the interrupt
|
|
||||||
critical_section::with(|_| {
|
|
||||||
regs.cr1().modify(|w| w.set_tcie(false));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
|
||||||
|
// the interrupt
|
||||||
|
critical_section::with(|_| {
|
||||||
|
regs.cr1().modify(|w| w.set_tcie(false));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -77,18 +68,6 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
|
||||||
waker: AtomicWaker,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
pub(crate) const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
waker: AtomicWaker::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
|
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -104,7 +83,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
|
||||||
|
+ interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
|
||||||
|
+ 'd,
|
||||||
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
tx_dma: impl Peripheral<P = TXDMA> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
rx_dma: impl Peripheral<P = RXDMA> + 'd,
|
||||||
freq: Hertz,
|
freq: Hertz,
|
||||||
@ -150,8 +131,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
reg.set_pe(true);
|
reg.set_pe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
T::Interrupt::unpend();
|
unsafe { T::EventInterrupt::enable() };
|
||||||
unsafe { T::Interrupt::enable() };
|
unsafe { T::ErrorInterrupt::enable() };
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
_peri: peri,
|
_peri: peri,
|
||||||
@ -987,35 +968,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "time")]
|
|
||||||
mod eh02 {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// I2C Stop Configuration
|
/// I2C Stop Configuration
|
||||||
///
|
///
|
||||||
/// Peripheral options for generating the STOP condition
|
/// Peripheral options for generating the STOP condition
|
||||||
@ -1140,83 +1092,6 @@ impl Timings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-traits")]
|
|
||||||
mod eh1 {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
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!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
|
||||||
mod eha {
|
|
||||||
use super::super::{RxDma, TxDma};
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
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!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> SetConfig for I2c<'d, T> {
|
impl<'d, T: Instance> SetConfig for I2c<'d, T> {
|
||||||
type Config = Hertz;
|
type Config = Hertz;
|
||||||
type ConfigError = ();
|
type ConfigError = ();
|
||||||
|
@ -14,7 +14,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -19,7 +19,8 @@ const HEIGHT: usize = 100;
|
|||||||
static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2];
|
static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2];
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C1_EV => i2c::InterruptHandler<peripherals::I2C1>;
|
I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
|
||||||
|
I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
|
||||||
DCMI => dcmi::InterruptHandler<peripherals::DCMI>;
|
DCMI => dcmi::InterruptHandler<peripherals::DCMI>;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -14,7 +14,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -16,7 +16,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -13,7 +13,8 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
|
I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
|
||||||
|
I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
|
@ -40,7 +40,8 @@ use static_cell::make_static;
|
|||||||
use {embassy_stm32 as hal, panic_probe as _};
|
use {embassy_stm32 as hal, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
I2C3_EV => i2c::InterruptHandler<peripherals::I2C3>;
|
I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>;
|
||||||
|
I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>;
|
||||||
RNG => rng::InterruptHandler<peripherals::RNG>;
|
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user