Add dma_channel_cleanup method and use it to cleanup after pico_cyw43_driver is closed (#1372)

This commit is contained in:
Peter Harper 2023-06-02 18:52:39 +01:00 committed by GitHub
parent 3b44b0d177
commit 6a221e023d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 0 deletions

View File

@ -70,6 +70,18 @@ bool dma_timer_is_claimed(uint timer) {
return hw_is_claimed(&_timer_claimed, timer);
}
void dma_channel_cleanup(uint channel) {
check_dma_channel_param(channel);
// Disable CHAIN_TO, and disable channel, so that it ignores any further triggers
hw_write_masked( &dma_hw->ch[channel].al1_ctrl, (channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB) | (0u << DMA_CH0_CTRL_TRIG_EN_LSB), DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS | DMA_CH0_CTRL_TRIG_EN_BITS );
// disable IRQs first as abort can cause spurious IRQs
dma_channel_set_irq0_enabled(channel, false);
dma_channel_set_irq1_enabled(channel, false);
dma_channel_abort(channel);
// finally clear the IRQ status, which may have been set during abort
dma_hw->intr = 1u << channel;
}
#ifndef NDEBUG
void print_dma_ctrl(dma_channel_hw_t *channel) {

View File

@ -891,6 +891,25 @@ static inline uint dma_get_timer_dreq(uint timer_num) {
return DREQ_DMA_TIMER0 + timer_num;
}
/*! \brief Performs DMA channel cleanup after use
* \ingroup hardware_dma
*
* This can be used to cleanup dma channels when they're no longer needed, such that they are in a clean state for reuse.
* IRQ's for the channel are disabled, any in flight-transfer is aborted and any outstanding interrupts are cleared.
* The channel is then clear to be reused for other purposes.
*
* \code
* if (dma_channel >= 0) {
* dma_channel_cleanup(dma_channel);
* dma_channel_unclaim(dma_channel);
* dma_channel = -1;
* }
* \endcode
*
* \param channel DMA channel
*/
void dma_channel_cleanup(uint channel);
#ifndef NDEBUG
void print_dma_ctrl(dma_channel_hw_t *channel);
#endif

View File

@ -163,10 +163,12 @@ void cyw43_spi_deinit(cyw43_int_t *self) {
pio_sm_unclaim(bus_data->pio, bus_data->pio_sm);
}
if (bus_data->dma_out >= 0) {
dma_channel_cleanup(bus_data->dma_out);
dma_channel_unclaim(bus_data->dma_out);
bus_data->dma_out = -1;
}
if (bus_data->dma_in >= 0) {
dma_channel_cleanup(bus_data->dma_in);
dma_channel_unclaim(bus_data->dma_in);
bus_data->dma_in = -1;
}