Skip to content

Commit 6a221e0

Browse files
Add dma_channel_cleanup method and use it to cleanup after pico_cyw43_driver is closed (#1372)
1 parent 3b44b0d commit 6a221e0

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

src/rp2_common/hardware_dma/dma.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ bool dma_timer_is_claimed(uint timer) {
7070
return hw_is_claimed(&_timer_claimed, timer);
7171
}
7272

73+
void dma_channel_cleanup(uint channel) {
74+
check_dma_channel_param(channel);
75+
// Disable CHAIN_TO, and disable channel, so that it ignores any further triggers
76+
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 );
77+
// disable IRQs first as abort can cause spurious IRQs
78+
dma_channel_set_irq0_enabled(channel, false);
79+
dma_channel_set_irq1_enabled(channel, false);
80+
dma_channel_abort(channel);
81+
// finally clear the IRQ status, which may have been set during abort
82+
dma_hw->intr = 1u << channel;
83+
}
84+
7385
#ifndef NDEBUG
7486

7587
void print_dma_ctrl(dma_channel_hw_t *channel) {

src/rp2_common/hardware_dma/include/hardware/dma.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,25 @@ static inline uint dma_get_timer_dreq(uint timer_num) {
891891
return DREQ_DMA_TIMER0 + timer_num;
892892
}
893893

894+
/*! \brief Performs DMA channel cleanup after use
895+
* \ingroup hardware_dma
896+
*
897+
* This can be used to cleanup dma channels when they're no longer needed, such that they are in a clean state for reuse.
898+
* IRQ's for the channel are disabled, any in flight-transfer is aborted and any outstanding interrupts are cleared.
899+
* The channel is then clear to be reused for other purposes.
900+
*
901+
* \code
902+
* if (dma_channel >= 0) {
903+
* dma_channel_cleanup(dma_channel);
904+
* dma_channel_unclaim(dma_channel);
905+
* dma_channel = -1;
906+
* }
907+
* \endcode
908+
*
909+
* \param channel DMA channel
910+
*/
911+
void dma_channel_cleanup(uint channel);
912+
894913
#ifndef NDEBUG
895914
void print_dma_ctrl(dma_channel_hw_t *channel);
896915
#endif

src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,12 @@ void cyw43_spi_deinit(cyw43_int_t *self) {
163163
pio_sm_unclaim(bus_data->pio, bus_data->pio_sm);
164164
}
165165
if (bus_data->dma_out >= 0) {
166+
dma_channel_cleanup(bus_data->dma_out);
166167
dma_channel_unclaim(bus_data->dma_out);
167168
bus_data->dma_out = -1;
168169
}
169170
if (bus_data->dma_in >= 0) {
171+
dma_channel_cleanup(bus_data->dma_in);
170172
dma_channel_unclaim(bus_data->dma_in);
171173
bus_data->dma_in = -1;
172174
}

0 commit comments

Comments
 (0)