mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
stm32/spi: fix hang/corruption of word sizes other than 8bit.
This commit is contained in:
parent
59dcffbc60
commit
68b783aedf
@ -311,51 +311,29 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set SPI word size. Disables SPI if needed, you have to enable it back yourself.
|
||||
fn set_word_size(&mut self, word_size: word_impl::Config) {
|
||||
if self.current_word_size == word_size {
|
||||
return;
|
||||
}
|
||||
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
#[cfg(any(spi_v1, spi_f1))]
|
||||
{
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_spe(false);
|
||||
reg.set_dff(word_size)
|
||||
});
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_spe(true);
|
||||
});
|
||||
}
|
||||
self.info.regs.cr1().modify(|reg| {
|
||||
reg.set_dff(word_size);
|
||||
});
|
||||
#[cfg(spi_v2)]
|
||||
{
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_frxth(word_size.1);
|
||||
w.set_ds(word_size.0);
|
||||
});
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(true);
|
||||
});
|
||||
}
|
||||
self.info.regs.cr2().modify(|w| {
|
||||
w.set_frxth(word_size.1);
|
||||
w.set_ds(word_size.0);
|
||||
});
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
{
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_csusp(true);
|
||||
});
|
||||
while self.info.regs.sr().read().eot() {}
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
self.info.regs.cfg1().modify(|w| {
|
||||
w.set_dsize(word_size);
|
||||
});
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_csusp(false);
|
||||
w.set_spe(true);
|
||||
});
|
||||
}
|
||||
self.info.regs.cfg1().modify(|w| {
|
||||
w.set_dsize(word_size);
|
||||
});
|
||||
|
||||
self.current_word_size = word_size;
|
||||
}
|
||||
@ -365,9 +343,9 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
// needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...?
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(false));
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.info.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter() {
|
||||
// this cannot use `transfer_word` because on SPIv2 and higher,
|
||||
// the SPI RX state machine hangs if no physical pin is connected to the SCK AF.
|
||||
@ -402,9 +380,9 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
// needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...?
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(false));
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.info.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(self.info.regs, W::default())?;
|
||||
}
|
||||
@ -418,9 +396,9 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
// needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...?
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(false));
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.info.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(self.info.regs, *word)?;
|
||||
}
|
||||
@ -437,9 +415,9 @@ impl<'d, M: PeriMode> Spi<'d, M> {
|
||||
// needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...?
|
||||
#[cfg(any(spi_v3, spi_v4, spi_v5))]
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(false));
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| w.set_spe(true));
|
||||
flush_rx_fifo(self.info.regs);
|
||||
self.set_word_size(W::CONFIG);
|
||||
let len = read.len().max(write.len());
|
||||
for i in 0..len {
|
||||
let wb = write.get(i).copied().unwrap_or_default();
|
||||
@ -648,10 +626,10 @@ impl<'d> Spi<'d, Async> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
self.set_word_size(W::CONFIG);
|
||||
|
||||
let tx_dst = self.info.regs.tx_ptr();
|
||||
let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
|
||||
@ -685,6 +663,8 @@ impl<'d> Spi<'d, Async> {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
|
||||
let comm = regs.cfg2().modify(|w| {
|
||||
let prev = w.comm();
|
||||
w.set_comm(vals::Comm::RECEIVER);
|
||||
@ -707,7 +687,6 @@ impl<'d> Spi<'d, Async> {
|
||||
let rx_src = regs.rx_ptr();
|
||||
|
||||
for mut chunk in data.chunks_mut(u16::max_value().into()) {
|
||||
self.set_word_size(W::CONFIG);
|
||||
set_rxdmaen(regs, true);
|
||||
|
||||
let tsize = chunk.len();
|
||||
@ -765,12 +744,12 @@ impl<'d> Spi<'d, Async> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
|
||||
// SPIv3 clears rxfifo on SPE=0
|
||||
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
|
||||
flush_rx_fifo(self.info.regs);
|
||||
@ -813,11 +792,12 @@ impl<'d> Spi<'d, Async> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
self.info.regs.cr1().modify(|w| {
|
||||
w.set_spe(false);
|
||||
});
|
||||
|
||||
self.set_word_size(W::CONFIG);
|
||||
|
||||
// SPIv3 clears rxfifo on SPE=0
|
||||
#[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
|
||||
flush_rx_fifo(self.info.regs);
|
||||
|
Loading…
Reference in New Issue
Block a user