This commit is contained in:
Henrik Alsér 2022-08-30 00:30:47 +02:00 committed by Henrik Alsér
parent e7d4bf258a
commit 07c64d902e
3 changed files with 112 additions and 7 deletions

View File

@ -3,6 +3,7 @@ use core::marker::PhantomData;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
pub use embedded_hal_02::spi::{Phase, Polarity}; pub use embedded_hal_02::spi::{Phase, Polarity};
use futures::future::join;
use crate::dma::{AnyChannel, Channel}; use crate::dma::{AnyChannel, Channel};
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;
@ -64,10 +65,8 @@ fn calc_prescs(freq: u32) -> (u8, u8) {
} }
impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
pub fn new( pub fn new_blocking(
inner: impl Peripheral<P = T> + 'd, inner: impl Peripheral<P = T> + 'd,
tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
@ -76,8 +75,8 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
into_ref!(clk, mosi, miso); into_ref!(clk, mosi, miso);
Self::new_inner( Self::new_inner(
inner, inner,
tx_dma, None,
rx_dma, None,
Some(clk.map_into()), Some(clk.map_into()),
Some(mosi.map_into()), Some(mosi.map_into()),
Some(miso.map_into()), Some(miso.map_into()),
@ -262,6 +261,81 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
} }
} }
impl<'d, T: Instance> Spi<'d, T, Async> {
pub fn new(
inner: impl Peripheral<P = T> + 'd,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
config: Config,
) -> Self {
into_ref!(tx_dma, rx_dma, clk, mosi, miso);
Self::new_inner(
inner,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
Some(clk.map_into()),
Some(mosi.map_into()),
Some(miso.map_into()),
None,
config,
)
}
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let ch = self.tx_dma.as_mut().unwrap();
let transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| {
reg.set_txdmae(true);
});
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
};
transfer.await;
Ok(())
}
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
let ch = self.rx_dma.as_mut().unwrap();
let transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| {
reg.set_rxdmae(true);
});
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ)
};
transfer.await;
Ok(())
}
pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> {
let tx_ch = self.tx_dma.as_mut().unwrap();
let tx_transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| {
reg.set_txdmae(true);
});
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::write(tx_ch, tx_buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
};
let rx_ch = self.rx_dma.as_mut().unwrap();
let rx_transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| {
reg.set_rxdmae(true);
});
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_buffer, T::RX_DREQ)
};
join(tx_transfer, rx_transfer).await;
Ok(())
}
}
mod sealed { mod sealed {
use super::*; use super::*;

View File

@ -4,7 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::spi::Spi; use embassy_rp::spi::{Blocking, Spi};
use embassy_rp::{gpio, spi}; use embassy_rp::{gpio, spi};
use gpio::{Level, Output}; use gpio::{Level, Output};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
// create SPI // create SPI
let mut config = spi::Config::default(); let mut config = spi::Config::default();
config.frequency = 2_000_000; config.frequency = 2_000_000;
let mut spi = Spi::new(p.SPI1, clk, mosi, miso, config); let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config);
// Configure CS // Configure CS
let mut cs = Output::new(touch_cs, Level::Low); let mut cs = Output::new(touch_cs, Level::Low);

View File

@ -0,0 +1,31 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::spi::{Async, Spi};
use embassy_rp::{gpio, spi};
use embassy_time::{Duration, Timer};
use gpio::{Level, Output};
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
info!("Hello World!");
let miso = p.PIN_12;
let mosi = p.PIN_11;
let clk = p.PIN_10;
let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default());
loop {
let tx_buf = [1_u8, 2, 3, 4, 5, 6];
let mut rx_buf = [0_u8; 6];
spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
info!("{:?}", rx_buf);
Timer::after(Duration::from_secs(1)).await;
}
}