mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
stm32/i2c: remove peripheral generic param.
This commit is contained in:
parent
6a508b3210
commit
45a12fd41f
@ -9,7 +9,7 @@ use core::future::Future;
|
||||
use core::iter;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
|
||||
use embassy_hal_internal::{into_ref, Peripheral};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
#[cfg(feature = "time")]
|
||||
use embassy_time::{Duration, Instant};
|
||||
@ -18,6 +18,7 @@ use crate::dma::ChannelAndRequest;
|
||||
use crate::gpio::{AFType, Pull};
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::mode::{Async, Blocking, Mode};
|
||||
use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
|
||||
use crate::time::Hertz;
|
||||
use crate::{interrupt, peripherals};
|
||||
|
||||
@ -72,8 +73,10 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
/// I2C driver.
|
||||
pub struct I2c<'d, T: Instance, M: Mode> {
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
pub struct I2c<'d, M: Mode> {
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
kernel_clock: Hertz,
|
||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
#[cfg(feature = "time")]
|
||||
@ -81,9 +84,9 @@ pub struct I2c<'d, T: Instance, M: Mode> {
|
||||
_phantom: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
impl<'d> I2c<'d, Async> {
|
||||
/// Create a new I2C driver.
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||
@ -99,9 +102,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> I2c<'d, T, Blocking> {
|
||||
impl<'d> I2c<'d, Blocking> {
|
||||
/// Create a new blocking I2C driver.
|
||||
pub fn new_blocking(
|
||||
pub fn new_blocking<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
|
||||
@ -112,10 +115,10 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> I2c<'d, M> {
|
||||
/// Create a new I2C driver.
|
||||
fn new_inner(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
fn new_inner<T: Instance>(
|
||||
_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>>,
|
||||
@ -123,7 +126,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
freq: Hertz,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(peri, scl, sda);
|
||||
into_ref!(scl, sda);
|
||||
|
||||
T::enable_and_reset();
|
||||
|
||||
@ -148,7 +151,9 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
unsafe { T::ErrorInterrupt::enable() };
|
||||
|
||||
let mut this = Self {
|
||||
_peri: peri,
|
||||
info: T::info(),
|
||||
state: T::state(),
|
||||
kernel_clock: T::frequency(),
|
||||
tx_dma,
|
||||
rx_dma,
|
||||
#[cfg(feature = "time")]
|
||||
@ -217,19 +222,14 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
trait SealedInstance: crate::rcc::RccPeripheral {
|
||||
fn regs() -> crate::pac::i2c::I2c;
|
||||
fn state() -> &'static State;
|
||||
struct Info {
|
||||
regs: crate::pac::i2c::I2c,
|
||||
pub(crate) enable_bit: ClockEnableBit,
|
||||
}
|
||||
|
||||
/// I2C peripheral instance
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + 'static {
|
||||
/// Event interrupt for this instance
|
||||
type EventInterrupt: interrupt::typelevel::Interrupt;
|
||||
/// Error interrupt for this instance
|
||||
type ErrorInterrupt: interrupt::typelevel::Interrupt;
|
||||
}
|
||||
peri_trait!(
|
||||
irqs: [EventInterrupt, ErrorInterrupt],
|
||||
);
|
||||
|
||||
pin_trait!(SclPin, Instance);
|
||||
pin_trait!(SdaPin, Instance);
|
||||
@ -260,11 +260,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte
|
||||
|
||||
foreach_peripheral!(
|
||||
(i2c, $inst:ident) => {
|
||||
#[allow(private_interfaces)]
|
||||
impl SealedInstance for peripherals::$inst {
|
||||
fn regs() -> crate::pac::i2c::I2c {
|
||||
crate::pac::$inst
|
||||
fn info() -> &'static Info {
|
||||
static INFO: Info = Info{
|
||||
regs: crate::pac::$inst,
|
||||
enable_bit: crate::peripherals::$inst::ENABLE_BIT,
|
||||
};
|
||||
&INFO
|
||||
}
|
||||
|
||||
fn state() -> &'static State {
|
||||
static STATE: State = State::new();
|
||||
&STATE
|
||||
@ -278,7 +282,7 @@ foreach_peripheral!(
|
||||
};
|
||||
);
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -286,7 +290,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -294,7 +298,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -318,11 +322,11 @@ impl embedded_hal_1::i2c::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> {
|
||||
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_read(address, read)
|
||||
}
|
||||
@ -344,7 +348,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for I2c<'d, T, Async> {
|
||||
impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> {
|
||||
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.read(address, read).await
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use crate::pac::i2c;
|
||||
// There's some more details there, and we might have a fix for you. But please let us know if you
|
||||
// hit a case like this!
|
||||
pub unsafe fn on_interrupt<T: Instance>() {
|
||||
let regs = T::regs();
|
||||
let regs = T::info().regs;
|
||||
// i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
|
||||
// other stuff, so we wake the task on every interrupt.
|
||||
T::state().waker.wake();
|
||||
@ -41,9 +41,9 @@ pub unsafe fn on_interrupt<T: Instance>() {
|
||||
});
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
impl<'d, M: PeriMode> I2c<'d, M> {
|
||||
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_pe(false);
|
||||
//reg.set_anfoff(false);
|
||||
});
|
||||
@ -67,39 +67,39 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
//
|
||||
// This presents as an ~infinite hang on read or write, as the START condition
|
||||
// is never generated, meaning the start event is never generated.
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_swrst(true);
|
||||
});
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_swrst(false);
|
||||
});
|
||||
|
||||
let timings = Timings::new(T::frequency(), freq);
|
||||
let timings = Timings::new(self.kernel_clock, freq);
|
||||
|
||||
T::regs().cr2().modify(|reg| {
|
||||
self.info.regs.cr2().modify(|reg| {
|
||||
reg.set_freq(timings.freq);
|
||||
});
|
||||
T::regs().ccr().modify(|reg| {
|
||||
self.info.regs.ccr().modify(|reg| {
|
||||
reg.set_f_s(timings.mode.f_s());
|
||||
reg.set_duty(timings.duty.duty());
|
||||
reg.set_ccr(timings.ccr);
|
||||
});
|
||||
T::regs().trise().modify(|reg| {
|
||||
self.info.regs.trise().modify(|reg| {
|
||||
reg.set_trise(timings.trise);
|
||||
});
|
||||
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_pe(true);
|
||||
});
|
||||
}
|
||||
|
||||
fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> {
|
||||
fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
|
||||
// Note that flags should only be cleared once they have been registered. If flags are
|
||||
// cleared otherwise, there may be an inherent race condition and flags may be missed.
|
||||
let sr1 = T::regs().sr1().read();
|
||||
let sr1 = info.regs.sr1().read();
|
||||
|
||||
if sr1.timeout() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_timeout(false);
|
||||
});
|
||||
@ -107,7 +107,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
if sr1.pecerr() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_pecerr(false);
|
||||
});
|
||||
@ -115,7 +115,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
if sr1.ovr() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_ovr(false);
|
||||
});
|
||||
@ -123,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
if sr1.af() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_af(false);
|
||||
});
|
||||
@ -131,7 +131,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
if sr1.arlo() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_arlo(false);
|
||||
});
|
||||
@ -141,7 +141,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
// The errata indicates that BERR may be incorrectly detected. It recommends ignoring and
|
||||
// clearing the BERR bit instead.
|
||||
if sr1.berr() {
|
||||
T::regs().sr1().write(|reg| {
|
||||
info.regs.sr1().write(|reg| {
|
||||
reg.0 = !0;
|
||||
reg.set_berr(false);
|
||||
});
|
||||
@ -154,32 +154,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
if frame.send_start() {
|
||||
// Send a START condition
|
||||
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_start(true);
|
||||
});
|
||||
|
||||
// Wait until START condition was generated
|
||||
while !Self::check_and_clear_error_flags()?.start() {
|
||||
while !Self::check_and_clear_error_flags(self.info)?.start() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
// Check if we were the ones to generate START
|
||||
if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
|
||||
if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
|
||||
return Err(Error::Arbitration);
|
||||
}
|
||||
|
||||
// Set up current address we're trying to talk to
|
||||
T::regs().dr().write(|reg| reg.set_dr(addr << 1));
|
||||
self.info.regs.dr().write(|reg| reg.set_dr(addr << 1));
|
||||
|
||||
// Wait until address was sent
|
||||
// Wait for the address to be acknowledged
|
||||
// Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
|
||||
while !Self::check_and_clear_error_flags()?.addr() {
|
||||
while !Self::check_and_clear_error_flags(self.info)?.addr() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
// Clear condition by reading SR2
|
||||
let _ = T::regs().sr2().read();
|
||||
let _ = self.info.regs.sr2().read();
|
||||
}
|
||||
|
||||
// Send bytes
|
||||
@ -189,7 +189,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
|
||||
if frame.send_stop() {
|
||||
// Send a STOP condition
|
||||
T::regs().cr1().modify(|reg| reg.set_stop(true));
|
||||
self.info.regs.cr1().modify(|reg| reg.set_stop(true));
|
||||
}
|
||||
|
||||
// Fallthrough is success
|
||||
@ -200,18 +200,18 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
// Wait until we're ready for sending
|
||||
while {
|
||||
// Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
|
||||
!Self::check_and_clear_error_flags()?.txe()
|
||||
!Self::check_and_clear_error_flags(self.info)?.txe()
|
||||
} {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
// Push out a byte of data
|
||||
T::regs().dr().write(|reg| reg.set_dr(byte));
|
||||
self.info.regs.dr().write(|reg| reg.set_dr(byte));
|
||||
|
||||
// Wait until byte is transferred
|
||||
while {
|
||||
// Check for any potential error conditions.
|
||||
!Self::check_and_clear_error_flags()?.btf()
|
||||
!Self::check_and_clear_error_flags(self.info)?.btf()
|
||||
} {
|
||||
timeout.check()?;
|
||||
}
|
||||
@ -222,14 +222,14 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
fn recv_byte(&self, timeout: Timeout) -> Result<u8, Error> {
|
||||
while {
|
||||
// Check for any potential error conditions.
|
||||
Self::check_and_clear_error_flags()?;
|
||||
Self::check_and_clear_error_flags(self.info)?;
|
||||
|
||||
!T::regs().sr1().read().rxne()
|
||||
!self.info.regs.sr1().read().rxne()
|
||||
} {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
let value = T::regs().dr().read().dr();
|
||||
let value = self.info.regs.dr().read().dr();
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -246,32 +246,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
|
||||
if frame.send_start() {
|
||||
// Send a START condition and set ACK bit
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_start(true);
|
||||
reg.set_ack(true);
|
||||
});
|
||||
|
||||
// Wait until START condition was generated
|
||||
while !Self::check_and_clear_error_flags()?.start() {
|
||||
while !Self::check_and_clear_error_flags(self.info)?.start() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
// Check if we were the ones to generate START
|
||||
if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
|
||||
if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
|
||||
return Err(Error::Arbitration);
|
||||
}
|
||||
|
||||
// Set up current address we're trying to talk to
|
||||
T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1));
|
||||
self.info.regs.dr().write(|reg| reg.set_dr((addr << 1) + 1));
|
||||
|
||||
// Wait until address was sent
|
||||
// Wait for the address to be acknowledged
|
||||
while !Self::check_and_clear_error_flags()?.addr() {
|
||||
while !Self::check_and_clear_error_flags(self.info)?.addr() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
// Clear condition by reading SR2
|
||||
let _ = T::regs().sr2().read();
|
||||
let _ = self.info.regs.sr2().read();
|
||||
}
|
||||
|
||||
// Receive bytes into buffer
|
||||
@ -280,7 +280,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
// Prepare to send NACK then STOP after next byte
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
if frame.send_nack() {
|
||||
reg.set_ack(false);
|
||||
}
|
||||
@ -346,17 +346,17 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
|
||||
// Async
|
||||
|
||||
#[inline] // pretty sure this should always be inlined
|
||||
fn enable_interrupts() -> () {
|
||||
T::regs().cr2().modify(|w| {
|
||||
fn enable_interrupts(info: &'static Info) -> () {
|
||||
info.regs.cr2().modify(|w| {
|
||||
w.set_iterren(true);
|
||||
w.set_itevten(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
impl<'d> I2c<'d, Async> {
|
||||
async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
// Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
|
||||
// reception.
|
||||
w.set_itbufen(false);
|
||||
@ -370,33 +370,31 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// Sentinel to disable transfer when an error occurs or future is canceled.
|
||||
// TODO: Generate STOP condition on cancel?
|
||||
let on_drop = OnDrop::new(|| {
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_dmaen(false);
|
||||
w.set_iterren(false);
|
||||
w.set_itevten(false);
|
||||
})
|
||||
});
|
||||
|
||||
let state = T::state();
|
||||
|
||||
if frame.send_start() {
|
||||
// Send a START condition
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_start(true);
|
||||
});
|
||||
|
||||
// Wait until START condition was generated
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err(e)),
|
||||
Ok(sr1) => {
|
||||
if sr1.start() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -405,25 +403,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
.await?;
|
||||
|
||||
// Check if we were the ones to generate START
|
||||
if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
|
||||
if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
|
||||
return Err(Error::Arbitration);
|
||||
}
|
||||
|
||||
// Set up current address we're trying to talk to
|
||||
T::regs().dr().write(|reg| reg.set_dr(address << 1));
|
||||
self.info.regs.dr().write(|reg| reg.set_dr(address << 1));
|
||||
|
||||
// Wait for the address to be acknowledged
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err(e)),
|
||||
Ok(sr1) => {
|
||||
if sr1.addr() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -432,26 +430,26 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
.await?;
|
||||
|
||||
// Clear condition by reading SR2
|
||||
T::regs().sr2().read();
|
||||
self.info.regs.sr2().read();
|
||||
}
|
||||
|
||||
let dma_transfer = unsafe {
|
||||
// Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to
|
||||
// this address from the memory after each TxE event.
|
||||
let dst = T::regs().dr().as_ptr() as *mut u8;
|
||||
let dst = self.info.regs.dr().as_ptr() as *mut u8;
|
||||
|
||||
self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
|
||||
};
|
||||
|
||||
// Wait for bytes to be sent, or an error to occur.
|
||||
let poll_error = poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err::<(), Error>(e)),
|
||||
Ok(_) => {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -463,7 +461,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_dmaen(false);
|
||||
});
|
||||
|
||||
@ -473,16 +471,16 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA
|
||||
// requests then wait for a BTF event before programming the Stop condition.”
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err(e)),
|
||||
Ok(sr1) => {
|
||||
if sr1.btf() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -490,7 +488,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
})
|
||||
.await?;
|
||||
|
||||
T::regs().cr1().modify(|w| {
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_stop(true);
|
||||
});
|
||||
}
|
||||
@ -525,7 +523,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// Some branches below depend on whether the buffer contains only a single byte.
|
||||
let single_byte = buffer.len() == 1;
|
||||
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
// Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
|
||||
// reception.
|
||||
w.set_itbufen(false);
|
||||
@ -541,34 +539,32 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// Sentinel to disable transfer when an error occurs or future is canceled.
|
||||
// TODO: Generate STOP condition on cancel?
|
||||
let on_drop = OnDrop::new(|| {
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_dmaen(false);
|
||||
w.set_iterren(false);
|
||||
w.set_itevten(false);
|
||||
})
|
||||
});
|
||||
|
||||
let state = T::state();
|
||||
|
||||
if frame.send_start() {
|
||||
// Send a START condition and set ACK bit
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_start(true);
|
||||
reg.set_ack(true);
|
||||
});
|
||||
|
||||
// Wait until START condition was generated
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err(e)),
|
||||
Ok(sr1) => {
|
||||
if sr1.start() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -577,25 +573,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
.await?;
|
||||
|
||||
// Check if we were the ones to generate START
|
||||
if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
|
||||
if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
|
||||
return Err(Error::Arbitration);
|
||||
}
|
||||
|
||||
// Set up current address we're trying to talk to
|
||||
T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
|
||||
self.info.regs.dr().write(|reg| reg.set_dr((address << 1) + 1));
|
||||
|
||||
// Wait for the address to be acknowledged
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err(e)),
|
||||
Ok(sr1) => {
|
||||
if sr1.addr() {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -606,18 +602,18 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
|
||||
// event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
|
||||
if frame.send_nack() && single_byte {
|
||||
T::regs().cr1().modify(|w| {
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_ack(false);
|
||||
});
|
||||
}
|
||||
|
||||
// Clear condition by reading SR2
|
||||
T::regs().sr2().read();
|
||||
self.info.regs.sr2().read();
|
||||
} else {
|
||||
// Before starting reception of single byte (but without START condition, i.e. in case
|
||||
// of continued frame), program NACK to emit at end of this byte.
|
||||
if frame.send_nack() && single_byte {
|
||||
T::regs().cr1().modify(|w| {
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_ack(false);
|
||||
});
|
||||
}
|
||||
@ -627,7 +623,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
// condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
|
||||
// routine.
|
||||
if frame.send_stop() && single_byte {
|
||||
T::regs().cr1().modify(|w| {
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_stop(true);
|
||||
});
|
||||
}
|
||||
@ -635,20 +631,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
let dma_transfer = unsafe {
|
||||
// Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved
|
||||
// from this address from the memory after each RxE event.
|
||||
let src = T::regs().dr().as_ptr() as *mut u8;
|
||||
let src = self.info.regs.dr().as_ptr() as *mut u8;
|
||||
|
||||
self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
|
||||
};
|
||||
|
||||
// Wait for bytes to be received, or an error to occur.
|
||||
let poll_error = poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
match Self::check_and_clear_error_flags() {
|
||||
match Self::check_and_clear_error_flags(self.info) {
|
||||
Err(e) => Poll::Ready(Err::<(), Error>(e)),
|
||||
_ => {
|
||||
// When pending, (re-)enable interrupts to wake us up.
|
||||
Self::enable_interrupts();
|
||||
Self::enable_interrupts(self.info);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
@ -659,12 +655,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
|
||||
T::regs().cr2().modify(|w| {
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_dmaen(false);
|
||||
});
|
||||
|
||||
if frame.send_stop() && !single_byte {
|
||||
T::regs().cr1().modify(|w| {
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_stop(true);
|
||||
});
|
||||
}
|
||||
@ -704,9 +700,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> Drop for I2c<'d, T, M> {
|
||||
impl<'d, M: PeriMode> Drop for I2c<'d, M> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
self.info.enable_bit.disable()
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,20 +806,20 @@ impl Timings {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> SetConfig for I2c<'d, T, M> {
|
||||
impl<'d, M: PeriMode> SetConfig for I2c<'d, M> {
|
||||
type Config = Hertz;
|
||||
type ConfigError = ();
|
||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||
let timings = Timings::new(T::frequency(), *config);
|
||||
T::regs().cr2().modify(|reg| {
|
||||
let timings = Timings::new(self.kernel_clock, *config);
|
||||
self.info.regs.cr2().modify(|reg| {
|
||||
reg.set_freq(timings.freq);
|
||||
});
|
||||
T::regs().ccr().modify(|reg| {
|
||||
self.info.regs.ccr().modify(|reg| {
|
||||
reg.set_f_s(timings.mode.f_s());
|
||||
reg.set_duty(timings.duty.duty());
|
||||
reg.set_ccr(timings.ccr);
|
||||
});
|
||||
T::regs().trise().modify(|reg| {
|
||||
self.info.regs.trise().modify(|reg| {
|
||||
reg.set_trise(timings.trise);
|
||||
});
|
||||
|
||||
|
@ -10,7 +10,7 @@ use super::*;
|
||||
use crate::pac::i2c;
|
||||
|
||||
pub(crate) unsafe fn on_interrupt<T: Instance>() {
|
||||
let regs = T::regs();
|
||||
let regs = T::info().regs;
|
||||
let isr = regs.isr().read();
|
||||
|
||||
if isr.tcr() || isr.tc() {
|
||||
@ -23,16 +23,16 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
|
||||
});
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> I2c<'d, M> {
|
||||
pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_pe(false);
|
||||
reg.set_anfoff(false);
|
||||
});
|
||||
|
||||
let timings = Timings::new(T::frequency(), freq.into());
|
||||
let timings = Timings::new(self.kernel_clock, freq.into());
|
||||
|
||||
T::regs().timingr().write(|reg| {
|
||||
self.info.regs.timingr().write(|reg| {
|
||||
reg.set_presc(timings.prescale);
|
||||
reg.set_scll(timings.scll);
|
||||
reg.set_sclh(timings.sclh);
|
||||
@ -40,16 +40,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
reg.set_scldel(timings.scldel);
|
||||
});
|
||||
|
||||
T::regs().cr1().modify(|reg| {
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_pe(true);
|
||||
});
|
||||
}
|
||||
|
||||
fn master_stop(&mut self) {
|
||||
T::regs().cr2().write(|w| w.set_stop(true));
|
||||
self.info.regs.cr2().write(|w| w.set_stop(true));
|
||||
}
|
||||
|
||||
fn master_read(
|
||||
info: &'static Info,
|
||||
address: u8,
|
||||
length: usize,
|
||||
stop: Stop,
|
||||
@ -63,7 +64,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
// Wait for any previous address sequence to end
|
||||
// automatically. This could be up to 50% of a bus
|
||||
// cycle (ie. up to 0.5/freq)
|
||||
while T::regs().cr2().read().start() {
|
||||
while info.regs.cr2().read().start() {
|
||||
timeout.check()?;
|
||||
}
|
||||
}
|
||||
@ -78,7 +79,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
i2c::vals::Reload::COMPLETED
|
||||
};
|
||||
|
||||
T::regs().cr2().modify(|w| {
|
||||
info.regs.cr2().modify(|w| {
|
||||
w.set_sadd((address << 1 | 0) as u16);
|
||||
w.set_add10(i2c::vals::Addmode::BIT7);
|
||||
w.set_dir(i2c::vals::Dir::READ);
|
||||
@ -91,13 +92,20 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn master_write(address: u8, length: usize, stop: Stop, reload: bool, timeout: Timeout) -> Result<(), Error> {
|
||||
fn master_write(
|
||||
info: &'static Info,
|
||||
address: u8,
|
||||
length: usize,
|
||||
stop: Stop,
|
||||
reload: bool,
|
||||
timeout: Timeout,
|
||||
) -> Result<(), Error> {
|
||||
assert!(length < 256);
|
||||
|
||||
// Wait for any previous address sequence to end
|
||||
// automatically. This could be up to 50% of a bus
|
||||
// cycle (ie. up to 0.5/freq)
|
||||
while T::regs().cr2().read().start() {
|
||||
while info.regs.cr2().read().start() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
@ -110,7 +118,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
// Set START and prepare to send `bytes`. The
|
||||
// START bit can be set even if the bus is BUSY or
|
||||
// I2C is in slave mode.
|
||||
T::regs().cr2().modify(|w| {
|
||||
info.regs.cr2().modify(|w| {
|
||||
w.set_sadd((address << 1 | 0) as u16);
|
||||
w.set_add10(i2c::vals::Addmode::BIT7);
|
||||
w.set_dir(i2c::vals::Dir::WRITE);
|
||||
@ -123,10 +131,10 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn master_continue(length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
|
||||
fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
|
||||
assert!(length < 256 && length > 0);
|
||||
|
||||
while !T::regs().isr().read().tcr() {
|
||||
while !info.regs.isr().read().tcr() {
|
||||
timeout.check()?;
|
||||
}
|
||||
|
||||
@ -136,7 +144,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
i2c::vals::Reload::COMPLETED
|
||||
};
|
||||
|
||||
T::regs().cr2().modify(|w| {
|
||||
info.regs.cr2().modify(|w| {
|
||||
w.set_nbytes(length as u8);
|
||||
w.set_reload(reload);
|
||||
});
|
||||
@ -145,27 +153,27 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
}
|
||||
|
||||
fn flush_txdr(&self) {
|
||||
if T::regs().isr().read().txis() {
|
||||
T::regs().txdr().write(|w| w.set_txdata(0));
|
||||
if self.info.regs.isr().read().txis() {
|
||||
self.info.regs.txdr().write(|w| w.set_txdata(0));
|
||||
}
|
||||
if !T::regs().isr().read().txe() {
|
||||
T::regs().isr().modify(|w| w.set_txe(true))
|
||||
if !self.info.regs.isr().read().txe() {
|
||||
self.info.regs.isr().modify(|w| w.set_txe(true))
|
||||
}
|
||||
}
|
||||
|
||||
fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
|
||||
loop {
|
||||
let isr = T::regs().isr().read();
|
||||
let isr = self.info.regs.isr().read();
|
||||
if isr.txe() {
|
||||
return Ok(());
|
||||
} else if isr.berr() {
|
||||
T::regs().icr().write(|reg| reg.set_berrcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_berrcf(true));
|
||||
return Err(Error::Bus);
|
||||
} else if isr.arlo() {
|
||||
T::regs().icr().write(|reg| reg.set_arlocf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_arlocf(true));
|
||||
return Err(Error::Arbitration);
|
||||
} else if isr.nackf() {
|
||||
T::regs().icr().write(|reg| reg.set_nackcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_nackcf(true));
|
||||
self.flush_txdr();
|
||||
return Err(Error::Nack);
|
||||
}
|
||||
@ -176,17 +184,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
|
||||
loop {
|
||||
let isr = T::regs().isr().read();
|
||||
let isr = self.info.regs.isr().read();
|
||||
if isr.rxne() {
|
||||
return Ok(());
|
||||
} else if isr.berr() {
|
||||
T::regs().icr().write(|reg| reg.set_berrcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_berrcf(true));
|
||||
return Err(Error::Bus);
|
||||
} else if isr.arlo() {
|
||||
T::regs().icr().write(|reg| reg.set_arlocf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_arlocf(true));
|
||||
return Err(Error::Arbitration);
|
||||
} else if isr.nackf() {
|
||||
T::regs().icr().write(|reg| reg.set_nackcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_nackcf(true));
|
||||
self.flush_txdr();
|
||||
return Err(Error::Nack);
|
||||
}
|
||||
@ -197,17 +205,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
|
||||
loop {
|
||||
let isr = T::regs().isr().read();
|
||||
let isr = self.info.regs.isr().read();
|
||||
if isr.tc() {
|
||||
return Ok(());
|
||||
} else if isr.berr() {
|
||||
T::regs().icr().write(|reg| reg.set_berrcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_berrcf(true));
|
||||
return Err(Error::Bus);
|
||||
} else if isr.arlo() {
|
||||
T::regs().icr().write(|reg| reg.set_arlocf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_arlocf(true));
|
||||
return Err(Error::Arbitration);
|
||||
} else if isr.nackf() {
|
||||
T::regs().icr().write(|reg| reg.set_nackcf(true));
|
||||
self.info.regs.icr().write(|reg| reg.set_nackcf(true));
|
||||
self.flush_txdr();
|
||||
return Err(Error::Nack);
|
||||
}
|
||||
@ -226,6 +234,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
let last_chunk_idx = total_chunks.saturating_sub(1);
|
||||
|
||||
Self::master_read(
|
||||
self.info,
|
||||
address,
|
||||
read.len().min(255),
|
||||
Stop::Automatic,
|
||||
@ -236,14 +245,14 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
for (number, chunk) in read.chunks_mut(255).enumerate() {
|
||||
if number != 0 {
|
||||
Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
|
||||
Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
|
||||
}
|
||||
|
||||
for byte in chunk {
|
||||
// Wait until we have received something
|
||||
self.wait_rxne(timeout)?;
|
||||
|
||||
*byte = T::regs().rxdr().read().rxdata();
|
||||
*byte = self.info.regs.rxdr().read().rxdata();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -262,6 +271,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
//
|
||||
// ST SAD+W
|
||||
if let Err(err) = Self::master_write(
|
||||
self.info,
|
||||
address,
|
||||
write.len().min(255),
|
||||
Stop::Software,
|
||||
@ -276,7 +286,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
for (number, chunk) in write.chunks(255).enumerate() {
|
||||
if number != 0 {
|
||||
Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
|
||||
Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
|
||||
}
|
||||
|
||||
for byte in chunk {
|
||||
@ -290,7 +300,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
T::regs().txdr().write(|w| w.set_txdata(*byte));
|
||||
self.info.regs.txdr().write(|w| w.set_txdata(*byte));
|
||||
}
|
||||
}
|
||||
// Wait until the write finishes
|
||||
@ -348,6 +358,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
let last_slice_index = write.len() - 1;
|
||||
|
||||
if let Err(err) = Self::master_write(
|
||||
self.info,
|
||||
address,
|
||||
first_length.min(255),
|
||||
Stop::Software,
|
||||
@ -370,6 +381,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
if idx != 0 {
|
||||
if let Err(err) = Self::master_continue(
|
||||
self.info,
|
||||
slice_len.min(255),
|
||||
(idx != last_slice_index) || (slice_len > 255),
|
||||
timeout,
|
||||
@ -382,6 +394,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
for (number, chunk) in slice.chunks(255).enumerate() {
|
||||
if number != 0 {
|
||||
if let Err(err) = Self::master_continue(
|
||||
self.info,
|
||||
chunk.len(),
|
||||
(number != last_chunk_idx) || (idx != last_slice_index),
|
||||
timeout,
|
||||
@ -402,7 +415,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
|
||||
// Put byte on the wire
|
||||
//self.i2c.txdr.write(|w| w.txdata().bits(*byte));
|
||||
T::regs().txdr().write(|w| w.set_txdata(*byte));
|
||||
self.info.regs.txdr().write(|w| w.set_txdata(*byte));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,7 +426,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
impl<'d> I2c<'d, Async> {
|
||||
async fn write_dma_internal(
|
||||
&mut self,
|
||||
address: u8,
|
||||
@ -425,7 +438,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
let total_len = write.len();
|
||||
|
||||
let dma_transfer = unsafe {
|
||||
let regs = T::regs();
|
||||
let regs = self.info.regs;
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_txdmaen(true);
|
||||
if first_slice {
|
||||
@ -437,11 +450,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
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();
|
||||
let regs = self.info.regs;
|
||||
regs.cr1().modify(|w| {
|
||||
if last_slice {
|
||||
w.set_txdmaen(false);
|
||||
@ -451,12 +463,13 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
});
|
||||
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
let isr = T::regs().isr().read();
|
||||
let isr = self.info.regs.isr().read();
|
||||
if remaining_len == total_len {
|
||||
if first_slice {
|
||||
Self::master_write(
|
||||
self.info,
|
||||
address,
|
||||
total_len.min(255),
|
||||
Stop::Software,
|
||||
@ -464,8 +477,8 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
timeout,
|
||||
)?;
|
||||
} else {
|
||||
Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
|
||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||
Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
|
||||
self.info.regs.cr1().modify(|w| w.set_tcie(true));
|
||||
}
|
||||
} else if !(isr.tcr() || isr.tc()) {
|
||||
// poll_fn was woken without an interrupt present
|
||||
@ -475,10 +488,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
} else {
|
||||
let last_piece = (remaining_len <= 255) && last_slice;
|
||||
|
||||
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
|
||||
if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) {
|
||||
return Poll::Ready(Err(e));
|
||||
}
|
||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||
self.info.regs.cr1().modify(|w| w.set_tcie(true));
|
||||
}
|
||||
|
||||
remaining_len = remaining_len.saturating_sub(255);
|
||||
@ -509,7 +522,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
let total_len = buffer.len();
|
||||
|
||||
let dma_transfer = unsafe {
|
||||
let regs = T::regs();
|
||||
let regs = self.info.regs;
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_rxdmaen(true);
|
||||
w.set_tcie(true);
|
||||
@ -519,11 +532,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
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();
|
||||
let regs = self.info.regs;
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_rxdmaen(false);
|
||||
w.set_tcie(false);
|
||||
@ -531,11 +543,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
});
|
||||
|
||||
poll_fn(|cx| {
|
||||
state.waker.register(cx.waker());
|
||||
self.state.waker.register(cx.waker());
|
||||
|
||||
let isr = T::regs().isr().read();
|
||||
let isr = self.info.regs.isr().read();
|
||||
if remaining_len == total_len {
|
||||
Self::master_read(
|
||||
self.info,
|
||||
address,
|
||||
total_len.min(255),
|
||||
Stop::Software,
|
||||
@ -551,10 +564,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
} else {
|
||||
let last_piece = remaining_len <= 255;
|
||||
|
||||
if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
|
||||
if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) {
|
||||
return Poll::Ready(Err(e));
|
||||
}
|
||||
T::regs().cr1().modify(|w| w.set_tcie(true));
|
||||
self.info.regs.cr1().modify(|w| w.set_tcie(true));
|
||||
}
|
||||
|
||||
remaining_len = remaining_len.saturating_sub(255);
|
||||
@ -658,9 +671,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> Drop for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> Drop for I2c<'d, M> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
self.info.enable_bit.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,12 +801,12 @@ impl Timings {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> SetConfig for I2c<'d, T, M> {
|
||||
impl<'d, M: Mode> SetConfig for I2c<'d, M> {
|
||||
type Config = Hertz;
|
||||
type ConfigError = ();
|
||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||
let timings = Timings::new(T::frequency(), *config);
|
||||
T::regs().timingr().write(|reg| {
|
||||
let timings = Timings::new(self.kernel_clock, *config);
|
||||
self.info.regs.timingr().write(|reg| {
|
||||
reg.set_presc(timings.prescale);
|
||||
reg.set_scll(timings.scll);
|
||||
reg.set_sclh(timings.sclh);
|
||||
|
@ -1,7 +1,9 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! peri_trait {
|
||||
() => {
|
||||
(
|
||||
$(irqs: [$($irq:ident),*],)?
|
||||
) => {
|
||||
#[allow(private_interfaces)]
|
||||
pub(crate) trait SealedInstance {
|
||||
#[allow(unused)]
|
||||
@ -10,9 +12,14 @@ macro_rules! peri_trait {
|
||||
fn state() -> &'static State;
|
||||
}
|
||||
|
||||
/// SPI instance trait.
|
||||
/// Peripheral instance trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
|
||||
pub trait Instance: crate::Peripheral<P = Self> + SealedInstance + crate::rcc::RccPeripheral {
|
||||
$($(
|
||||
/// Interrupt for this peripheral.
|
||||
type $irq: crate::interrupt::typelevel::Interrupt;
|
||||
)*)?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,10 @@ use core::cell::RefCell;
|
||||
use defmt::*;
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::bind_interrupts;
|
||||
use embassy_stm32::i2c::{self, I2c};
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::peripherals::{self, I2C1};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::{bind_interrupts, peripherals};
|
||||
use embassy_sync::blocking_mutex::NoopMutex;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use static_cell::StaticCell;
|
||||
@ -24,7 +23,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17];
|
||||
const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
|
||||
const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
|
||||
|
||||
static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, I2C1, Async>>>> = StaticCell::new();
|
||||
static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new();
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
|
||||
|
@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
|
||||
pub type SpeInt = exti::ExtiInput<'static>;
|
||||
pub type SpeRst = Output<'static>;
|
||||
pub type Adin1110T = ADIN1110<SpeSpiCs>;
|
||||
pub type TempSensI2c = I2c<'static, peripherals::I2C3, Async>;
|
||||
pub type TempSensI2c = I2c<'static, Async>;
|
||||
|
||||
static TEMP: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user