Further improvement to SPIv2.

This commit is contained in:
Bob McWhirter 2021-05-12 14:18:42 -04:00
parent 36c16dbef8
commit 07db3ed7c1
2 changed files with 121 additions and 33 deletions

View File

@ -23,7 +23,7 @@ pub mod usart;
// This must go LAST so that it sees the `impl_foo!` macros // This must go LAST so that it sees the `impl_foo!` macros
mod pac; mod pac;
mod time; pub mod time;
pub use embassy_macros::interrupt; pub use embassy_macros::interrupt;
pub use pac::{interrupt, peripherals, Peripherals}; pub use pac::{interrupt, peripherals, Peripherals};

View File

@ -11,12 +11,48 @@ use crate::pac::gpio::vals::{Afr, Moder};
use crate::pac::spi; use crate::pac::spi;
use crate::pac::gpio::Gpio; use crate::pac::gpio::Gpio;
use crate::time::Hertz; use crate::time::Hertz;
//use crate::pac::spi; use term::terminfo::parm::Param::Words;
#[non_exhaustive]
pub struct Config {
pub mode: Mode,
pub byte_order: ByteOrder,
}
impl Default for Config {
fn default() -> Self {
Self {
mode: MODE_0,
byte_order: ByteOrder::MsbFirst,
}
}
}
// TODO move upwards in the tree // TODO move upwards in the tree
pub enum ByteOrder { pub enum ByteOrder {
LsbFirst, LsbFirst,
MsbFirst MsbFirst,
}
enum WordSize {
EightBit,
SixteenBit,
}
impl WordSize {
fn ds(&self) -> spi::vals::Ds {
match self {
WordSize::EightBit => spi::vals::Ds::EIGHTBIT,
WordSize::SixteenBit => spi::vals::Ds::SIXTEENBIT,
}
}
fn frxth(&self) -> spi::vals::Frxth {
match self {
WordSize::EightBit => spi::vals::Frxth::QUARTER,
WordSize::SixteenBit => spi::vals::Frxth::HALF,
}
}
} }
pub struct Spi<'d, T: Instance> { pub struct Spi<'d, T: Instance> {
@ -34,9 +70,8 @@ impl<'d, T: Instance> Spi<'d, T> {
sck: impl Unborrow<Target=impl Sck<T>>, sck: impl Unborrow<Target=impl Sck<T>>,
mosi: impl Unborrow<Target=impl Mosi<T>>, mosi: impl Unborrow<Target=impl Mosi<T>>,
miso: impl Unborrow<Target=impl Miso<T>>, miso: impl Unborrow<Target=impl Miso<T>>,
mode: Mode,
byte_order: ByteOrder,
freq: F, freq: F,
config: Config,
) -> Self ) -> Self
where where
F: Into<Hertz> F: Into<Hertz>
@ -54,16 +89,9 @@ impl<'d, T: Instance> Spi<'d, T> {
let mosi = mosi.degrade(); let mosi = mosi.degrade();
let miso = miso.degrade(); let miso = miso.degrade();
// FRXTH: RXNE event is generated if the FIFO level is greater than or equal to
// 8-bit
// DS: 8-bit data size
// SSOE: Slave Select output disabled
unsafe { unsafe {
T::regs().cr2() T::regs().cr2()
.write(|w| { .write(|w| {
// 8-bit transfers
w.set_ds( spi::vals::Ds(0b0111));
w.set_frxth( spi::vals::Frxth::QUARTER);
w.set_ssoe(false); w.set_ssoe(false);
}); });
} }
@ -73,12 +101,12 @@ impl<'d, T: Instance> Spi<'d, T> {
unsafe { unsafe {
T::regs().cr1().write(|w| { T::regs().cr1().write(|w| {
w.set_cpha( w.set_cpha(
match mode.phase == Phase::CaptureOnSecondTransition { match config.mode.phase == Phase::CaptureOnSecondTransition {
true => spi::vals::Cpha::SECONDEDGE, true => spi::vals::Cpha::SECONDEDGE,
false => spi::vals::Cpha::FIRSTEDGE, false => spi::vals::Cpha::FIRSTEDGE,
} }
); );
w.set_cpol(match mode.polarity == Polarity::IdleHigh { w.set_cpol(match config.mode.polarity == Polarity::IdleHigh {
true => spi::vals::Cpol::IDLEHIGH, true => spi::vals::Cpol::IDLEHIGH,
false => spi::vals::Cpol::IDLELOW, false => spi::vals::Cpol::IDLELOW,
}); });
@ -87,7 +115,7 @@ impl<'d, T: Instance> Spi<'d, T> {
w.set_br(spi::vals::Br(br)); w.set_br(spi::vals::Br(br));
w.set_spe(true); w.set_spe(true);
w.set_lsbfirst( w.set_lsbfirst(
match byte_order { match config.byte_order {
ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST, ByteOrder::LsbFirst => spi::vals::Lsbfirst::LSBFIRST,
ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST, ByteOrder::MsbFirst => spi::vals::Lsbfirst::MSBFIRST,
} }
@ -97,8 +125,7 @@ impl<'d, T: Instance> Spi<'d, T> {
w.set_crcen(false); w.set_crcen(false);
w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL);
}); });
T::regs().cr2().write(|w| { T::regs().cr2().write(|w| {})
})
} }
Self { Self {
@ -134,6 +161,16 @@ impl<'d, T: Instance> Spi<'d, T> {
_ => 0b111, _ => 0b111,
} }
} }
fn set_word_size(word_size: WordSize) {
unsafe {
T::regs().cr2()
.write(|w| {
w.set_ds(word_size.ds());
w.set_frxth(word_size.frxth());
});
}
}
} }
impl<'d, T: Instance> Drop for Spi<'d, T> { impl<'d, T: Instance> Drop for Spi<'d, T> {
@ -156,6 +193,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> {
type Error = Error; type Error = Error;
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
Self::set_word_size(WordSize::EightBit);
let regs = T::regs(); let regs = T::regs();
for word in words.iter() { for word in words.iter() {
@ -190,6 +228,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
type Error = Error; type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
Self::set_word_size(WordSize::EightBit);
let regs = T::regs(); let regs = T::regs();
for word in words.iter_mut() { for word in words.iter_mut() {
@ -203,6 +242,36 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
// spin waiting for inbound to shift in. // spin waiting for inbound to shift in.
} }
*word = unsafe { regs.dr().read().0 as u8 }; *word = unsafe { regs.dr().read().0 as u8 };
let sr = unsafe { regs.sr().read() };
if sr.fre() {
return Err(Error::Framing);
}
if sr.ovr() {
return Err(Error::Overrun);
}
if sr.crcerr() {
return Err(Error::Crc);
}
}
Ok(words)
}
}
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> {
type Error = Error;
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
Self::set_word_size(WordSize::SixteenBit);
let regs = T::regs();
for word in words.iter() {
while unsafe { !regs.sr().read().txe() } {
// spin
}
unsafe {
regs.dr().write(|reg| reg.0 = *word as u32);
}
loop { loop {
let sr = unsafe { regs.sr().read() }; let sr = unsafe { regs.sr().read() };
if sr.fre() { if sr.fre() {
@ -220,6 +289,40 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> {
} }
} }
Ok(())
}
}
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T> {
type Error = Error;
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
Self::set_word_size(WordSize::SixteenBit);
let regs = T::regs();
for word in words.iter_mut() {
while unsafe { !regs.sr().read().txe() } {
// spin
}
unsafe {
regs.dr().write(|reg| reg.0 = *word as u32);
}
while unsafe { !regs.sr().read().rxne() } {
// spin waiting for inbound to shift in.
}
*word = unsafe { regs.dr().read().0 as u16 };
let sr = unsafe { regs.sr().read() };
if sr.fre() {
return Err(Error::Framing);
}
if sr.ovr() {
return Err(Error::Overrun);
}
if sr.crcerr() {
return Err(Error::Crc);
}
}
Ok(words) Ok(words)
} }
} }
@ -229,21 +332,8 @@ pub(crate) mod sealed {
use super::*; use super::*;
use embassy::util::AtomicWaker; use embassy::util::AtomicWaker;
//pub struct State {
//pub end_waker: AtomicWaker,
//}
//impl State {
//pub const fn new() -> Self {
//Self {
//end_waker: AtomicWaker::new(),
//}
//}
//}
pub trait Instance { pub trait Instance {
fn regs() -> &'static spi::Spi; fn regs() -> &'static spi::Spi;
//fn state() -> &'static State;
} }
pub trait Sck<T: Instance>: Pin { pub trait Sck<T: Instance>: Pin {
@ -268,9 +358,7 @@ pub(crate) mod sealed {
} }
} }
pub trait Instance: sealed::Instance + 'static { pub trait Instance: sealed::Instance + 'static {}
//type Interrupt: Interrupt;
}
pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {} pub trait Sck<T: Instance>: sealed::Sck<T> + 'static {}