mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
stm32/spi: remove peripheral generic param.
This commit is contained in:
parent
eeb6ffce4c
commit
ca2eef5387
@ -153,17 +153,17 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
/// I2S driver.
|
||||
pub struct I2S<'d, T: Instance> {
|
||||
_peri: Spi<'d, T, Async>,
|
||||
pub struct I2S<'d> {
|
||||
_peri: Spi<'d, Async>,
|
||||
sd: Option<PeripheralRef<'d, AnyPin>>,
|
||||
ws: Option<PeripheralRef<'d, AnyPin>>,
|
||||
ck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> I2S<'d, T> {
|
||||
impl<'d> I2S<'d> {
|
||||
/// Note: Full-Duplex modes are not supported at this time
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sd: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
ws: impl Peripheral<P = impl WsPin<T>> + 'd,
|
||||
@ -208,7 +208,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
||||
// rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
|
||||
// register also has to be defined.
|
||||
|
||||
T::REGS.i2spr().modify(|w| {
|
||||
spi.regs.i2spr().modify(|w| {
|
||||
w.set_i2sdiv(div);
|
||||
w.set_odd(match odd {
|
||||
true => Odd::ODD,
|
||||
@ -235,7 +235,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
||||
|
||||
// 5. The I2SE bit in SPI_I2SCFGR register must be set.
|
||||
|
||||
T::REGS.i2scfgr().modify(|w| {
|
||||
spi.regs.i2scfgr().modify(|w| {
|
||||
w.set_ckpol(config.clock_polarity.ckpol());
|
||||
|
||||
w.set_i2smod(true);
|
||||
@ -276,7 +276,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Drop for I2S<'d, T> {
|
||||
impl<'d> Drop for I2S<'d> {
|
||||
fn drop(&mut self) {
|
||||
self.sd.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.ws.as_ref().map(|x| x.set_as_disconnected());
|
||||
|
@ -1,5 +1,30 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! peri_trait {
|
||||
() => {
|
||||
#[allow(private_interfaces)]
|
||||
pub(crate) trait SealedInstance {
|
||||
const INFO: Info;
|
||||
const STATE: &'static State;
|
||||
}
|
||||
|
||||
/// SPI instance trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! peri_trait_impl {
|
||||
($instance:ident, $info:expr) => {
|
||||
#[allow(private_interfaces)]
|
||||
impl SealedInstance for crate::peripherals::$instance {
|
||||
const INFO: Info = $info;
|
||||
const STATE: &'static State = &State::new();
|
||||
}
|
||||
impl Instance for crate::peripherals::$instance {}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! pin_trait {
|
||||
($signal:ident, $instance:path $(, $mode:path)?) => {
|
||||
#[doc = concat!(stringify!($signal), " pin trait")]
|
||||
|
@ -6,16 +6,16 @@ use core::ptr;
|
||||
|
||||
use embassy_embedded_hal::SetConfig;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
use embassy_hal_internal::PeripheralRef;
|
||||
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||
|
||||
use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
|
||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
||||
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
||||
use crate::pac::spi::{regs, vals, Spi as Regs};
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::rcc::{ClockEnableBit, RccPeripheral};
|
||||
use crate::time::Hertz;
|
||||
use crate::{peripherals, Peripheral};
|
||||
use crate::Peripheral;
|
||||
|
||||
/// SPI error.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@ -92,8 +92,10 @@ impl Config {
|
||||
}
|
||||
}
|
||||
/// SPI driver.
|
||||
pub struct Spi<'d, T: Instance, M: PeriMode> {
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
pub struct Spi<'d, M: PeriMode> {
|
||||
pub(crate) regs: Regs,
|
||||
enable_bit: ClockEnableBit,
|
||||
kernel_clock: Hertz,
|
||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||
@ -103,9 +105,9 @@ pub struct Spi<'d, T: Instance, M: PeriMode> {
|
||||
current_word_size: word_impl::Config,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
fn new_inner(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
fn new_inner<T: Instance>(
|
||||
_peri: impl Peripheral<P = T> + 'd,
|
||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||
@ -113,11 +115,9 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
rx_dma: Option<ChannelAndRequest<'d>>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(peri);
|
||||
|
||||
let pclk = T::frequency();
|
||||
let freq = config.frequency;
|
||||
let br = compute_baud_rate(pclk, freq);
|
||||
let regs = T::INFO.regs;
|
||||
let kernel_clock = T::frequency();
|
||||
let br = compute_baud_rate(kernel_clock, config.frequency);
|
||||
|
||||
let cpha = config.raw_phase();
|
||||
let cpol = config.raw_polarity();
|
||||
@ -128,10 +128,10 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
|
||||
#[cfg(any(spi_v1, spi_f1))]
|
||||
{
|
||||
T::REGS.cr2().modify(|w| {
|
||||
regs.cr2().modify(|w| {
|
||||
w.set_ssoe(false);
|
||||
});
|
||||
T::REGS.cr1().modify(|w| {
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_cpha(cpha);
|
||||
w.set_cpol(cpol);
|
||||
|
||||
@ -151,13 +151,13 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
}
|
||||
#[cfg(spi_v2)]
|
||||
{
|
||||
T::REGS.cr2().modify(|w| {
|
||||
regs.cr2().modify(|w| {
|
||||
let (ds, frxth) = <u8 as SealedWord>::CONFIG;
|
||||
w.set_frxth(frxth);
|
||||
w.set_ds(ds);
|
||||
w.set_ssoe(false);
|
||||
});
|
||||
T::REGS.cr1().modify(|w| {
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_cpha(cpha);
|
||||
w.set_cpol(cpol);
|
||||
|
||||
@ -173,8 +173,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
}
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
{
|
||||
T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
|
||||
T::REGS.cfg2().modify(|w| {
|
||||
regs.ifcr().write(|w| w.0 = 0xffff_ffff);
|
||||
regs.cfg2().modify(|w| {
|
||||
//w.set_ssoe(true);
|
||||
w.set_ssoe(false);
|
||||
w.set_cpha(cpha);
|
||||
@ -189,23 +189,25 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
w.set_afcntr(true);
|
||||
w.set_ssiop(vals::Ssiop::ACTIVEHIGH);
|
||||
});
|
||||
T::REGS.cfg1().modify(|w| {
|
||||
regs.cfg1().modify(|w| {
|
||||
w.set_crcen(false);
|
||||
w.set_mbr(br);
|
||||
w.set_dsize(<u8 as SealedWord>::CONFIG);
|
||||
w.set_fthlv(vals::Fthlv::ONEFRAME);
|
||||
});
|
||||
T::REGS.cr2().modify(|w| {
|
||||
regs.cr2().modify(|w| {
|
||||
w.set_tsize(0);
|
||||
});
|
||||
T::REGS.cr1().modify(|w| {
|
||||
regs.cr1().modify(|w| {
|
||||
w.set_ssi(false);
|
||||
w.set_spe(true);
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
_peri: peri,
|
||||
regs,
|
||||
enable_bit: T::enable_bit(),
|
||||
kernel_clock,
|
||||
sck,
|
||||
mosi,
|
||||
miso,
|
||||
@ -223,12 +225,10 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
|
||||
let lsbfirst = config.raw_byte_order();
|
||||
|
||||
let pclk = T::frequency();
|
||||
let freq = config.frequency;
|
||||
let br = compute_baud_rate(pclk, freq);
|
||||
let br = compute_baud_rate(self.kernel_clock, config.frequency);
|
||||
|
||||
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_cpha(cpha);
|
||||
w.set_cpol(cpol);
|
||||
w.set_br(br);
|
||||
@ -237,12 +237,12 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
{
|
||||
T::REGS.cfg2().modify(|w| {
|
||||
self.regs.cfg2().modify(|w| {
|
||||
w.set_cpha(cpha);
|
||||
w.set_cpol(cpol);
|
||||
w.set_lsbfirst(lsbfirst);
|
||||
});
|
||||
T::REGS.cfg1().modify(|w| {
|
||||
self.regs.cfg1().modify(|w| {
|
||||
w.set_mbr(br);
|
||||
});
|
||||
}
|
||||
@ -252,11 +252,11 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
/// Get current SPI configuration.
|
||||
pub fn get_current_config(&self) -> Config {
|
||||
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
||||
let cfg = T::REGS.cr1().read();
|
||||
let cfg = self.regs.cr1().read();
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
let cfg = T::REGS.cfg2().read();
|
||||
let cfg = self.regs.cfg2().read();
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
let cfg1 = T::REGS.cfg1().read();
|
||||
let cfg1 = self.regs.cfg1().read();
|
||||
|
||||
let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
|
||||
Polarity::IdleLow
|
||||
@ -280,8 +280,7 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
let br = cfg1.mbr();
|
||||
|
||||
let pclk = T::frequency();
|
||||
let frequency = compute_frequency(pclk, br);
|
||||
let frequency = compute_frequency(self.kernel_clock, br);
|
||||
|
||||
Config {
|
||||
mode: Mode { polarity, phase },
|
||||
@ -297,40 +296,40 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
|
||||
#[cfg(any(spi_v1, spi_f1))]
|
||||
{
|
||||
T::REGS.cr1().modify(|reg| {
|
||||
self.regs.cr1().modify(|reg| {
|
||||
reg.set_spe(false);
|
||||
reg.set_dff(word_size)
|
||||
});
|
||||
T::REGS.cr1().modify(|reg| {
|
||||
self.regs.cr1().modify(|reg| {
|
||||
reg.set_spe(true);
|
||||
});
|
||||
}
|
||||
#[cfg(spi_v2)]
|
||||
{
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
T::REGS.cr2().modify(|w| {
|
||||
self.regs.cr2().modify(|w| {
|
||||
w.set_frxth(word_size.1);
|
||||
w.set_ds(word_size.0);
|
||||
});
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
}
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
{
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_csusp(true);
|
||||
});
|
||||
while T::REGS.sr().read().eot() {}
|
||||
T::REGS.cr1().modify(|w| {
|
||||
while self.regs.sr().read().eot() {}
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
T::REGS.cfg1().modify(|w| {
|
||||
self.regs.cfg1().modify(|w| {
|
||||
w.set_dsize(word_size);
|
||||
});
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_csusp(false);
|
||||
w.set_spe(true);
|
||||
});
|
||||
@ -341,22 +340,22 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
|
||||
/// Blocking write.
|
||||
pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
|
||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(T::REGS);
|
||||
self.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter() {
|
||||
let _ = transfer_word(T::REGS, *word)?;
|
||||
let _ = transfer_word(self.regs, *word)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Blocking read.
|
||||
pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(T::REGS);
|
||||
self.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(T::REGS, W::default())?;
|
||||
*word = transfer_word(self.regs, W::default())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -365,11 +364,11 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
///
|
||||
/// 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> {
|
||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(T::REGS);
|
||||
self.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(T::REGS, *word)?;
|
||||
*word = transfer_word(self.regs, *word)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -381,13 +380,13 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
/// 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.
|
||||
pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
|
||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(T::REGS);
|
||||
self.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
let len = read.len().max(write.len());
|
||||
for i in 0..len {
|
||||
let wb = write.get(i).copied().unwrap_or_default();
|
||||
let rb = transfer_word(T::REGS, wb)?;
|
||||
let rb = transfer_word(self.regs, wb)?;
|
||||
if let Some(r) = read.get_mut(i) {
|
||||
*r = rb;
|
||||
}
|
||||
@ -396,9 +395,9 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
impl<'d> Spi<'d, Blocking> {
|
||||
/// Create a new blocking SPI driver.
|
||||
pub fn new_blocking(
|
||||
pub fn new_blocking<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
@ -417,7 +416,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
}
|
||||
|
||||
/// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
||||
pub fn new_blocking_rxonly(
|
||||
pub fn new_blocking_rxonly<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
@ -435,7 +434,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
}
|
||||
|
||||
/// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
||||
pub fn new_blocking_txonly(
|
||||
pub fn new_blocking_txonly<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
@ -455,7 +454,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
/// Create a new SPI driver, in TX-only mode, without SCK pin.
|
||||
///
|
||||
/// This can be useful for bit-banging non-SPI protocols.
|
||||
pub fn new_blocking_txonly_nosck(
|
||||
pub fn new_blocking_txonly_nosck<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
config: Config,
|
||||
@ -472,9 +471,9 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
impl<'d> Spi<'d, Async> {
|
||||
/// Create a new SPI driver.
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
@ -495,7 +494,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
||||
pub fn new_rxonly(
|
||||
pub fn new_rxonly<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
@ -514,7 +513,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
||||
pub fn new_txonly(
|
||||
pub fn new_txonly<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
@ -535,7 +534,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
/// Create a new SPI driver, in TX-only mode, without SCK pin.
|
||||
///
|
||||
/// This can be useful for bit-banging non-SPI protocols.
|
||||
pub fn new_txonly_nosck(
|
||||
pub fn new_txonly_nosck<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
@ -554,7 +553,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
|
||||
#[cfg(stm32wl)]
|
||||
/// Useful for on chip peripherals like SUBGHZ which are hardwired.
|
||||
pub fn new_subghz(
|
||||
pub fn new_subghz<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
@ -562,7 +561,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
// see RM0453 rev 1 section 7.2.13 page 291
|
||||
// The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
|
||||
// The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz.
|
||||
let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
|
||||
let pclk3_freq = <crate::peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
|
||||
let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
|
||||
let mut config = Config::default();
|
||||
config.mode = MODE_0;
|
||||
@ -573,7 +572,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new_internal(
|
||||
pub(crate) fn new_internal<T: Instance>(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
@ -589,25 +588,25 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_dst = self.regs.tx_ptr();
|
||||
let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
set_txdmaen(self.regs, true);
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
tx_f.await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
finish_dma(self.regs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -619,22 +618,22 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
// SPIv3 clears rxfifo on SPE=0
|
||||
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
|
||||
flush_rx_fifo(T::REGS);
|
||||
flush_rx_fifo(self.regs);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
set_rxdmaen(self.regs, true);
|
||||
|
||||
let clock_byte_count = data.len();
|
||||
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_src = self.regs.rx_ptr();
|
||||
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
|
||||
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_dst = self.regs.tx_ptr();
|
||||
let clock_byte = 0x00u8;
|
||||
let tx_f = unsafe {
|
||||
self.tx_dma
|
||||
@ -643,18 +642,18 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
.write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
|
||||
};
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
set_txdmaen(self.regs, true);
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
finish_dma(self.regs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -668,20 +667,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
// SPIv3 clears rxfifo on SPE=0
|
||||
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
|
||||
flush_rx_fifo(T::REGS);
|
||||
flush_rx_fifo(self.regs);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
set_rxdmaen(self.regs, true);
|
||||
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_src = self.regs.rx_ptr();
|
||||
let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
|
||||
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_dst = self.regs.tx_ptr();
|
||||
let tx_f = unsafe {
|
||||
self.tx_dma
|
||||
.as_mut()
|
||||
@ -689,18 +688,18 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
.write_raw(write, tx_dst, Default::default())
|
||||
};
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
set_txdmaen(self.regs, true);
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
self.regs.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
finish_dma(self.regs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -723,13 +722,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> Drop for Spi<'d, T, M> {
|
||||
impl<'d, M: PeriMode> Drop for Spi<'d, M> {
|
||||
fn drop(&mut self) {
|
||||
self.sck.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());
|
||||
|
||||
T::disable();
|
||||
self.enable_bit.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -738,8 +737,8 @@ use vals::Br;
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
use vals::Mbr as Br;
|
||||
|
||||
fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
|
||||
let val = match clocks.0 / freq.0 {
|
||||
fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br {
|
||||
let val = match kernel_clock.0 / freq.0 {
|
||||
0 => panic!("You are trying to reach a frequency higher than the clock"),
|
||||
1..=2 => 0b000,
|
||||
3..=5 => 0b001,
|
||||
@ -754,7 +753,7 @@ fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
|
||||
Br::from_bits(val)
|
||||
}
|
||||
|
||||
fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
|
||||
fn compute_frequency(kernel_clock: Hertz, br: Br) -> Hertz {
|
||||
let div: u16 = match br {
|
||||
Br::DIV2 => 2,
|
||||
Br::DIV4 => 4,
|
||||
@ -766,7 +765,7 @@ fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
|
||||
Br::DIV256 => 256,
|
||||
};
|
||||
|
||||
clocks / div
|
||||
kernel_clock / div
|
||||
}
|
||||
|
||||
trait RegsExt {
|
||||
@ -941,7 +940,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
|
||||
// some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289
|
||||
macro_rules! impl_blocking {
|
||||
($w:ident) => {
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, T, M> {
|
||||
impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
|
||||
@ -949,7 +948,7 @@ macro_rules! impl_blocking {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, T, M> {
|
||||
impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
|
||||
@ -963,11 +962,11 @@ macro_rules! impl_blocking {
|
||||
impl_blocking!(u8);
|
||||
impl_blocking!(u16);
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, T, M> {
|
||||
impl<'d, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, M> {
|
||||
impl<'d, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -1000,7 +999,7 @@ impl embedded_hal_1::spi::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Async> {
|
||||
impl<'d, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async> {
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -1022,10 +1021,6 @@ impl<'d, T: Instance, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait SealedInstance {
|
||||
const REGS: Regs;
|
||||
}
|
||||
|
||||
trait SealedWord {
|
||||
const CONFIG: word_impl::Config;
|
||||
}
|
||||
@ -1111,9 +1106,19 @@ mod word_impl {
|
||||
impl_word!(u32, 32 - 1);
|
||||
}
|
||||
|
||||
/// SPI instance trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
|
||||
struct Info {
|
||||
regs: Regs,
|
||||
}
|
||||
|
||||
struct State {}
|
||||
|
||||
impl State {
|
||||
const fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
peri_trait!();
|
||||
|
||||
pin_trait!(SckPin, Instance);
|
||||
pin_trait!(MosiPin, Instance);
|
||||
@ -1127,15 +1132,13 @@ dma_trait!(TxDma, Instance);
|
||||
|
||||
foreach_peripheral!(
|
||||
(spi, $inst:ident) => {
|
||||
impl SealedInstance for peripherals::$inst {
|
||||
const REGS: Regs = crate::pac::$inst;
|
||||
}
|
||||
|
||||
impl Instance for peripherals::$inst {}
|
||||
peri_trait_impl!($inst, Info {
|
||||
regs: crate::pac::$inst,
|
||||
});
|
||||
};
|
||||
);
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> SetConfig for Spi<'d, T, M> {
|
||||
impl<'d, M: PeriMode> SetConfig for Spi<'d, M> {
|
||||
type Config = Config;
|
||||
type ConfigError = ();
|
||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||
|
@ -8,7 +8,6 @@ use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Blocking;
|
||||
use embassy_stm32::peripherals::SPI3;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{spi, Config};
|
||||
use heapless::String;
|
||||
@ -16,7 +15,7 @@ use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, Blocking>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
|
@ -9,7 +9,7 @@ use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{peripherals, spi, Config};
|
||||
use embassy_stm32::{spi, Config};
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -19,7 +19,7 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
static mut RAM_D3: [u8; 64 * 1024] = [0u8; 64 * 1024];
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI6, Async>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, Async>) {
|
||||
let read_buffer = unsafe { &mut RAM_D3[0..128] };
|
||||
let write_buffer = unsafe { &mut RAM_D3[128..256] };
|
||||
|
||||
|
@ -9,13 +9,13 @@ use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{peripherals, spi, Config};
|
||||
use embassy_stm32::{spi, Config};
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, Async>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
let mut read = [0; 128];
|
||||
|
@ -8,7 +8,6 @@ use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Blocking;
|
||||
use embassy_stm32::peripherals::SPI3;
|
||||
use embassy_stm32::spi;
|
||||
use embassy_stm32::time::mhz;
|
||||
use heapless::String;
|
||||
@ -16,7 +15,7 @@ use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, Blocking>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
|
@ -8,14 +8,14 @@ use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::spi;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{peripherals, spi};
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, Async>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
let mut read = [0; 128];
|
||||
|
@ -55,7 +55,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address([192, 168, 1, 5]), 24);
|
||||
// Listen port for the webserver
|
||||
const HTTP_LISTEN_PORT: u16 = 80;
|
||||
|
||||
pub type SpeSpi = Spi<'static, peripherals::SPI2, Async>;
|
||||
pub type SpeSpi = Spi<'static, Async>;
|
||||
pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
|
||||
pub type SpeInt = exti::ExtiInput<'static>;
|
||||
pub type SpeRst = Output<'static>;
|
||||
|
Loading…
Reference in New Issue
Block a user