drivers: dma: dma_mcux_lpc: fix multiple bugs with continuous mode
There are multiple bugs related to continuous/circular mode.
Continuous/circular mode is where the DMA runs continuously
until the stop API is called, instead of auto-stopping on
completion on a single transfer. After a stop, the DMA
can then be reconfigured/restarted.
1. Fix bug where stop didn't actually stop. This can cause memory
corruption if the user thought the DMA stopped and repurposed
the dest memory, but in fact the DMA is still writing to it.
The bug was due the incorrect usage of the DMA controller busy
state. The DMA controller is busy only when a transfer is
actively in progress, but the driver needed to stop even if
the transfer is not active but is only enabled (and may become
active on a subsequent trigger event). Change so that data->busy
doesn't use the DMA controller busy state but tracks the enable
state. Also, to make it doubly safe, make stop function always stop
regardless of data->busy state because it is alway safe/correct
to do so.
2. Fix race condition where a stop request from another ISR might race
with a DMA completion interrupt, and the DMA completion callback
gets invoked after the DMA has already been stopped. The fix
is to unregister the callback with the sdk DMA driver, so the
ISR still runs and clear the interrupt without invoking the
callback. There is potentially still a race if the interrupt
is restarted before the ISR fires, so the callback might be
called too early. However, the Zephyr DMA driver doesn't
have the channel level details that the SDK driver does and
it cannot clear just the channel interrupt.
Also a couple of general fixes/improvements:
a. Use interrupt B for end of transfer (single transfer or end
of block list). Use interrupt A for interrupts of a block
in the middle of a transfer or for continuous/circular transfers.
This fixes the dma callback so it can properly report
DMA_STATUS_BLOCK vs DMA_STATUS_COMPLETE.
b. Reorder some fields in struct channel_data to pack a little
better in memory
Signed-off-by:
Mike J. Chen <mjchen@google.com>
Loading
Please sign in to comment