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

diff --git a/src/rp2_common/hardware_dma/dma.c b/src/rp2_common/hardware_dma/dma.c
index 5fec210..f306def 100644
--- a/src/rp2_common/hardware_dma/dma.c
+++ b/src/rp2_common/hardware_dma/dma.c
@@ -70,6 +70,18 @@
     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) {
diff --git a/src/rp2_common/hardware_dma/include/hardware/dma.h b/src/rp2_common/hardware_dma/include/hardware/dma.h
index fc34155..65c357e 100644
--- a/src/rp2_common/hardware_dma/include/hardware/dma.h
+++ b/src/rp2_common/hardware_dma/include/hardware/dma.h
@@ -891,6 +891,25 @@
     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
diff --git a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
index 809635d..5afe85e 100644
--- a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
+++ b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
@@ -163,10 +163,12 @@
             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;
         }