SPI DMA not seeming to always "let go" of buffers after a transfer (not certain)

honey_the_codewitch

Well-known member
Solved: I found a quirky bug in my UI code that occasionally made the target draw bitmap larger than the available buffer space. Walking off the end was causing errors in a different part of my code, which confused me and inspired this post. Sorry for the churn.


Code:
FPS: 150
Transfer completed of buffer at 0x20203088 (buffer 1)
Pending flush of buffer 2 starting at address 0x20204090
Begin DMA transfer of buffer at 0x20204090
Start painting controls
Writing to buffer #1
Controls rendered. xfer state 1 = 2. xfer state 2 = 1
Transfer completed of buffer at 0x20204090 (buffer 2)
Pending flush of buffer 1 starting at address 0x20203088
Begin DMA transfer of buffer at 0x20203088 (buffer 1)
Start painting controls
Writing to buffer #2
*hard fault*

What you're looking at are my logs. I've been over and over this for 3 days, trying so many different things, even rewriting my dirty rect rendering.
Note that it renders for many complete iterations of using both buffers before faulting. The faulting portion is no different than the parts that haven't faulted.

Also, some of this rendering code is part of my UIX library. This is the only device it faults on.
I can show code for the SPI stuff, and even the UIX library but it's non-trivial so I'd rather show bits on request but I will paste my on DMA completion code here:

C++:
#ifdef FASTRUN
    FASTRUN
#endif
void lcd_spi_driver_t4::process_dma_interrupt(void) {
    // See if we are logically done

    // We are in single refresh mode or the user has called cancel so
    // Lets try to release the CS pin
    // Lets wait until FIFO is not empty
    while (_pimxrt_spi->FSR & 0x1f);  // wait until this one is complete
    while (_pimxrt_spi->SR & LPSPI_SR_MBF);  // wait until this one is complete

    _dma_data[_spi_num]._dmatx.clearComplete();
    _pimxrt_spi->FCR = _spi_fcr_save;  // LPSPI_FCR_TXWATER(15); // _spi_fcr_save;    // restore the FSR status...
    _pimxrt_spi->DER = 0;              // DMA no longer doing TX (or RX)

    _pimxrt_spi->CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF;  // actually clear both...
    _pimxrt_spi->SR = 0x3f00;                                      // clear out all of the other status...
    _pending_rx_count = 0;                                         // Make sure count is zero
    end_transaction();
    _dma_state &= ~(LCD_SPI_DMA_ACTIVE | LCD_SPI_DMA_FINISH);

    _dma_data[_spi_num]._dmatx.clearInterrupt();
    _dma_data[_spi_num]._dmatx.clearComplete();
    asm("dsb");
#if defined(DEBUG_ASYNC_UPDATE)
    Serial.print("Transfer completed of buffer at 0x");
    Serial.println((unsigned long)(uintptr_t)_buffer,16);
#endif
    if (_on_transfer_complete != nullptr) {
        _on_transfer_complete(_on_transfer_complete_state);
    }
}

I feel like there's something I'm missing.
 
Last edited:
Back
Top