From df7ebcd783d5f8bbb9aeb82adda489911665f026 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Sat, 24 Oct 2026 12:42:21 +1100 Subject: [PATCH] machine/rp2: stop SPI1 transmit from restarting SPI0 DMA Each SPI1 transmit restarted the SPI0 DMA channel, so SPI0 sent bytes from memory past the end of its previous buffer. The SPI DMA channels now chain to themselves, and SPI1 no longer affects SPI0. Fixes #6009 --- src/machine/machine_rp2_spi.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_rp2_spi.go b/src/machine/machine_rp2_spi.go index 14ac5bae6a..d0f86d7661 100644 --- a/src/machine/machine_rp2_spi.go +++ b/src/machine/machine_rp2_spi.go @@ -274,21 +274,23 @@ func (spi *SPI) tx(tx []byte) error { } // Pick the DMA channel reserved for this SPI peripheral. - var ch *dmaChannel + var channel uint32 var dreq uint32 if spi.Bus == rp.SPI0 { - ch = &dmaChannels[spi0DMAChannel] + channel = spi0DMAChannel dreq = rp.DREQ_SPI0_TX } else { // SPI1 - ch = &dmaChannels[spi1DMAChannel] + channel = spi1DMAChannel dreq = rp.DREQ_SPI1_TX } + ch := &dmaChannels[channel] // Configure the DMA peripheral as follows: // - set read address, write address, and number of transfer units (bytes) // - increment read address (in memory), don't increment write address (SSPDR) // - set data size to single bytes // - set the DREQ so that the DMA will fill the SPI FIFO as needed + // - chain to itself, which disables chaining // - start the transfer ch.READ_ADDR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(tx))))) ch.WRITE_ADDR.Set(uint32(uintptr(unsafe.Pointer(&spi.Bus.SSPDR)))) @@ -296,6 +298,7 @@ func (spi *SPI) tx(tx []byte) error { ch.CTRL_TRIG.Set(rp.DMA_CH0_CTRL_TRIG_INCR_READ | rp.DMA_CH0_CTRL_TRIG_DATA_SIZE_SIZE_BYTE<