Skip to content

Commit 30fb190

Browse files
committed
rp2/machine_spi: Detect RX overrun when using DMA transfers.
Fixes bug where SPI can freeze if another DMA channel is tranferring to/from PSRAM. Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
1 parent 8fb848f commit 30fb190

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

ports/rp2/machine_spi.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
273273
bool use_dma = chan_rx >= 0 && chan_tx >= 0;
274274
// note src is guaranteed to be non-NULL
275275
bool write_only = dest == NULL;
276+
bool success = true;
276277

277278
if (use_dma) {
278279
uint8_t dev_null;
@@ -297,8 +298,16 @@ static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
297298
false);
298299

299300
dma_start_channel_mask((1u << chan_rx) | (1u << chan_tx));
300-
dma_channel_wait_for_finish_blocking(chan_rx);
301301
dma_channel_wait_for_finish_blocking(chan_tx);
302+
303+
// Fix for #18471. Wait for SPI to finish then check for RX overrun
304+
while (spi_is_busy(self->spi_inst) || spi_is_readable(self->spi_inst)) {
305+
}
306+
if (spi_get_const_hw(self->spi_inst)->ris & SPI_SSPRIS_RORRIS_BITS) {
307+
// RX overrun occurred, RX DMA channel needs to be manually aborted
308+
success = false;
309+
dma_channel_abort(chan_rx);
310+
}
302311
}
303312

304313
// If we have claimed only one channel successfully, we should release immediately
@@ -317,6 +326,11 @@ static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
317326
spi_write_read_blocking(self->spi_inst, src, dest, len);
318327
}
319328
}
329+
330+
// Raise OSError if something went wrong
331+
if (!success) {
332+
mp_raise_OSError(MP_EIO);
333+
}
320334
}
321335

322336
// Buffer protocol implementation for SPI.

0 commit comments

Comments
 (0)