diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index 554981ce7..302b7a2a1 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -303,28 +303,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spi<'d, T, NoDm let regs = T::regs(); for word in words.iter() { - while unsafe { !regs.sr().read().txe() } { - // spin - } - unsafe { - let dr = regs.dr().ptr() as *mut u8; - ptr::write_volatile(dr, *word); - } - loop { - 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); - } - if !sr.txe() { - // loop waiting for TXE - } - } + write_word(regs, *word)?; + let _: u8 = read_word(regs)?; } Ok(()) @@ -339,33 +319,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, N let regs = T::regs(); for word in words.iter_mut() { - while unsafe { !regs.sr().read().txe() } { - // spin - } - unsafe { - let dr = regs.dr().ptr() as *mut u8; - ptr::write_volatile(dr, *word); - } - - while unsafe { !regs.sr().read().rxne() } { - // spin waiting for inbound to shift in. - } - - unsafe { - let dr = regs.dr().ptr() as *const u8; - *word = ptr::read_volatile(dr); - } - - 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); - } + write_word(regs, *word)?; + *word = read_word(regs)?; } Ok(words) @@ -380,28 +335,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spi<'d, T, NoD let regs = T::regs(); for word in words.iter() { - while unsafe { !regs.sr().read().txe() } { - // spin - } - unsafe { - let dr = regs.dr().ptr() as *mut u16; - ptr::write_volatile(dr, *word); - } - loop { - 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); - } - if !sr.txe() { - // loop waiting for TXE - } - } + write_word(regs, *word)?; + let _: u8 = read_word(regs)?; } Ok(()) @@ -416,31 +351,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, let regs = T::regs(); for word in words.iter_mut() { - while unsafe { !regs.sr().read().txe() } { - // spin - } - unsafe { - let dr = regs.dr().ptr() as *mut u16; - ptr::write_volatile(dr, *word); - } - while unsafe { !regs.sr().read().rxne() } { - // spin waiting for inbound to shift in. - } - unsafe { - let dr = regs.dr().ptr() as *const u16; - *word = ptr::read_volatile(dr); - } - - 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); - } + write_word(regs, *word)?; + *word = read_word(regs)?; } Ok(words) @@ -485,3 +397,50 @@ impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::FullDupl self.read_write_dma_u8(read, write) } } + +trait Word {} + +impl Word for u8 {} +impl Word for u16 {} + +fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { + loop { + let sr = unsafe { regs.sr().read() }; + if sr.ovr() { + return Err(Error::Overrun); + } else if sr.fre() { + return Err(Error::Framing); + } else if sr.modf() { + return Err(Error::ModeFault); + } else if sr.crcerr() { + return Err(Error::Crc); + } else if sr.txe() { + unsafe { + let dr = regs.dr().ptr() as *mut W; + ptr::write_volatile(dr, word); + } + return Ok(()); + } + } +} + +/// Read a single word blocking. Assumes word size have already been set. +fn read_word(regs: &'static crate::pac::spi::Spi) -> Result { + loop { + let sr = unsafe { regs.sr().read() }; + if sr.ovr() { + return Err(Error::Overrun); + } else if sr.modf() { + return Err(Error::ModeFault); + } else if sr.fre() { + return Err(Error::Framing); + } else if sr.crcerr() { + return Err(Error::Crc); + } else if sr.rxne() { + unsafe { + let dr = regs.dr().ptr() as *const W; + return Ok(ptr::read_volatile(dr)); + } + } + } +}