Skip to content

Commit 54171d2

Browse files
committed
rp2/machine_spi: Don't use DMA channels for SPI transfers.
Fixes bug where SPI can freeze if another DMA channel is tranferring to/from PSRAM. Signed-off-by: Dryw Wade <[email protected]>
1 parent 78ff170 commit 54171d2

File tree

1 file changed

+5
-52
lines changed

1 file changed

+5
-52
lines changed

ports/rp2/machine_spi.c

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -261,61 +261,14 @@ static void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj
261261

262262
static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
263263
machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
264-
// Use DMA for large transfers if channels are available
265-
const size_t dma_min_size_threshold = 32;
266-
int chan_tx = -1;
267-
int chan_rx = -1;
268-
if (len >= dma_min_size_threshold) {
269-
// Use two DMA channels to service the two FIFOs
270-
chan_tx = dma_claim_unused_channel(false);
271-
chan_rx = dma_claim_unused_channel(false);
272-
}
273-
bool use_dma = chan_rx >= 0 && chan_tx >= 0;
264+
274265
// note src is guaranteed to be non-NULL
275266
bool write_only = dest == NULL;
276267

277-
if (use_dma) {
278-
uint8_t dev_null;
279-
dma_channel_config c = dma_channel_get_default_config(chan_tx);
280-
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
281-
channel_config_set_dreq(&c, spi_get_index(self->spi_inst) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
282-
dma_channel_configure(chan_tx, &c,
283-
&spi_get_hw(self->spi_inst)->dr,
284-
src,
285-
len,
286-
false);
287-
288-
c = dma_channel_get_default_config(chan_rx);
289-
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
290-
channel_config_set_dreq(&c, spi_get_index(self->spi_inst) ? DREQ_SPI1_RX : DREQ_SPI0_RX);
291-
channel_config_set_read_increment(&c, false);
292-
channel_config_set_write_increment(&c, !write_only);
293-
dma_channel_configure(chan_rx, &c,
294-
write_only ? &dev_null : dest,
295-
&spi_get_hw(self->spi_inst)->dr,
296-
len,
297-
false);
298-
299-
dma_start_channel_mask((1u << chan_rx) | (1u << chan_tx));
300-
dma_channel_wait_for_finish_blocking(chan_rx);
301-
dma_channel_wait_for_finish_blocking(chan_tx);
302-
}
303-
304-
// If we have claimed only one channel successfully, we should release immediately
305-
if (chan_rx >= 0) {
306-
dma_channel_unclaim(chan_rx);
307-
}
308-
if (chan_tx >= 0) {
309-
dma_channel_unclaim(chan_tx);
310-
}
311-
312-
if (!use_dma) {
313-
// Use software for small transfers, or if couldn't claim two DMA channels
314-
if (write_only) {
315-
spi_write_blocking(self->spi_inst, src, len);
316-
} else {
317-
spi_write_read_blocking(self->spi_inst, src, dest, len);
318-
}
268+
if (write_only) {
269+
spi_write_blocking(self->spi_inst, src, len);
270+
} else {
271+
spi_write_read_blocking(self->spi_inst, src, dest, len);
319272
}
320273
}
321274

0 commit comments

Comments
 (0)