Add documentation to dma_channel_abort regarding errata RP2040-E13 (#816)
Co-authored-by: Luke Wren <wren6991@gmail.com>
This commit is contained in:
parent
5a927792ef
commit
4e62c26a2c
@ -473,6 +473,32 @@ static inline void dma_channel_start(uint channel) {
|
|||||||
*
|
*
|
||||||
* Function will only return once the DMA has stopped.
|
* Function will only return once the DMA has stopped.
|
||||||
*
|
*
|
||||||
|
* Note that due to errata RP2040-E13, aborting a channel which has transfers
|
||||||
|
* in-flight (i.e. an individual read has taken place but the corresponding write has not), the ABORT
|
||||||
|
* status bit will clear prematurely, and subsequently the in-flight
|
||||||
|
* transfers will trigger a completion interrupt once they complete.
|
||||||
|
*
|
||||||
|
* The effect of this is that you \em may see a spurious completion interrupt
|
||||||
|
* on the channel as a result of calling this method.
|
||||||
|
*
|
||||||
|
* The calling code should be sure to ignore a completion IRQ as a result of this method. This may
|
||||||
|
* not require any additional work, as aborting a channel which may be about to complete, when you have a completion
|
||||||
|
* IRQ handler registered, is inherently race-prone, and so code is likely needed to disambiguate the two occurrences.
|
||||||
|
*
|
||||||
|
* If that is not the case, but you do have a channel completion IRQ handler registered, you can simply
|
||||||
|
* disable/re-enable the IRQ around the call to this method as shown by this code fragment (using DMA IRQ0).
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* // disable the channel on IRQ0
|
||||||
|
* dma_channel_set_irq0_enabled(channel, false);
|
||||||
|
* // abort the channel
|
||||||
|
* dma_channel_abort(channel);
|
||||||
|
* // clear the spurious IRQ (if there was one)
|
||||||
|
* dma_channel_acknowledge_irq0(channel);
|
||||||
|
* // re-enable the channel on IRQ0
|
||||||
|
* dma_channel_set_irq0_enabled(channel, true);
|
||||||
|
*\endcode
|
||||||
|
*
|
||||||
* \param channel DMA channel
|
* \param channel DMA channel
|
||||||
*/
|
*/
|
||||||
static inline void dma_channel_abort(uint channel) {
|
static inline void dma_channel_abort(uint channel) {
|
||||||
@ -480,7 +506,7 @@ static inline void dma_channel_abort(uint channel) {
|
|||||||
dma_hw->abort = 1u << channel;
|
dma_hw->abort = 1u << channel;
|
||||||
// Bit will go 0 once channel has reached safe state
|
// Bit will go 0 once channel has reached safe state
|
||||||
// (i.e. any in-flight transfers have retired)
|
// (i.e. any in-flight transfers have retired)
|
||||||
while (dma_hw->abort & (1ul << channel)) tight_loop_contents();
|
while (dma_hw->ch[channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_0
|
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_0
|
||||||
|
Loading…
Reference in New Issue
Block a user