mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 16:23:10 +00:00
Merge pull request #2819 from embassy-rs/spi-nodma
stm32/spi: remove DMA generic params.
This commit is contained in:
commit
d66c054aae
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -15,10 +15,11 @@
|
||||
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
|
||||
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
|
||||
"rust-analyzer.cargo.features": [
|
||||
"stm32f103c8",
|
||||
"stm32f446re",
|
||||
"time-driver-any",
|
||||
"unstable-pac",
|
||||
"exti",
|
||||
"rt",
|
||||
],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
// Uncomment ONE line for the chip you want to work on.
|
||||
|
@ -2,6 +2,7 @@
|
||||
use embassy_hal_internal::into_ref;
|
||||
|
||||
use crate::gpio::{AFType, AnyPin, SealedPin};
|
||||
use crate::mode::Async;
|
||||
use crate::pac::spi::vals;
|
||||
use crate::spi::{Config as SpiConfig, *};
|
||||
use crate::time::Hertz;
|
||||
@ -152,15 +153,15 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
/// I2S driver.
|
||||
pub struct I2S<'d, T: Instance, Tx, Rx> {
|
||||
_peri: Spi<'d, T, Tx, Rx>,
|
||||
pub struct I2S<'d, T: Instance> {
|
||||
_peri: Spi<'d, T, 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, Tx, Rx> I2S<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance> I2S<'d, T> {
|
||||
/// Note: Full-Duplex modes are not supported at this time
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
@ -168,8 +169,8 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
|
||||
ws: impl Peripheral<P = impl WsPin<T>> + 'd,
|
||||
ck: impl Peripheral<P = impl CkPin<T>> + 'd,
|
||||
mck: impl Peripheral<P = impl MckPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
freq: Hertz,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
@ -265,24 +266,17 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
|
||||
}
|
||||
|
||||
/// Write audio data.
|
||||
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
{
|
||||
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> {
|
||||
self._peri.write(data).await
|
||||
}
|
||||
|
||||
/// Read audio data.
|
||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
Rx: RxDma<T>,
|
||||
{
|
||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
|
||||
self._peri.read(data).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance> Drop for I2S<'d, T> {
|
||||
fn drop(&mut self) {
|
||||
self.sd.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.ws.as_ref().map(|x| x.set_as_disconnected());
|
||||
|
@ -17,6 +17,29 @@ include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
|
||||
// Utilities
|
||||
pub mod time;
|
||||
mod traits;
|
||||
/// Operating modes for peripherals.
|
||||
pub mod mode {
|
||||
trait SealedMode {}
|
||||
|
||||
/// Operating mode for a peripheral.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Mode: SealedMode {}
|
||||
|
||||
macro_rules! impl_mode {
|
||||
($name:ident) => {
|
||||
impl SealedMode for $name {}
|
||||
impl Mode for $name {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Blocking mode.
|
||||
pub struct Blocking;
|
||||
/// Async mode.
|
||||
pub struct Async;
|
||||
|
||||
impl_mode!(Blocking);
|
||||
impl_mode!(Async);
|
||||
}
|
||||
|
||||
// Always-present hardware
|
||||
pub mod dma;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Serial Peripheral Interface (SPI)
|
||||
#![macro_use]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr;
|
||||
|
||||
use embassy_embedded_hal::SetConfig;
|
||||
@ -8,8 +9,9 @@ use embassy_futures::join::join;
|
||||
use embassy_hal_internal::{into_ref, 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, Transfer};
|
||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _};
|
||||
use crate::dma::{slice_ptr_parts, word, AnyChannel, Request, Transfer};
|
||||
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::time::Hertz;
|
||||
@ -81,163 +83,37 @@ impl Config {
|
||||
BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sck_pull_mode(&self) -> Pull {
|
||||
match self.mode.polarity {
|
||||
Polarity::IdleLow => Pull::Down,
|
||||
Polarity::IdleHigh => Pull::Up,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// SPI driver.
|
||||
pub struct Spi<'d, T: Instance, Tx, Rx> {
|
||||
pub struct Spi<'d, T: Instance, M: PeriMode> {
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||
txdma: PeripheralRef<'d, Tx>,
|
||||
rxdma: PeripheralRef<'d, Rx>,
|
||||
txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
||||
rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
||||
_phantom: PhantomData<M>,
|
||||
current_word_size: word_impl::Config,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
/// Create a new SPI driver.
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(peri, sck, mosi, miso);
|
||||
|
||||
let sck_pull_mode = match config.mode.polarity {
|
||||
Polarity::IdleLow => Pull::Down,
|
||||
Polarity::IdleHigh => Pull::Up,
|
||||
};
|
||||
|
||||
sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode);
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
miso.set_as_af(miso.af_num(), AFType::Input);
|
||||
miso.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.map_into()),
|
||||
Some(mosi.map_into()),
|
||||
Some(miso.map_into()),
|
||||
txdma,
|
||||
rxdma,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
||||
pub fn new_rxonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd, // TODO remove
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(sck, miso);
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
miso.set_as_af(miso.af_num(), AFType::Input);
|
||||
miso.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.map_into()),
|
||||
None,
|
||||
Some(miso.map_into()),
|
||||
txdma,
|
||||
rxdma,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
||||
pub fn new_txonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd, // TODO remove
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(sck, mosi);
|
||||
sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
|
||||
sck.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
|
||||
mosi.set_speed(crate::gpio::Speed::VeryHigh);
|
||||
|
||||
Self::new_inner(
|
||||
peri,
|
||||
Some(sck.map_into()),
|
||||
Some(mosi.map_into()),
|
||||
None,
|
||||
txdma,
|
||||
rxdma,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// 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(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd, // TODO: remove
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(mosi);
|
||||
mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down);
|
||||
mosi.set_speed(crate::gpio::Speed::Medium);
|
||||
|
||||
Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, config)
|
||||
}
|
||||
|
||||
#[cfg(stm32wl)]
|
||||
/// Useful for on chip peripherals like SUBGHZ which are hardwired.
|
||||
pub fn new_subghz(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
) -> Self {
|
||||
// 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 freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
|
||||
let mut config = Config::default();
|
||||
config.mode = MODE_0;
|
||||
config.bit_order = BitOrder::MsbFirst;
|
||||
config.frequency = freq;
|
||||
Self::new_inner(peri, None, None, None, txdma, rxdma, config)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new_internal(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(peri, None, None, None, txdma, rxdma, config)
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
|
||||
fn new_inner(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
rxdma: impl Peripheral<P = Rx> + 'd,
|
||||
txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
||||
rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(peri, txdma, rxdma);
|
||||
into_ref!(peri);
|
||||
|
||||
let pclk = T::frequency();
|
||||
let freq = config.frequency;
|
||||
@ -336,6 +212,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
txdma,
|
||||
rxdma,
|
||||
current_word_size: <u8 as SealedWord>::CONFIG,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,169 +339,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
self.current_word_size = word_size;
|
||||
}
|
||||
|
||||
/// SPI write, using DMA.
|
||||
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
{
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
let tx_request = self.txdma.request();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) };
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
tx_f.await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// SPI read, using DMA.
|
||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
Rx: RxDma<T>,
|
||||
{
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::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);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
|
||||
let clock_byte_count = data.len();
|
||||
|
||||
let rx_request = self.rxdma.request();
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_f = unsafe { Transfer::new_read(&mut self.rxdma, rx_request, rx_src, data, Default::default()) };
|
||||
|
||||
let tx_request = self.txdma.request();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let clock_byte = 0x00u8;
|
||||
let tx_f = unsafe {
|
||||
Transfer::new_write_repeated(
|
||||
&mut self.txdma,
|
||||
tx_request,
|
||||
&clock_byte,
|
||||
clock_byte_count,
|
||||
tx_dst,
|
||||
Default::default(),
|
||||
)
|
||||
};
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
Rx: RxDma<T>,
|
||||
{
|
||||
let (_, rx_len) = slice_ptr_parts(read);
|
||||
let (_, tx_len) = slice_ptr_parts(write);
|
||||
assert_eq!(rx_len, tx_len);
|
||||
if rx_len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::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);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
|
||||
let rx_request = self.rxdma.request();
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_f = unsafe { Transfer::new_read_raw(&mut self.rxdma, rx_request, rx_src, read, Default::default()) };
|
||||
|
||||
let tx_request = self.txdma.request();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) };
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Bidirectional transfer, using DMA.
|
||||
///
|
||||
/// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
|
||||
///
|
||||
/// 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 async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
Rx: RxDma<T>,
|
||||
{
|
||||
self.transfer_inner(read, write).await
|
||||
}
|
||||
|
||||
/// In-place bidirectional transfer, using DMA.
|
||||
///
|
||||
/// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
|
||||
pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDma<T>,
|
||||
Rx: RxDma<T>,
|
||||
{
|
||||
self.transfer_inner(data, data).await
|
||||
}
|
||||
|
||||
/// Blocking write.
|
||||
pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
|
||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||
@ -682,7 +396,338 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance> Spi<'d, T, Blocking> {
|
||||
/// Create a new blocking SPI driver.
|
||||
pub fn new_blocking(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||
None,
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
||||
pub fn new_blocking_rxonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
None,
|
||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||
None,
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
||||
pub fn new_blocking_txonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// 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(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
None,
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Spi<'d, T, Async> {
|
||||
/// Create a new SPI driver.
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||
new_dma!(txdma),
|
||||
new_dma!(rxdma),
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
||||
pub fn new_rxonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
|
||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
None,
|
||||
new_pin!(miso, AFType::Input, Speed::VeryHigh),
|
||||
None,
|
||||
new_dma!(rxdma),
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
||||
pub fn new_txonly(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
None,
|
||||
new_dma!(txdma),
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
/// 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(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
None,
|
||||
new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
|
||||
None,
|
||||
new_dma!(txdma),
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(stm32wl)]
|
||||
/// Useful for on chip peripherals like SUBGHZ which are hardwired.
|
||||
pub fn new_subghz(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
) -> Self {
|
||||
// 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 freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
|
||||
let mut config = Config::default();
|
||||
config.mode = MODE_0;
|
||||
config.bit_order = BitOrder::MsbFirst;
|
||||
config.frequency = freq;
|
||||
|
||||
Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new_internal(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config)
|
||||
}
|
||||
|
||||
/// SPI write, using DMA.
|
||||
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> {
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_f = unsafe { Transfer::new_write(txdma, *tx_request, data, tx_dst, Default::default()) };
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
tx_f.await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// SPI read, using DMA.
|
||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::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);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
|
||||
let clock_byte_count = data.len();
|
||||
|
||||
let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_f = unsafe { Transfer::new_read(rxdma, *rx_request, rx_src, data, Default::default()) };
|
||||
|
||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let clock_byte = 0x00u8;
|
||||
let tx_f = unsafe {
|
||||
Transfer::new_write_repeated(
|
||||
txdma,
|
||||
*tx_request,
|
||||
&clock_byte,
|
||||
clock_byte_count,
|
||||
tx_dst,
|
||||
Default::default(),
|
||||
)
|
||||
};
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
|
||||
let (_, rx_len) = slice_ptr_parts(read);
|
||||
let (_, tx_len) = slice_ptr_parts(write);
|
||||
assert_eq!(rx_len, tx_len);
|
||||
if rx_len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
T::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);
|
||||
|
||||
set_rxdmaen(T::REGS, true);
|
||||
|
||||
let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
|
||||
let rx_src = T::REGS.rx_ptr();
|
||||
let rx_f = unsafe { Transfer::new_read_raw(rxdma, *rx_request, rx_src, read, Default::default()) };
|
||||
|
||||
let (txdma, tx_request) = self.txdma.as_mut().unwrap();
|
||||
let tx_dst = T::REGS.tx_ptr();
|
||||
let tx_f = unsafe { Transfer::new_write_raw(txdma, *tx_request, write, tx_dst, Default::default()) };
|
||||
|
||||
set_txdmaen(T::REGS, true);
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
T::REGS.cr1().modify(|w| {
|
||||
w.set_cstart(true);
|
||||
});
|
||||
|
||||
join(tx_f, rx_f).await;
|
||||
|
||||
finish_dma(T::REGS);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Bidirectional transfer, using DMA.
|
||||
///
|
||||
/// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
|
||||
///
|
||||
/// 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 async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
|
||||
self.transfer_inner(read, write).await
|
||||
}
|
||||
|
||||
/// In-place bidirectional transfer, using DMA.
|
||||
///
|
||||
/// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
|
||||
pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
|
||||
self.transfer_inner(data, data).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: PeriMode> Drop for Spi<'d, T, 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());
|
||||
@ -900,7 +945,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, Tx, Rx> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, T, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
|
||||
@ -908,7 +953,7 @@ macro_rules! impl_blocking {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, T, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
|
||||
@ -922,11 +967,11 @@ macro_rules! impl_blocking {
|
||||
impl_blocking!(u8);
|
||||
impl_blocking!(u16);
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> embedded_hal_1::spi::ErrorType for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, T, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, M> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -959,7 +1004,7 @@ impl embedded_hal_1::spi::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Async> {
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -1094,7 +1139,7 @@ foreach_peripheral!(
|
||||
};
|
||||
);
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> {
|
||||
impl<'d, T: Instance, M: PeriMode> SetConfig for Spi<'d, T, M> {
|
||||
type Config = Config;
|
||||
type ConfigError = ();
|
||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
|
||||
|
@ -69,3 +69,26 @@ macro_rules! dma_trait_impl {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! new_dma {
|
||||
($name:ident) => {{
|
||||
let dma = $name.into_ref();
|
||||
let req = dma.request();
|
||||
Some((dma.map_into(), req))
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! new_pin {
|
||||
($name:ident, $aftype:expr, $speed:expr) => {{
|
||||
let pin = $name.into_ref();
|
||||
pin.set_as_af(pin.af_num(), $aftype);
|
||||
pin.set_speed($speed);
|
||||
Some(pin.map_into())
|
||||
}};
|
||||
($name:ident, $aftype:expr, $speed:expr, $pull:expr) => {{
|
||||
let pin = $name.into_ref();
|
||||
pin.set_as_af_pull(pin.af_num(), $aftype, $pull);
|
||||
pin.set_speed($speed);
|
||||
Some(pin.map_into())
|
||||
}};
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
@ -18,7 +17,7 @@ fn main() -> ! {
|
||||
let mut spi_config = Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
|
||||
let mut spi = Spi::new_blocking(p.SPI3, p.PC10, p.PC12, p.PC11, spi_config);
|
||||
|
||||
let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
|
||||
|
||||
|
@ -13,8 +13,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embassy_stm32::spi;
|
||||
use embassy_stm32::time::khz;
|
||||
use embassy_stm32::{dma, spi};
|
||||
use embassy_time::{Duration, Ticker, Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
@ -78,7 +78,7 @@ async fn main(_spawner: embassy_executor::Spawner) {
|
||||
spi_config.frequency = khz(12_800);
|
||||
|
||||
// Since we only output waveform, then the Rx and Sck and RxDma it is not considered
|
||||
let mut ws2812_spi = spi::Spi::new_txonly_nosck(dp.SPI1, dp.PB5, dp.DMA2_CH3, dma::NoDma, spi_config);
|
||||
let mut ws2812_spi = spi::Spi::new_txonly_nosck(dp.SPI1, dp.PB5, dp.DMA2_CH3, spi_config);
|
||||
|
||||
// flip color at 2 Hz
|
||||
let mut ticker = Ticker::every(Duration::from_millis(500));
|
||||
|
@ -4,7 +4,6 @@
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::dma::word::U5;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_time::Timer;
|
||||
@ -77,7 +76,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let mut config = Config::default();
|
||||
config.frequency = Hertz(4_000_000);
|
||||
let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, NoDma, config);
|
||||
let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, config);
|
||||
|
||||
let mut neopixels = Ws2812::new();
|
||||
|
||||
|
@ -7,7 +7,7 @@ use core::str::from_utf8;
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::mode::Blocking;
|
||||
use embassy_stm32::peripherals::SPI3;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{spi, Config};
|
||||
@ -16,7 +16,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, NoDma, NoDma>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
@ -62,7 +62,7 @@ fn main() -> ! {
|
||||
let mut spi_config = spi::Config::default();
|
||||
spi_config.frequency = mhz(1);
|
||||
|
||||
let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, NoDma, NoDma, spi_config);
|
||||
let spi = spi::Spi::new_blocking(p.SPI3, p.PB3, p.PB5, p.PB4, spi_config);
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
|
||||
|
@ -7,15 +7,15 @@ use core::str::from_utf8;
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::peripherals::{DMA1_CH3, DMA1_CH4, SPI3};
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{spi, Config};
|
||||
use embassy_stm32::{peripherals, 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, SPI3, DMA1_CH3, DMA1_CH4>) {
|
||||
async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
let mut read = [0; 128];
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
@ -17,7 +16,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut spi_config = Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let mut spi = Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, NoDma, NoDma, spi_config);
|
||||
let mut spi = Spi::new_blocking(p.SPI1, p.PB3, p.PA7, p.PA6, spi_config);
|
||||
|
||||
let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh);
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
@ -17,7 +16,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut spi_config = Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let mut spi = Spi::new(p.SPI1, p.PA5, p.PA7, p.PA6, NoDma, NoDma, spi_config);
|
||||
let mut spi = Spi::new_blocking(p.SPI1, p.PA5, p.PA7, p.PA6, spi_config);
|
||||
|
||||
let mut cs = Output::new(p.PA4, Level::High, Speed::VeryHigh);
|
||||
|
||||
|
@ -23,18 +23,23 @@ use embassy_futures::select::{select, Either};
|
||||
use embassy_futures::yield_now;
|
||||
use embassy_net::tcp::TcpSocket;
|
||||
use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4};
|
||||
use embassy_net_adin1110::{Device, Runner, ADIN1110};
|
||||
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
|
||||
use embassy_stm32::i2c::{self, Config as I2C_Config, I2c};
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::rng::{self, Rng};
|
||||
use embassy_stm32::spi::{Config as SPI_Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::{bind_interrupts, exti, pac, peripherals};
|
||||
use embassy_time::{Delay, Duration, Ticker, Timer};
|
||||
use embedded_hal_async::i2c::I2c as I2cBus;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_io::Write as bWrite;
|
||||
use embedded_io_async::Write;
|
||||
use hal::gpio::{Input, Level, Output, Speed};
|
||||
use hal::i2c::{self, I2c};
|
||||
use hal::rng::{self, Rng};
|
||||
use hal::{bind_interrupts, exti, pac, peripherals};
|
||||
use heapless::Vec;
|
||||
use panic_probe as _;
|
||||
use rand::RngCore;
|
||||
use static_cell::StaticCell;
|
||||
use {embassy_stm32 as hal, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>;
|
||||
@ -42,13 +47,6 @@ bind_interrupts!(struct Irqs {
|
||||
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||
});
|
||||
|
||||
use embassy_net_adin1110::{Device, Runner, ADIN1110};
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use hal::gpio::Pull;
|
||||
use hal::i2c::Config as I2C_Config;
|
||||
use hal::spi::{Config as SPI_Config, Spi};
|
||||
use hal::time::Hertz;
|
||||
|
||||
// Basic settings
|
||||
// MAC-address used by the adin1110
|
||||
const MAC: [u8; 6] = [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff];
|
||||
@ -57,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, peripherals::DMA1_CH1, peripherals::DMA1_CH2>;
|
||||
pub type SpeSpi = Spi<'static, peripherals::SPI2, Async>;
|
||||
pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
|
||||
pub type SpeInt = exti::ExtiInput<'static>;
|
||||
pub type SpeRst = Output<'static>;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
@ -17,7 +16,7 @@ fn main() -> ! {
|
||||
let mut spi_config = Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
|
||||
let mut spi = Spi::new_blocking(p.SPI3, p.PC10, p.PC12, p.PC11, spi_config);
|
||||
|
||||
let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
use defmt::*;
|
||||
use embassy_embedded_hal::adapter::BlockingAsync;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
|
||||
use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
@ -19,7 +18,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut spi_config = Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
|
||||
let spi = Spi::new_blocking(p.SPI3, p.PC10, p.PC12, p.PC11, spi_config);
|
||||
|
||||
let mut spi = BlockingAsync::new(spi);
|
||||
|
||||
|
@ -6,7 +6,6 @@ mod common;
|
||||
use common::*;
|
||||
use defmt::assert_eq;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::dma::NoDma;
|
||||
use embassy_stm32::spi::{self, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
|
||||
@ -23,11 +22,11 @@ async fn main(_spawner: Spawner) {
|
||||
let mut spi_config = spi::Config::default();
|
||||
spi_config.frequency = Hertz(1_000_000);
|
||||
|
||||
let mut spi = Spi::new(
|
||||
let mut spi = Spi::new_blocking(
|
||||
spi, sck, // Arduino D13
|
||||
mosi, // Arduino D11
|
||||
miso, // Arduino D12
|
||||
NoDma, NoDma, spi_config,
|
||||
spi_config,
|
||||
);
|
||||
|
||||
let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE];
|
||||
|
Loading…
Reference in New Issue
Block a user