Merge pull request from embassy-rs/spi-nogenerics

stm32/i2c: remove peripheral generic param.
This commit is contained in:
Dario Nieuwenhuis
2024-05-21 20:46:03 +00:00
committed by GitHub
10 changed files with 291 additions and 263 deletions

@ -653,9 +653,9 @@ fn main() {
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
#decr_stop_refcount #decr_stop_refcount
} }
fn enable_bit() -> crate::rcc::ClockEnableBit {
unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) } const ENABLE_BIT: crate::rcc::ClockEnableBit =
} unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) };
} }
impl crate::rcc::RccPeripheral for peripherals::#pname {} impl crate::rcc::RccPeripheral for peripherals::#pname {}

@ -9,7 +9,7 @@ use core::future::Future;
use core::iter; use core::iter;
use core::marker::PhantomData; use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_hal_internal::{into_ref, Peripheral};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")] #[cfg(feature = "time")]
use embassy_time::{Duration, Instant}; use embassy_time::{Duration, Instant};
@ -18,6 +18,7 @@ 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::mode::{Async, Blocking, Mode};
use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
use crate::time::Hertz; use crate::time::Hertz;
use crate::{interrupt, peripherals}; use crate::{interrupt, peripherals};
@ -72,8 +73,10 @@ impl Default for Config {
} }
/// I2C driver. /// I2C driver.
pub struct I2c<'d, T: Instance, M: Mode> { pub struct I2c<'d, M: Mode> {
_peri: PeripheralRef<'d, T>, info: &'static Info,
state: &'static State,
kernel_clock: Hertz,
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
#[cfg(feature = "time")] #[cfg(feature = "time")]
@ -81,9 +84,9 @@ pub struct I2c<'d, T: Instance, M: Mode> {
_phantom: PhantomData<M>, _phantom: PhantomData<M>,
} }
impl<'d, T: Instance> I2c<'d, T, Async> { impl<'d> I2c<'d, Async> {
/// Create a new I2C driver. /// Create a new I2C driver.
pub fn new( pub fn new<T: Instance>(
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,
@ -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. /// Create a new blocking I2C driver.
pub fn new_blocking( pub fn new_blocking<T: Instance>(
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,
@ -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. /// Create a new I2C driver.
fn new_inner( fn new_inner<T: Instance>(
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,
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
@ -123,7 +126,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
freq: Hertz, freq: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(peri, scl, sda); into_ref!(scl, sda);
T::enable_and_reset(); T::enable_and_reset();
@ -148,7 +151,9 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
unsafe { T::ErrorInterrupt::enable() }; unsafe { T::ErrorInterrupt::enable() };
let mut this = Self { let mut this = Self {
_peri: peri, info: T::info(),
state: T::state(),
kernel_clock: T::frequency(),
tx_dma, tx_dma,
rx_dma, rx_dma,
#[cfg(feature = "time")] #[cfg(feature = "time")]
@ -217,19 +222,14 @@ impl State {
} }
} }
trait SealedInstance: crate::rcc::RccPeripheral { struct Info {
fn regs() -> crate::pac::i2c::I2c; regs: crate::pac::i2c::I2c,
fn state() -> &'static State; pub(crate) enable_bit: ClockEnableBit,
} }
/// I2C peripheral instance peri_trait!(
#[allow(private_bounds)] irqs: [EventInterrupt, ErrorInterrupt],
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;
}
pin_trait!(SclPin, Instance); pin_trait!(SclPin, Instance);
pin_trait!(SdaPin, Instance); pin_trait!(SdaPin, Instance);
@ -260,11 +260,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte
foreach_peripheral!( foreach_peripheral!(
(i2c, $inst:ident) => { (i2c, $inst:ident) => {
#[allow(private_interfaces)]
impl SealedInstance for peripherals::$inst { impl SealedInstance for peripherals::$inst {
fn regs() -> crate::pac::i2c::I2c { fn info() -> &'static Info {
crate::pac::$inst static INFO: Info = Info{
regs: crate::pac::$inst,
enable_bit: crate::peripherals::$inst::ENABLE_BIT,
};
&INFO
} }
fn state() -> &'static State { fn state() -> &'static State {
static STATE: State = State::new(); static STATE: State = State::new();
&STATE &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; 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> {
@ -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; 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> {
@ -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; 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> {
@ -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; 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> { fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(address, read) 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> { async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.read(address, read).await 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 // 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! // hit a case like this!
pub unsafe fn on_interrupt<T: Instance>() { 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 // 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. // other stuff, so we wake the task on every interrupt.
T::state().waker.wake(); 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) { 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_pe(false);
//reg.set_anfoff(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 // This presents as an ~infinite hang on read or write, as the START condition
// is never generated, meaning the start event is never generated. // 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); reg.set_swrst(true);
}); });
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_swrst(false); 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); 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_f_s(timings.mode.f_s());
reg.set_duty(timings.duty.duty()); reg.set_duty(timings.duty.duty());
reg.set_ccr(timings.ccr); reg.set_ccr(timings.ccr);
}); });
T::regs().trise().modify(|reg| { self.info.regs.trise().modify(|reg| {
reg.set_trise(timings.trise); reg.set_trise(timings.trise);
}); });
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_pe(true); 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 // 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. // 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() { if sr1.timeout() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_timeout(false); reg.set_timeout(false);
}); });
@ -107,7 +107,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
} }
if sr1.pecerr() { if sr1.pecerr() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_pecerr(false); reg.set_pecerr(false);
}); });
@ -115,7 +115,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
} }
if sr1.ovr() { if sr1.ovr() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_ovr(false); reg.set_ovr(false);
}); });
@ -123,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
} }
if sr1.af() { if sr1.af() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_af(false); reg.set_af(false);
}); });
@ -131,7 +131,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
} }
if sr1.arlo() { if sr1.arlo() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_arlo(false); 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 // The errata indicates that BERR may be incorrectly detected. It recommends ignoring and
// clearing the BERR bit instead. // clearing the BERR bit instead.
if sr1.berr() { if sr1.berr() {
T::regs().sr1().write(|reg| { info.regs.sr1().write(|reg| {
reg.0 = !0; reg.0 = !0;
reg.set_berr(false); reg.set_berr(false);
}); });
@ -154,32 +154,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
if frame.send_start() { if frame.send_start() {
// Send a START condition // Send a START condition
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_start(true); reg.set_start(true);
}); });
// Wait until START condition was generated // 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()?; timeout.check()?;
} }
// Check if we were the ones to generate START // 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); return Err(Error::Arbitration);
} }
// Set up current address we're trying to talk to // 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 until address was sent
// Wait for the address to be acknowledged // Wait for the address to be acknowledged
// Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. // 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()?; timeout.check()?;
} }
// Clear condition by reading SR2 // Clear condition by reading SR2
let _ = T::regs().sr2().read(); let _ = self.info.regs.sr2().read();
} }
// Send bytes // Send bytes
@ -189,7 +189,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
if frame.send_stop() { if frame.send_stop() {
// Send a STOP condition // 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 // Fallthrough is success
@ -200,18 +200,18 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
// Wait until we're ready for sending // Wait until we're ready for sending
while { while {
// Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. // 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()?; timeout.check()?;
} }
// Push out a byte of data // 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 // Wait until byte is transferred
while { while {
// Check for any potential error conditions. // Check for any potential error conditions.
!Self::check_and_clear_error_flags()?.btf() !Self::check_and_clear_error_flags(self.info)?.btf()
} { } {
timeout.check()?; 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> { fn recv_byte(&self, timeout: Timeout) -> Result<u8, Error> {
while { while {
// Check for any potential error conditions. // 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()?; timeout.check()?;
} }
let value = T::regs().dr().read().dr(); let value = self.info.regs.dr().read().dr();
Ok(value) Ok(value)
} }
@ -246,32 +246,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
if frame.send_start() { if frame.send_start() {
// Send a START condition and set ACK bit // 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_start(true);
reg.set_ack(true); reg.set_ack(true);
}); });
// Wait until START condition was generated // 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()?; timeout.check()?;
} }
// Check if we were the ones to generate START // 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); return Err(Error::Arbitration);
} }
// Set up current address we're trying to talk to // 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 until address was sent
// Wait for the address to be acknowledged // 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()?; timeout.check()?;
} }
// Clear condition by reading SR2 // Clear condition by reading SR2
let _ = T::regs().sr2().read(); let _ = self.info.regs.sr2().read();
} }
// Receive bytes into buffer // 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 // Prepare to send NACK then STOP after next byte
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
if frame.send_nack() { if frame.send_nack() {
reg.set_ack(false); reg.set_ack(false);
} }
@ -346,17 +346,17 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
// Async // Async
#[inline] // pretty sure this should always be inlined #[inline] // pretty sure this should always be inlined
fn enable_interrupts() -> () { fn enable_interrupts(info: &'static Info) -> () {
T::regs().cr2().modify(|w| { info.regs.cr2().modify(|w| {
w.set_iterren(true); w.set_iterren(true);
w.set_itevten(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> { 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 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
// reception. // reception.
w.set_itbufen(false); 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. // Sentinel to disable transfer when an error occurs or future is canceled.
// TODO: Generate STOP condition on cancel? // TODO: Generate STOP condition on cancel?
let on_drop = OnDrop::new(|| { let on_drop = OnDrop::new(|| {
T::regs().cr2().modify(|w| { self.info.regs.cr2().modify(|w| {
w.set_dmaen(false); w.set_dmaen(false);
w.set_iterren(false); w.set_iterren(false);
w.set_itevten(false); w.set_itevten(false);
}) })
}); });
let state = T::state();
if frame.send_start() { if frame.send_start() {
// Send a START condition // Send a START condition
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_start(true); reg.set_start(true);
}); });
// Wait until START condition was generated // Wait until START condition was generated
poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err(e)),
Ok(sr1) => { Ok(sr1) => {
if sr1.start() { if sr1.start() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -405,25 +403,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
.await?; .await?;
// Check if we were the ones to generate START // 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); return Err(Error::Arbitration);
} }
// Set up current address we're trying to talk to // 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 // Wait for the address to be acknowledged
poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err(e)),
Ok(sr1) => { Ok(sr1) => {
if sr1.addr() { if sr1.addr() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -432,26 +430,26 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
.await?; .await?;
// Clear condition by reading SR2 // Clear condition by reading SR2
T::regs().sr2().read(); self.info.regs.sr2().read();
} }
let dma_transfer = unsafe { let dma_transfer = unsafe {
// Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to // 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. // 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()) self.tx_dma.as_mut().unwrap().write(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.
let poll_error = poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err::<(), Error>(e)),
Ok(_) => { Ok(_) => {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -463,7 +461,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
_ => Ok(()), _ => Ok(()),
}?; }?;
T::regs().cr2().modify(|w| { self.info.regs.cr2().modify(|w| {
w.set_dmaen(false); 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 // 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.” // requests then wait for a BTF event before programming the Stop condition.”
poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err(e)),
Ok(sr1) => { Ok(sr1) => {
if sr1.btf() { if sr1.btf() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -490,7 +488,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
}) })
.await?; .await?;
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_stop(true); 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. // Some branches below depend on whether the buffer contains only a single byte.
let single_byte = buffer.len() == 1; 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 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
// reception. // reception.
w.set_itbufen(false); 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. // Sentinel to disable transfer when an error occurs or future is canceled.
// TODO: Generate STOP condition on cancel? // TODO: Generate STOP condition on cancel?
let on_drop = OnDrop::new(|| { let on_drop = OnDrop::new(|| {
T::regs().cr2().modify(|w| { self.info.regs.cr2().modify(|w| {
w.set_dmaen(false); w.set_dmaen(false);
w.set_iterren(false); w.set_iterren(false);
w.set_itevten(false); w.set_itevten(false);
}) })
}); });
let state = T::state();
if frame.send_start() { if frame.send_start() {
// Send a START condition and set ACK bit // 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_start(true);
reg.set_ack(true); reg.set_ack(true);
}); });
// Wait until START condition was generated // Wait until START condition was generated
poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err(e)),
Ok(sr1) => { Ok(sr1) => {
if sr1.start() { if sr1.start() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -577,25 +573,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
.await?; .await?;
// Check if we were the ones to generate START // 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); return Err(Error::Arbitration);
} }
// Set up current address we're trying to talk to // 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 // Wait for the address to be acknowledged
poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err(e)),
Ok(sr1) => { Ok(sr1) => {
if sr1.addr() { if sr1.addr() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending 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 // 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. // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
if frame.send_nack() && single_byte { if frame.send_nack() && single_byte {
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_ack(false); w.set_ack(false);
}); });
} }
// Clear condition by reading SR2 // Clear condition by reading SR2
T::regs().sr2().read(); self.info.regs.sr2().read();
} else { } else {
// Before starting reception of single byte (but without START condition, i.e. in case // 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. // of continued frame), program NACK to emit at end of this byte.
if frame.send_nack() && single_byte { if frame.send_nack() && single_byte {
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_ack(false); 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 // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
// routine. // routine.
if frame.send_stop() && single_byte { if frame.send_stop() && single_byte {
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_stop(true); w.set_stop(true);
}); });
} }
@ -635,20 +631,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
let dma_transfer = unsafe { let dma_transfer = unsafe {
// Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved // 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. // 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()) self.rx_dma.as_mut().unwrap().read(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.
let poll_error = poll_fn(|cx| { 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)), Err(e) => Poll::Ready(Err::<(), Error>(e)),
_ => { _ => {
// When pending, (re-)enable interrupts to wake us up. // When pending, (re-)enable interrupts to wake us up.
Self::enable_interrupts(); Self::enable_interrupts(self.info);
Poll::Pending Poll::Pending
} }
} }
@ -659,12 +655,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
_ => Ok(()), _ => Ok(()),
}?; }?;
T::regs().cr2().modify(|w| { self.info.regs.cr2().modify(|w| {
w.set_dmaen(false); w.set_dmaen(false);
}); });
if frame.send_stop() && !single_byte { if frame.send_stop() && !single_byte {
T::regs().cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_stop(true); 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) { 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 Config = Hertz;
type ConfigError = (); type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
let timings = Timings::new(T::frequency(), *config); let timings = Timings::new(self.kernel_clock, *config);
T::regs().cr2().modify(|reg| { self.info.regs.cr2().modify(|reg| {
reg.set_freq(timings.freq); 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_f_s(timings.mode.f_s());
reg.set_duty(timings.duty.duty()); reg.set_duty(timings.duty.duty());
reg.set_ccr(timings.ccr); reg.set_ccr(timings.ccr);
}); });
T::regs().trise().modify(|reg| { self.info.regs.trise().modify(|reg| {
reg.set_trise(timings.trise); reg.set_trise(timings.trise);
}); });

@ -10,7 +10,7 @@ use super::*;
use crate::pac::i2c; use crate::pac::i2c;
pub(crate) unsafe fn on_interrupt<T: Instance>() { pub(crate) unsafe fn on_interrupt<T: Instance>() {
let regs = T::regs(); let regs = T::info().regs;
let isr = regs.isr().read(); let isr = regs.isr().read();
if isr.tcr() || isr.tc() { 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) { 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_pe(false);
reg.set_anfoff(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_presc(timings.prescale);
reg.set_scll(timings.scll); reg.set_scll(timings.scll);
reg.set_sclh(timings.sclh); reg.set_sclh(timings.sclh);
@ -40,16 +40,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
reg.set_scldel(timings.scldel); reg.set_scldel(timings.scldel);
}); });
T::regs().cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_pe(true); reg.set_pe(true);
}); });
} }
fn master_stop(&mut self) { 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( fn master_read(
info: &'static Info,
address: u8, address: u8,
length: usize, length: usize,
stop: Stop, stop: Stop,
@ -63,7 +64,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
// Wait for any previous address sequence to end // Wait for any previous address sequence to end
// automatically. This could be up to 50% of a bus // automatically. This could be up to 50% of a bus
// cycle (ie. up to 0.5/freq) // cycle (ie. up to 0.5/freq)
while T::regs().cr2().read().start() { while info.regs.cr2().read().start() {
timeout.check()?; timeout.check()?;
} }
} }
@ -78,7 +79,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
i2c::vals::Reload::COMPLETED i2c::vals::Reload::COMPLETED
}; };
T::regs().cr2().modify(|w| { info.regs.cr2().modify(|w| {
w.set_sadd((address << 1 | 0) as u16); w.set_sadd((address << 1 | 0) as u16);
w.set_add10(i2c::vals::Addmode::BIT7); w.set_add10(i2c::vals::Addmode::BIT7);
w.set_dir(i2c::vals::Dir::READ); w.set_dir(i2c::vals::Dir::READ);
@ -91,13 +92,20 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
Ok(()) 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); assert!(length < 256);
// Wait for any previous address sequence to end // Wait for any previous address sequence to end
// automatically. This could be up to 50% of a bus // automatically. This could be up to 50% of a bus
// cycle (ie. up to 0.5/freq) // cycle (ie. up to 0.5/freq)
while T::regs().cr2().read().start() { while info.regs.cr2().read().start() {
timeout.check()?; timeout.check()?;
} }
@ -110,7 +118,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
// Set START and prepare to send `bytes`. The // Set START and prepare to send `bytes`. The
// START bit can be set even if the bus is BUSY or // START bit can be set even if the bus is BUSY or
// I2C is in slave mode. // 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_sadd((address << 1 | 0) as u16);
w.set_add10(i2c::vals::Addmode::BIT7); w.set_add10(i2c::vals::Addmode::BIT7);
w.set_dir(i2c::vals::Dir::WRITE); w.set_dir(i2c::vals::Dir::WRITE);
@ -123,10 +131,10 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
Ok(()) 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); assert!(length < 256 && length > 0);
while !T::regs().isr().read().tcr() { while !info.regs.isr().read().tcr() {
timeout.check()?; timeout.check()?;
} }
@ -136,7 +144,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
i2c::vals::Reload::COMPLETED i2c::vals::Reload::COMPLETED
}; };
T::regs().cr2().modify(|w| { info.regs.cr2().modify(|w| {
w.set_nbytes(length as u8); w.set_nbytes(length as u8);
w.set_reload(reload); w.set_reload(reload);
}); });
@ -145,27 +153,27 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
} }
fn flush_txdr(&self) { fn flush_txdr(&self) {
if T::regs().isr().read().txis() { if self.info.regs.isr().read().txis() {
T::regs().txdr().write(|w| w.set_txdata(0)); self.info.regs.txdr().write(|w| w.set_txdata(0));
} }
if !T::regs().isr().read().txe() { if !self.info.regs.isr().read().txe() {
T::regs().isr().modify(|w| w.set_txe(true)) self.info.regs.isr().modify(|w| w.set_txe(true))
} }
} }
fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
loop { loop {
let isr = T::regs().isr().read(); let isr = self.info.regs.isr().read();
if isr.txe() { if isr.txe() {
return Ok(()); return Ok(());
} else if isr.berr() { } 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); return Err(Error::Bus);
} else if isr.arlo() { } 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); return Err(Error::Arbitration);
} else if isr.nackf() { } 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(); self.flush_txdr();
return Err(Error::Nack); 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> { fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
loop { loop {
let isr = T::regs().isr().read(); let isr = self.info.regs.isr().read();
if isr.rxne() { if isr.rxne() {
return Ok(()); return Ok(());
} else if isr.berr() { } 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); return Err(Error::Bus);
} else if isr.arlo() { } 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); return Err(Error::Arbitration);
} else if isr.nackf() { } 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(); self.flush_txdr();
return Err(Error::Nack); 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> { fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
loop { loop {
let isr = T::regs().isr().read(); let isr = self.info.regs.isr().read();
if isr.tc() { if isr.tc() {
return Ok(()); return Ok(());
} else if isr.berr() { } 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); return Err(Error::Bus);
} else if isr.arlo() { } 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); return Err(Error::Arbitration);
} else if isr.nackf() { } 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(); self.flush_txdr();
return Err(Error::Nack); 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); let last_chunk_idx = total_chunks.saturating_sub(1);
Self::master_read( Self::master_read(
self.info,
address, address,
read.len().min(255), read.len().min(255),
Stop::Automatic, 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() { for (number, chunk) in read.chunks_mut(255).enumerate() {
if number != 0 { 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 { for byte in chunk {
// Wait until we have received something // Wait until we have received something
self.wait_rxne(timeout)?; self.wait_rxne(timeout)?;
*byte = T::regs().rxdr().read().rxdata(); *byte = self.info.regs.rxdr().read().rxdata();
} }
} }
Ok(()) Ok(())
@ -262,6 +271,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
// //
// ST SAD+W // ST SAD+W
if let Err(err) = Self::master_write( if let Err(err) = Self::master_write(
self.info,
address, address,
write.len().min(255), write.len().min(255),
Stop::Software, Stop::Software,
@ -276,7 +286,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
for (number, chunk) in write.chunks(255).enumerate() { for (number, chunk) in write.chunks(255).enumerate() {
if number != 0 { 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 { for byte in chunk {
@ -290,7 +300,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
return Err(err); 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 // 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; let last_slice_index = write.len() - 1;
if let Err(err) = Self::master_write( if let Err(err) = Self::master_write(
self.info,
address, address,
first_length.min(255), first_length.min(255),
Stop::Software, Stop::Software,
@ -370,6 +381,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
if idx != 0 { if idx != 0 {
if let Err(err) = Self::master_continue( if let Err(err) = Self::master_continue(
self.info,
slice_len.min(255), slice_len.min(255),
(idx != last_slice_index) || (slice_len > 255), (idx != last_slice_index) || (slice_len > 255),
timeout, timeout,
@ -382,6 +394,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
for (number, chunk) in slice.chunks(255).enumerate() { for (number, chunk) in slice.chunks(255).enumerate() {
if number != 0 { if number != 0 {
if let Err(err) = Self::master_continue( if let Err(err) = Self::master_continue(
self.info,
chunk.len(), chunk.len(),
(number != last_chunk_idx) || (idx != last_slice_index), (number != last_chunk_idx) || (idx != last_slice_index),
timeout, timeout,
@ -402,7 +415,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
// Put byte on the wire // Put byte on the wire
//self.i2c.txdr.write(|w| w.txdata().bits(*byte)); //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( async fn write_dma_internal(
&mut self, &mut self,
address: u8, address: u8,
@ -425,7 +438,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
let total_len = write.len(); let total_len = write.len();
let dma_transfer = unsafe { let dma_transfer = unsafe {
let regs = T::regs(); let regs = self.info.regs;
regs.cr1().modify(|w| { regs.cr1().modify(|w| {
w.set_txdmaen(true); w.set_txdmaen(true);
if first_slice { 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()) self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
}; };
let state = T::state();
let mut remaining_len = total_len; let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| { let on_drop = OnDrop::new(|| {
let regs = T::regs(); let regs = self.info.regs;
regs.cr1().modify(|w| { regs.cr1().modify(|w| {
if last_slice { if last_slice {
w.set_txdmaen(false); w.set_txdmaen(false);
@ -451,12 +463,13 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
}); });
poll_fn(|cx| { 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 remaining_len == total_len {
if first_slice { if first_slice {
Self::master_write( Self::master_write(
self.info,
address, address,
total_len.min(255), total_len.min(255),
Stop::Software, Stop::Software,
@ -464,8 +477,8 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
timeout, timeout,
)?; )?;
} else { } else {
Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?; Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
T::regs().cr1().modify(|w| w.set_tcie(true)); self.info.regs.cr1().modify(|w| w.set_tcie(true));
} }
} else if !(isr.tcr() || isr.tc()) { } else if !(isr.tcr() || isr.tc()) {
// poll_fn was woken without an interrupt present // poll_fn was woken without an interrupt present
@ -475,10 +488,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
} else { } else {
let last_piece = (remaining_len <= 255) && last_slice; 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)); 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); 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 total_len = buffer.len();
let dma_transfer = unsafe { let dma_transfer = unsafe {
let regs = T::regs(); let regs = self.info.regs;
regs.cr1().modify(|w| { regs.cr1().modify(|w| {
w.set_rxdmaen(true); w.set_rxdmaen(true);
w.set_tcie(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()) self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
}; };
let state = T::state();
let mut remaining_len = total_len; let mut remaining_len = total_len;
let on_drop = OnDrop::new(|| { let on_drop = OnDrop::new(|| {
let regs = T::regs(); let regs = self.info.regs;
regs.cr1().modify(|w| { regs.cr1().modify(|w| {
w.set_rxdmaen(false); w.set_rxdmaen(false);
w.set_tcie(false); w.set_tcie(false);
@ -531,11 +543,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
}); });
poll_fn(|cx| { 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 remaining_len == total_len {
Self::master_read( Self::master_read(
self.info,
address, address,
total_len.min(255), total_len.min(255),
Stop::Software, Stop::Software,
@ -551,10 +564,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
} else { } else {
let last_piece = remaining_len <= 255; 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)); 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); 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) { 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 Config = Hertz;
type ConfigError = (); type ConfigError = ();
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
let timings = Timings::new(T::frequency(), *config); let timings = Timings::new(self.kernel_clock, *config);
T::regs().timingr().write(|reg| { self.info.regs.timingr().write(|reg| {
reg.set_presc(timings.prescale); reg.set_presc(timings.prescale);
reg.set_scll(timings.scll); reg.set_scll(timings.scll);
reg.set_sclh(timings.sclh); reg.set_sclh(timings.sclh);

@ -208,7 +208,7 @@ impl<'d> I2S<'d> {
// rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
// register also has to be defined. // register also has to be defined.
spi.regs.i2spr().modify(|w| { spi.info.regs.i2spr().modify(|w| {
w.set_i2sdiv(div); w.set_i2sdiv(div);
w.set_odd(match odd { w.set_odd(match odd {
true => Odd::ODD, true => Odd::ODD,
@ -235,7 +235,7 @@ impl<'d> I2S<'d> {
// 5. The I2SE bit in SPI_I2SCFGR register must be set. // 5. The I2SE bit in SPI_I2SCFGR register must be set.
spi.regs.i2scfgr().modify(|w| { spi.info.regs.i2scfgr().modify(|w| {
w.set_ckpol(config.clock_polarity.ckpol()); w.set_ckpol(config.clock_polarity.ckpol());
w.set_i2smod(true); w.set_i2smod(true);

@ -1,16 +1,25 @@
#![macro_use] #![macro_use]
macro_rules! peri_trait { macro_rules! peri_trait {
() => { (
$(irqs: [$($irq:ident),*],)?
) => {
#[allow(private_interfaces)] #[allow(private_interfaces)]
pub(crate) trait SealedInstance { pub(crate) trait SealedInstance {
const INFO: Info; #[allow(unused)]
const STATE: &'static State; fn info() -> &'static Info;
#[allow(unused)]
fn state() -> &'static State;
} }
/// SPI instance trait. /// Peripheral instance trait.
#[allow(private_bounds)] #[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;
)*)?
}
}; };
} }
@ -18,8 +27,14 @@ macro_rules! peri_trait_impl {
($instance:ident, $info:expr) => { ($instance:ident, $info:expr) => {
#[allow(private_interfaces)] #[allow(private_interfaces)]
impl SealedInstance for crate::peripherals::$instance { impl SealedInstance for crate::peripherals::$instance {
const INFO: Info = $info; fn info() -> &'static Info {
const STATE: &'static State = &State::new(); static INFO: Info = $info;
&INFO
}
fn state() -> &'static State {
static STATE: State = State::new();
&STATE
}
} }
impl Instance for crate::peripherals::$instance {} impl Instance for crate::peripherals::$instance {}
}; };

@ -67,10 +67,11 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
} }
pub(crate) trait SealedRccPeripheral { pub(crate) trait SealedRccPeripheral {
const ENABLE_BIT: ClockEnableBit;
fn frequency() -> Hertz; fn frequency() -> Hertz;
fn enable_and_reset_with_cs(cs: CriticalSection); fn enable_and_reset_with_cs(cs: CriticalSection);
fn disable_with_cs(cs: CriticalSection); fn disable_with_cs(cs: CriticalSection);
fn enable_bit() -> ClockEnableBit;
fn enable_and_reset() { fn enable_and_reset() {
critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
@ -151,7 +152,7 @@ pub(crate) struct ClockEnableBit {
impl ClockEnableBit { impl ClockEnableBit {
/// Safety: offset+bit must correspond to a valid xxxEN bit. /// Safety: offset+bit must correspond to a valid xxxEN bit.
pub(crate) unsafe fn new(offset: u8, bit: u8) -> Self { pub(crate) const unsafe fn new(offset: u8, bit: u8) -> Self {
Self { offset, bit } Self { offset, bit }
} }

@ -13,7 +13,7 @@ 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};
use crate::rcc::{ClockEnableBit, RccPeripheral}; use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
use crate::time::Hertz; use crate::time::Hertz;
use crate::Peripheral; use crate::Peripheral;
@ -93,8 +93,7 @@ impl Config {
} }
/// SPI driver. /// SPI driver.
pub struct Spi<'d, M: PeriMode> { pub struct Spi<'d, M: PeriMode> {
pub(crate) regs: Regs, pub(crate) info: &'static Info,
enable_bit: ClockEnableBit,
kernel_clock: Hertz, kernel_clock: Hertz,
sck: Option<PeripheralRef<'d, AnyPin>>, sck: Option<PeripheralRef<'d, AnyPin>>,
mosi: Option<PeripheralRef<'d, AnyPin>>, mosi: Option<PeripheralRef<'d, AnyPin>>,
@ -115,7 +114,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
config: Config, config: Config,
) -> Self { ) -> Self {
let regs = T::INFO.regs; let regs = T::info().regs;
let kernel_clock = T::frequency(); let kernel_clock = T::frequency();
let br = compute_baud_rate(kernel_clock, config.frequency); let br = compute_baud_rate(kernel_clock, config.frequency);
@ -205,8 +204,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
} }
Self { Self {
regs, info: T::info(),
enable_bit: T::enable_bit(),
kernel_clock, kernel_clock,
sck, sck,
mosi, mosi,
@ -228,7 +226,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
let br = compute_baud_rate(self.kernel_clock, config.frequency); let br = compute_baud_rate(self.kernel_clock, config.frequency);
#[cfg(any(spi_v1, spi_f1, spi_v2))] #[cfg(any(spi_v1, spi_f1, spi_v2))]
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_cpha(cpha); w.set_cpha(cpha);
w.set_cpol(cpol); w.set_cpol(cpol);
w.set_br(br); w.set_br(br);
@ -237,12 +235,12 @@ impl<'d, M: PeriMode> Spi<'d, M> {
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
{ {
self.regs.cfg2().modify(|w| { self.info.regs.cfg2().modify(|w| {
w.set_cpha(cpha); w.set_cpha(cpha);
w.set_cpol(cpol); w.set_cpol(cpol);
w.set_lsbfirst(lsbfirst); w.set_lsbfirst(lsbfirst);
}); });
self.regs.cfg1().modify(|w| { self.info.regs.cfg1().modify(|w| {
w.set_mbr(br); w.set_mbr(br);
}); });
} }
@ -252,11 +250,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
/// Get current SPI configuration. /// Get current SPI configuration.
pub fn get_current_config(&self) -> Config { pub fn get_current_config(&self) -> Config {
#[cfg(any(spi_v1, spi_f1, spi_v2))] #[cfg(any(spi_v1, spi_f1, spi_v2))]
let cfg = self.regs.cr1().read(); let cfg = self.info.regs.cr1().read();
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
let cfg = self.regs.cfg2().read(); let cfg = self.info.regs.cfg2().read();
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
let cfg1 = self.regs.cfg1().read(); let cfg1 = self.info.regs.cfg1().read();
let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
Polarity::IdleLow Polarity::IdleLow
@ -296,40 +294,40 @@ impl<'d, M: PeriMode> Spi<'d, M> {
#[cfg(any(spi_v1, spi_f1))] #[cfg(any(spi_v1, spi_f1))]
{ {
self.regs.cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_spe(false); reg.set_spe(false);
reg.set_dff(word_size) reg.set_dff(word_size)
}); });
self.regs.cr1().modify(|reg| { self.info.regs.cr1().modify(|reg| {
reg.set_spe(true); reg.set_spe(true);
}); });
} }
#[cfg(spi_v2)] #[cfg(spi_v2)]
{ {
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(false); w.set_spe(false);
}); });
self.regs.cr2().modify(|w| { self.info.regs.cr2().modify(|w| {
w.set_frxth(word_size.1); w.set_frxth(word_size.1);
w.set_ds(word_size.0); w.set_ds(word_size.0);
}); });
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
} }
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
{ {
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_csusp(true); w.set_csusp(true);
}); });
while self.regs.sr().read().eot() {} while self.info.regs.sr().read().eot() {}
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(false); w.set_spe(false);
}); });
self.regs.cfg1().modify(|w| { self.info.regs.cfg1().modify(|w| {
w.set_dsize(word_size); w.set_dsize(word_size);
}); });
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_csusp(false); w.set_csusp(false);
w.set_spe(true); w.set_spe(true);
}); });
@ -340,22 +338,22 @@ impl<'d, M: PeriMode> Spi<'d, M> {
/// Blocking write. /// Blocking write.
pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
self.regs.cr1().modify(|w| w.set_spe(true)); self.info.regs.cr1().modify(|w| w.set_spe(true));
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
for word in words.iter() { for word in words.iter() {
let _ = transfer_word(self.regs, *word)?; let _ = transfer_word(self.info.regs, *word)?;
} }
Ok(()) Ok(())
} }
/// Blocking read. /// Blocking read.
pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
self.regs.cr1().modify(|w| w.set_spe(true)); self.info.regs.cr1().modify(|w| w.set_spe(true));
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
for word in words.iter_mut() { for word in words.iter_mut() {
*word = transfer_word(self.regs, W::default())?; *word = transfer_word(self.info.regs, W::default())?;
} }
Ok(()) Ok(())
} }
@ -364,11 +362,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
/// ///
/// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time. /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
self.regs.cr1().modify(|w| w.set_spe(true)); self.info.regs.cr1().modify(|w| w.set_spe(true));
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
for word in words.iter_mut() { for word in words.iter_mut() {
*word = transfer_word(self.regs, *word)?; *word = transfer_word(self.info.regs, *word)?;
} }
Ok(()) Ok(())
} }
@ -380,13 +378,13 @@ impl<'d, M: PeriMode> Spi<'d, M> {
/// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored. /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
/// If `write` is shorter it is padded with zero bytes. /// If `write` is shorter it is padded with zero bytes.
pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
self.regs.cr1().modify(|w| w.set_spe(true)); self.info.regs.cr1().modify(|w| w.set_spe(true));
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
let len = read.len().max(write.len()); let len = read.len().max(write.len());
for i in 0..len { for i in 0..len {
let wb = write.get(i).copied().unwrap_or_default(); let wb = write.get(i).copied().unwrap_or_default();
let rb = transfer_word(self.regs, wb)?; let rb = transfer_word(self.info.regs, wb)?;
if let Some(r) = read.get_mut(i) { if let Some(r) = read.get_mut(i) {
*r = rb; *r = rb;
} }
@ -588,25 +586,25 @@ impl<'d> Spi<'d, Async> {
} }
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(false); w.set_spe(false);
}); });
let tx_dst = self.regs.tx_ptr(); let tx_dst = self.info.regs.tx_ptr();
let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) }; let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
set_txdmaen(self.regs, true); set_txdmaen(self.info.regs, true);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
tx_f.await; tx_f.await;
finish_dma(self.regs); finish_dma(self.info.regs);
Ok(()) Ok(())
} }
@ -618,22 +616,22 @@ impl<'d> Spi<'d, Async> {
} }
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(false); w.set_spe(false);
}); });
// SPIv3 clears rxfifo on SPE=0 // SPIv3 clears rxfifo on SPE=0
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
set_rxdmaen(self.regs, true); set_rxdmaen(self.info.regs, true);
let clock_byte_count = data.len(); let clock_byte_count = data.len();
let rx_src = self.regs.rx_ptr(); let rx_src = self.info.regs.rx_ptr();
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) }; let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
let tx_dst = self.regs.tx_ptr(); let tx_dst = self.info.regs.tx_ptr();
let clock_byte = 0x00u8; let clock_byte = 0x00u8;
let tx_f = unsafe { let tx_f = unsafe {
self.tx_dma self.tx_dma
@ -642,18 +640,18 @@ impl<'d> Spi<'d, Async> {
.write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default()) .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
}; };
set_txdmaen(self.regs, true); set_txdmaen(self.info.regs, true);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
join(tx_f, rx_f).await; join(tx_f, rx_f).await;
finish_dma(self.regs); finish_dma(self.info.regs);
Ok(()) Ok(())
} }
@ -667,20 +665,20 @@ impl<'d> Spi<'d, Async> {
} }
self.set_word_size(W::CONFIG); self.set_word_size(W::CONFIG);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(false); w.set_spe(false);
}); });
// SPIv3 clears rxfifo on SPE=0 // SPIv3 clears rxfifo on SPE=0
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
flush_rx_fifo(self.regs); flush_rx_fifo(self.info.regs);
set_rxdmaen(self.regs, true); set_rxdmaen(self.info.regs, true);
let rx_src = self.regs.rx_ptr(); let rx_src = self.info.regs.rx_ptr();
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
let tx_dst = self.regs.tx_ptr(); let tx_dst = self.info.regs.tx_ptr();
let tx_f = unsafe { let tx_f = unsafe {
self.tx_dma self.tx_dma
.as_mut() .as_mut()
@ -688,18 +686,18 @@ impl<'d> Spi<'d, Async> {
.write_raw(write, tx_dst, Default::default()) .write_raw(write, tx_dst, Default::default())
}; };
set_txdmaen(self.regs, true); set_txdmaen(self.info.regs, true);
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4, spi_v5))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
self.regs.cr1().modify(|w| { self.info.regs.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
join(tx_f, rx_f).await; join(tx_f, rx_f).await;
finish_dma(self.regs); finish_dma(self.info.regs);
Ok(()) Ok(())
} }
@ -728,7 +726,7 @@ impl<'d, M: PeriMode> Drop for Spi<'d, M> {
self.mosi.as_ref().map(|x| x.set_as_disconnected()); self.mosi.as_ref().map(|x| x.set_as_disconnected());
self.miso.as_ref().map(|x| x.set_as_disconnected()); self.miso.as_ref().map(|x| x.set_as_disconnected());
self.enable_bit.disable(); self.info.enable_bit.disable();
} }
} }
@ -1106,8 +1104,9 @@ mod word_impl {
impl_word!(u32, 32 - 1); impl_word!(u32, 32 - 1);
} }
struct Info { pub(crate) struct Info {
regs: Regs, pub(crate) regs: Regs,
pub(crate) enable_bit: ClockEnableBit,
} }
struct State {} struct State {}
@ -1134,6 +1133,7 @@ foreach_peripheral!(
(spi, $inst:ident) => { (spi, $inst:ident) => {
peri_trait_impl!($inst, Info { peri_trait_impl!($inst, Info {
regs: crate::pac::$inst, regs: crate::pac::$inst,
enable_bit: crate::peripherals::$inst::ENABLE_BIT,
}); });
}; };
); );

@ -6,11 +6,10 @@ use core::cell::RefCell;
use defmt::*; use defmt::*;
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::bind_interrupts;
use embassy_stm32::i2c::{self, I2c}; use embassy_stm32::i2c::{self, I2c};
use embassy_stm32::mode::Async; use embassy_stm32::mode::Async;
use embassy_stm32::peripherals::{self, I2C1};
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, peripherals};
use embassy_sync::blocking_mutex::NoopMutex; use embassy_sync::blocking_mutex::NoopMutex;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use static_cell::StaticCell; 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_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; 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 { bind_interrupts!(struct Irqs {
I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; 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 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, Async>; pub type TempSensI2c = I2c<'static, Async>;
static TEMP: AtomicI32 = AtomicI32::new(0); static TEMP: AtomicI32 = AtomicI32::new(0);