stm32/spi: add v4/v5 support (for H5).

This commit is contained in:
Dario Nieuwenhuis 2023-04-10 15:11:23 +02:00
parent 44b7fe45e2
commit 4ef8e008e8

View file

@ -258,7 +258,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
w.set_spe(true); w.set_spe(true);
}); });
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
unsafe { unsafe {
T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
T::REGS.cfg2().modify(|w| { T::REGS.cfg2().modify(|w| {
@ -317,7 +317,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
}); });
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
unsafe { unsafe {
T::REGS.cfg2().modify(|w| { T::REGS.cfg2().modify(|w| {
w.set_cpha(cpha); w.set_cpha(cpha);
@ -330,7 +330,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
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 = unsafe { T::REGS.cr1().read() }; let cfg = unsafe { T::REGS.cr1().read() };
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
let cfg = unsafe { T::REGS.cfg2().read() }; let cfg = unsafe { T::REGS.cfg2().read() };
let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
Polarity::IdleLow Polarity::IdleLow
@ -383,7 +383,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
w.set_spe(true); w.set_spe(true);
}); });
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
unsafe { unsafe {
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_csusp(true); w.set_csusp(true);
@ -429,7 +429,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
@ -459,7 +459,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
} }
// SPIv3 clears rxfifo on SPE=0 // SPIv3 clears rxfifo on SPE=0
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
flush_rx_fifo(T::REGS); flush_rx_fifo(T::REGS);
set_rxdmaen(T::REGS, true); set_rxdmaen(T::REGS, true);
@ -481,7 +481,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
@ -514,7 +514,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
} }
// SPIv3 clears rxfifo on SPE=0 // SPIv3 clears rxfifo on SPE=0
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
flush_rx_fifo(T::REGS); flush_rx_fifo(T::REGS);
set_rxdmaen(T::REGS, true); set_rxdmaen(T::REGS, true);
@ -534,7 +534,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_spe(true); w.set_spe(true);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
T::REGS.cr1().modify(|w| { T::REGS.cr1().modify(|w| {
w.set_cstart(true); w.set_cstart(true);
}); });
@ -619,9 +619,9 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
} }
} }
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
use vals::Br; use vals::Br;
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
use vals::Mbr as Br; use vals::Mbr as Br;
fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br { fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
@ -647,17 +647,17 @@ trait RegsExt {
impl RegsExt for Regs { impl RegsExt for Regs {
fn tx_ptr<W>(&self) -> *mut W { fn tx_ptr<W>(&self) -> *mut W {
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
let dr = self.dr(); let dr = self.dr();
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
let dr = self.txdr(); let dr = self.txdr();
dr.ptr() as *mut W dr.ptr() as *mut W
} }
fn rx_ptr<W>(&self) -> *mut W { fn rx_ptr<W>(&self) -> *mut W {
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
let dr = self.dr(); let dr = self.dr();
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
let dr = self.rxdr(); let dr = self.rxdr();
dr.ptr() as *mut W dr.ptr() as *mut W
} }
@ -667,22 +667,22 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
if sr.ovr() { if sr.ovr() {
return Err(Error::Overrun); return Err(Error::Overrun);
} }
#[cfg(not(any(spi_f1, spi_v3, spi_v4)))] #[cfg(not(any(spi_f1, spi_v3, spi_v4, spi_v5)))]
if sr.fre() { if sr.fre() {
return Err(Error::Framing); return Err(Error::Framing);
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
if sr.tifre() { if sr.tifre() {
return Err(Error::Framing); return Err(Error::Framing);
} }
if sr.modf() { if sr.modf() {
return Err(Error::ModeFault); return Err(Error::ModeFault);
} }
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
if sr.crcerr() { if sr.crcerr() {
return Err(Error::Crc); return Err(Error::Crc);
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
if sr.crce() { if sr.crce() {
return Err(Error::Crc); return Err(Error::Crc);
} }
@ -696,11 +696,11 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> {
check_error_flags(sr)?; check_error_flags(sr)?;
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
if sr.txe() { if sr.txe() {
return Ok(()); return Ok(());
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
if sr.txp() { if sr.txp() {
return Ok(()); return Ok(());
} }
@ -713,11 +713,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
check_error_flags(sr)?; check_error_flags(sr)?;
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
if sr.rxne() { if sr.rxne() {
return Ok(()); return Ok(());
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
if sr.rxp() { if sr.rxp() {
return Ok(()); return Ok(());
} }
@ -726,11 +726,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
fn flush_rx_fifo(regs: Regs) { fn flush_rx_fifo(regs: Regs) {
unsafe { unsafe {
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
while regs.sr().read().rxne() { while regs.sr().read().rxne() {
let _ = regs.dr().read(); let _ = regs.dr().read();
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
while regs.sr().read().rxp() { while regs.sr().read().rxp() {
let _ = regs.rxdr().read(); let _ = regs.rxdr().read();
} }
@ -739,11 +739,11 @@ fn flush_rx_fifo(regs: Regs) {
fn set_txdmaen(regs: Regs, val: bool) { fn set_txdmaen(regs: Regs, val: bool) {
unsafe { unsafe {
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
regs.cr2().modify(|reg| { regs.cr2().modify(|reg| {
reg.set_txdmaen(val); reg.set_txdmaen(val);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
regs.cfg1().modify(|reg| { regs.cfg1().modify(|reg| {
reg.set_txdmaen(val); reg.set_txdmaen(val);
}); });
@ -752,11 +752,11 @@ fn set_txdmaen(regs: Regs, val: bool) {
fn set_rxdmaen(regs: Regs, val: bool) { fn set_rxdmaen(regs: Regs, val: bool) {
unsafe { unsafe {
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
regs.cr2().modify(|reg| { regs.cr2().modify(|reg| {
reg.set_rxdmaen(val); reg.set_rxdmaen(val);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
regs.cfg1().modify(|reg| { regs.cfg1().modify(|reg| {
reg.set_rxdmaen(val); reg.set_rxdmaen(val);
}); });
@ -768,9 +768,9 @@ fn finish_dma(regs: Regs) {
#[cfg(spi_v2)] #[cfg(spi_v2)]
while regs.sr().read().ftlvl() > 0 {} while regs.sr().read().ftlvl() > 0 {}
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
while !regs.sr().read().txc() {} while !regs.sr().read().txc() {}
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
while regs.sr().read().bsy() {} while regs.sr().read().bsy() {}
// Disable the spi peripheral // Disable the spi peripheral
@ -780,12 +780,12 @@ fn finish_dma(regs: Regs) {
// The peripheral automatically disables the DMA stream on completion without error, // The peripheral automatically disables the DMA stream on completion without error,
// but it does not clear the RXDMAEN/TXDMAEN flag in CR2. // but it does not clear the RXDMAEN/TXDMAEN flag in CR2.
#[cfg(not(any(spi_v3, spi_v4)))] #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
regs.cr2().modify(|reg| { regs.cr2().modify(|reg| {
reg.set_txdmaen(false); reg.set_txdmaen(false);
reg.set_rxdmaen(false); reg.set_rxdmaen(false);
}); });
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
regs.cfg1().modify(|reg| { regs.cfg1().modify(|reg| {
reg.set_txdmaen(false); reg.set_txdmaen(false);
reg.set_rxdmaen(false); reg.set_rxdmaen(false);
@ -799,7 +799,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
unsafe { unsafe {
ptr::write_volatile(regs.tx_ptr(), tx_word); ptr::write_volatile(regs.tx_ptr(), tx_word);
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
regs.cr1().modify(|reg| reg.set_cstart(true)); regs.cr1().modify(|reg| reg.set_cstart(true));
} }
@ -970,7 +970,7 @@ pub(crate) mod sealed {
} }
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
pub fn dsize(&self) -> u8 { pub fn dsize(&self) -> u8 {
match self { match self {
WordSize::EightBit => 0b0111, WordSize::EightBit => 0b0111,
@ -978,7 +978,7 @@ pub(crate) mod sealed {
} }
} }
#[cfg(any(spi_v3, spi_v4))] #[cfg(any(spi_v3, spi_v4, spi_v5))]
pub fn _frxth(&self) -> vals::Fthlv { pub fn _frxth(&self) -> vals::Fthlv {
match self { match self {
WordSize::EightBit => vals::Fthlv::ONEFRAME, WordSize::EightBit => vals::Fthlv::ONEFRAME,