diff --git a/components/driver/gdma.c b/components/driver/gdma.c index d0791b8eaf..c1b7f497fc 100644 --- a/components/driver/gdma.c +++ b/components/driver/gdma.c @@ -51,7 +51,7 @@ typedef struct gdma_rx_channel_t gdma_rx_channel_t; * We don't use an all-in-one spin lock in this driver, instead, we created different spin locks at different level. * For platform, it has a spinlock, which is used to protect the group handle slots and reference count of each group. * For group, it has a spinlock, which is used to protect group level stuffs, e.g. hal object, pair handle slots and reference count of each pair. - * For pair, it has a sinlock, which is used to protect pair level stuffs, e.g. interrupt handle, channel handle slots, occupy code. + * For pair, it has a spinlock, which is used to protect pair level stuffs, e.g. channel handle slots, occupy code. */ struct gdma_platform_t { @@ -74,12 +74,12 @@ struct gdma_pair_t { gdma_tx_channel_t *tx_chan; // pointer of tx channel in the pair gdma_rx_channel_t *rx_chan; // pointer of rx channel in the pair int occupy_code; // each bit indicates which channel has been occupied (an occupied channel will be skipped during channel search) - intr_handle_t intr; // Interrupt is at pair level portMUX_TYPE spinlock; // pair level spinlock }; struct gdma_channel_t { gdma_pair_t *pair; // which pair the channel belongs to + intr_handle_t intr; // per-channel interrupt handle gdma_channel_direction_t direction; // channel direction int periph_id; // Peripheral instance ID, indicates which peripheral is connected to this GDMA channel esp_err_t (*del)(gdma_channel_t *channel); // channel deletion function, it's polymorphic, see `gdma_del_tx_channel` or `gdma_del_rx_channel` @@ -105,7 +105,8 @@ static void gdma_uninstall_group(gdma_group_t *group); static void gdma_uninstall_pair(gdma_pair_t *pair); static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel); static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel); -static esp_err_t gdma_install_interrupt(gdma_pair_t *pair); +static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan); +static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan); // gdma driver platform static gdma_platform_t s_platform = { @@ -309,17 +310,17 @@ esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ gdma_tx_channel_t *tx_chan = __containerof(dma_chan, gdma_tx_channel_t, base); // lazy install interrupt service - ESP_GOTO_ON_ERROR(gdma_install_interrupt(pair), err, TAG, "install interrupt service failed"); + ESP_GOTO_ON_ERROR(gdma_install_tx_interrupt(tx_chan), err, TAG, "install interrupt service failed"); // enable/disable GDMA interrupt events for TX channel portENTER_CRITICAL(&pair->spinlock); - gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, GDMA_LL_EVENT_TX_EOF, cbs->on_trans_eof != NULL); + gdma_ll_tx_enable_interrupt(group->hal.dev, pair->pair_id, GDMA_LL_EVENT_TX_EOF, cbs->on_trans_eof != NULL); portEXIT_CRITICAL(&pair->spinlock); tx_chan->on_trans_eof = cbs->on_trans_eof; tx_chan->user_data = user_data; - ESP_GOTO_ON_ERROR(esp_intr_enable(pair->intr), err, TAG, "enable interrupt failed"); + ESP_GOTO_ON_ERROR(esp_intr_enable(dma_chan->intr), err, TAG, "enable interrupt failed"); err: return ret; @@ -336,17 +337,17 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ gdma_rx_channel_t *rx_chan = __containerof(dma_chan, gdma_rx_channel_t, base); // lazy install interrupt service - ESP_GOTO_ON_ERROR(gdma_install_interrupt(pair), err, TAG, "install interrupt service failed"); + ESP_GOTO_ON_ERROR(gdma_install_rx_interrupt(rx_chan), err, TAG, "install interrupt service failed"); // enable/disable GDMA interrupt events for RX channel portENTER_CRITICAL(&pair->spinlock); - gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, GDMA_LL_EVENT_RX_SUC_EOF, cbs->on_recv_eof != NULL); + gdma_ll_rx_enable_interrupt(group->hal.dev, pair->pair_id, GDMA_LL_EVENT_RX_SUC_EOF, cbs->on_recv_eof != NULL); portEXIT_CRITICAL(&pair->spinlock); rx_chan->on_recv_eof = cbs->on_recv_eof; rx_chan->user_data = user_data; - ESP_GOTO_ON_ERROR(esp_intr_enable(pair->intr), err, TAG, "enable interrupt failed"); + ESP_GOTO_ON_ERROR(esp_intr_enable(dma_chan->intr), err, TAG, "enable interrupt failed"); err: return ret; @@ -486,20 +487,10 @@ static void gdma_uninstall_pair(gdma_pair_t *pair) assert(group->pairs[pair_id]); do_deinitialize = true; group->pairs[pair_id] = NULL; // deregister from pair - if (pair->intr) { - // disable interrupt handler (but not freed, esp_intr_free is a blocking API, we can't use it in a critical section) - esp_intr_disable(pair->intr); - gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events - gdma_ll_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events - } } portEXIT_CRITICAL(&group->spinlock); if (do_deinitialize) { - if (pair->intr) { - esp_intr_free(pair->intr); // free interrupt resource - ESP_LOGD(TAG, "uninstall interrupt service for pair (%d,%d)", group->group_id, pair_id); - } free(pair); ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id); @@ -559,6 +550,15 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel) pair->occupy_code &= ~SEARCH_REQUEST_TX_CHANNEL; portEXIT_CRITICAL(&pair->spinlock); + if (dma_channel->intr) { + esp_intr_free(dma_channel->intr); + portENTER_CRITICAL(&pair->spinlock); + gdma_ll_tx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events + gdma_ll_tx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events + portEXIT_CRITICAL(&pair->spinlock); + ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group->group_id, pair->pair_id); + } + ESP_LOGD(TAG, "del tx channel (%d,%d)", group->group_id, pair->pair_id); free(tx_chan); gdma_uninstall_pair(pair); @@ -575,22 +575,30 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel) pair->occupy_code &= ~SEARCH_REQUEST_RX_CHANNEL; portEXIT_CRITICAL(&pair->spinlock); + if (dma_channel->intr) { + esp_intr_free(dma_channel->intr); + portENTER_CRITICAL(&pair->spinlock); + gdma_ll_rx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events + gdma_ll_rx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events + portEXIT_CRITICAL(&pair->spinlock); + ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group->group_id, pair->pair_id); + } + ESP_LOGD(TAG, "del rx channel (%d,%d)", group->group_id, pair->pair_id); free(rx_chan); gdma_uninstall_pair(pair); return ESP_OK; } -static void IRAM_ATTR gdma_default_isr(void *args) +static void IRAM_ATTR gdma_default_rx_isr(void *args) { - gdma_pair_t *pair = (gdma_pair_t *)args; + gdma_rx_channel_t *rx_chan = (gdma_rx_channel_t *)args; + gdma_pair_t *pair = rx_chan->base.pair; gdma_group_t *group = pair->group; - gdma_rx_channel_t *rx_chan = pair->rx_chan; - gdma_tx_channel_t *tx_chan = pair->tx_chan; bool need_yield = false; // clear pending interrupt event - uint32_t intr_status = gdma_ll_get_interrupt_status(group->hal.dev, pair->pair_id); - gdma_ll_clear_interrupt_status(group->hal.dev, pair->pair_id, intr_status); + uint32_t intr_status = gdma_ll_rx_get_interrupt_status(group->hal.dev, pair->pair_id); + gdma_ll_rx_clear_interrupt_status(group->hal.dev, pair->pair_id, intr_status); if (intr_status & GDMA_LL_EVENT_RX_SUC_EOF) { if (rx_chan && rx_chan->on_recv_eof) { @@ -604,6 +612,21 @@ static void IRAM_ATTR gdma_default_isr(void *args) } } + if (need_yield) { + portYIELD_FROM_ISR(); + } +} + +static void IRAM_ATTR gdma_default_tx_isr(void *args) +{ + gdma_tx_channel_t *tx_chan = (gdma_tx_channel_t *)args; + gdma_pair_t *pair = tx_chan->base.pair; + gdma_group_t *group = pair->group; + bool need_yield = false; + // clear pending interrupt event + uint32_t intr_status = gdma_ll_tx_get_interrupt_status(group->hal.dev, pair->pair_id); + gdma_ll_tx_clear_interrupt_status(group->hal.dev, pair->pair_id, intr_status); + if (intr_status & GDMA_LL_EVENT_TX_EOF) { if (tx_chan && tx_chan->on_trans_eof) { uint32_t eof_addr = gdma_ll_tx_get_eof_desc_addr(group->hal.dev, pair->pair_id); @@ -621,34 +644,55 @@ static void IRAM_ATTR gdma_default_isr(void *args) } } -static esp_err_t gdma_install_interrupt(gdma_pair_t *pair) +static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan) { esp_err_t ret = ESP_OK; + gdma_pair_t *pair = rx_chan->base.pair; gdma_group_t *group = pair->group; - bool do_install_isr = false; - // pre-alloc a interrupt handle, shared with other handle, with handler disabled - // This is used to prevent potential concurrency between interrupt install and uninstall - int isr_flags = ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED; + // pre-alloc a interrupt handle, with handler disabled + int isr_flags = ESP_INTR_FLAG_INTRDISABLED; +#if SOC_GDMA_TX_RX_SHARE_INTERRUPT + isr_flags |= ESP_INTR_FLAG_SHARED; +#endif intr_handle_t intr = NULL; - ret = esp_intr_alloc(gdma_periph_signals.groups[group->group_id].pairs[pair->pair_id].irq_id, isr_flags, gdma_default_isr, pair, &intr); + ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair->pair_id].rx_irq_id, isr_flags, + (uint32_t)gdma_ll_rx_get_interrupt_status_reg(group->hal.dev, pair->pair_id), GDMA_LL_RX_EVENT_MASK, + gdma_default_rx_isr, rx_chan, &intr); ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc interrupt failed"); + rx_chan->base.intr = intr; - if (!pair->intr) { - portENTER_CRITICAL(&pair->spinlock); - if (!pair->intr) { - do_install_isr = true; - pair->intr = intr; - gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events - gdma_ll_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events - } - portEXIT_CRITICAL(&pair->spinlock); - } - if (do_install_isr) { - ESP_LOGD(TAG, "install interrupt service for pair (%d,%d)", group->group_id, pair->pair_id); - } else { - // interrupt handle has been installed before, so removed this one - esp_intr_free(intr); - } + portENTER_CRITICAL(&pair->spinlock); + gdma_ll_rx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events + gdma_ll_rx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events + portEXIT_CRITICAL(&pair->spinlock); + ESP_LOGD(TAG, "install interrupt service for rx channel (%d,%d)", group->group_id, pair->pair_id); + +err: + return ret; +} + +static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan) +{ + esp_err_t ret = ESP_OK; + gdma_pair_t *pair = tx_chan->base.pair; + gdma_group_t *group = pair->group; + // pre-alloc a interrupt handle, with handler disabled + int isr_flags = ESP_INTR_FLAG_INTRDISABLED; +#if SOC_GDMA_TX_RX_SHARE_INTERRUPT + isr_flags |= ESP_INTR_FLAG_SHARED; +#endif + intr_handle_t intr = NULL; + ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair->pair_id].tx_irq_id, isr_flags, + (uint32_t)gdma_ll_tx_get_interrupt_status_reg(group->hal.dev, pair->pair_id), GDMA_LL_TX_EVENT_MASK, + gdma_default_tx_isr, tx_chan, &intr); + ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc interrupt failed"); + tx_chan->base.intr = intr; + + portENTER_CRITICAL(&pair->spinlock); + gdma_ll_tx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events + gdma_ll_tx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events + portEXIT_CRITICAL(&pair->spinlock); + ESP_LOGD(TAG, "install interrupt service for tx channel (%d,%d)", group->group_id, pair->pair_id); err: return ret; diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index c0ef73d29a..7b956221ff 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -202,8 +202,8 @@ void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *conf void adc_hal_digi_init(adc_hal_context_t *hal) { - gdma_ll_clear_interrupt_status(hal->dev, hal->dma_chan, UINT32_MAX); - gdma_ll_enable_interrupt(hal->dev, hal->dma_chan, GDMA_LL_EVENT_RX_SUC_EOF, true); + gdma_ll_rx_clear_interrupt_status(hal->dev, hal->dma_chan, UINT32_MAX); + gdma_ll_rx_enable_interrupt(hal->dev, hal->dma_chan, GDMA_LL_EVENT_RX_SUC_EOF, true); adc_ll_digi_dma_set_eof_num(hal->eof_num); adc_ll_onetime_sample_enable(ADC_NUM_1, false); adc_ll_onetime_sample_enable(ADC_NUM_2, false); @@ -273,12 +273,12 @@ void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal) void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask) { - gdma_ll_clear_interrupt_status(hal->dev, hal->dma_chan, mask); + gdma_ll_rx_clear_interrupt_status(hal->dev, hal->dma_chan, mask); } void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask) { - gdma_ll_enable_interrupt(hal->dev, hal->dma_chan, mask, false); + gdma_ll_rx_enable_interrupt(hal->dev, hal->dma_chan, mask, false); } void adc_hal_digi_stop(adc_hal_context_t *hal) diff --git a/components/hal/esp32c3/include/hal/gdma_ll.h b/components/hal/esp32c3/include/hal/gdma_ll.h index a1d6e1389a..6ce2f89f66 100644 --- a/components/hal/esp32c3/include/hal/gdma_ll.h +++ b/components/hal/esp32c3/include/hal/gdma_ll.h @@ -17,7 +17,6 @@ #include #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" -#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -25,6 +24,9 @@ extern "C" { #define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL) +#define GDMA_LL_RX_EVENT_MASK (0x06A7) +#define GDMA_LL_TX_EVENT_MASK (0x1958) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<12) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<11) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<10) @@ -47,40 +49,12 @@ static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bo { dev->channel[channel].in.in_conf0.mem_trans_en = enable; if (enable) { - // only have to give it a valid value + // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a valid value dev->channel[channel].in.in_peri_sel.sel = 0; dev->channel[channel].out.out_peri_sel.sel = 0; } } -/** - * @brief Get DMA interrupt status word - */ -static inline uint32_t gdma_ll_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) -{ - return dev->intr[channel].st.val; -} - -/** - * @brief Enable DMA interrupt - */ -static inline void gdma_ll_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) -{ - if (enable) { - dev->intr[channel].ena.val |= mask; - } else { - dev->intr[channel].ena.val &= ~mask; - } -} - -/** - * @brief Clear DMA interrupt - */ -static inline void gdma_ll_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) -{ - dev->intr[channel].clr.val = mask; -} - /** * @brief Enable DMA clock gating */ @@ -90,6 +64,42 @@ static inline void gdma_ll_enable_clock(gdma_dev_t *dev, bool enable) } ///////////////////////////////////// RX ///////////////////////////////////////// +/** + * @brief Get DMA RX channel interrupt status word + */ +static inline uint32_t gdma_ll_rx_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) +{ + return dev->intr[channel].st.val & GDMA_LL_RX_EVENT_MASK; +} + +/** + * @brief Enable DMA RX channel interrupt + */ +static inline void gdma_ll_rx_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) +{ + if (enable) { + dev->intr[channel].ena.val |= (mask & GDMA_LL_RX_EVENT_MASK); + } else { + dev->intr[channel].ena.val &= ~(mask & GDMA_LL_RX_EVENT_MASK); + } +} + +/** + * @brief Clear DMA RX channel interrupt + */ +static inline void gdma_ll_rx_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) +{ + dev->intr[channel].clr.val = (mask & GDMA_LL_RX_EVENT_MASK); +} + +/** + * @brief Get DMA RX channel interrupt status register address + */ +static inline volatile void *gdma_ll_rx_get_interrupt_status_reg(gdma_dev_t *dev, uint32_t channel) +{ + return (volatile void *)(&dev->intr[channel].st); +} + /** * @brief Enable DMA RX channel to check the owner bit in the descriptor, disabled by default */ @@ -248,6 +258,42 @@ static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channe } ///////////////////////////////////// TX ///////////////////////////////////////// +/** + * @brief Get DMA TX channel interrupt status word + */ +static inline uint32_t gdma_ll_tx_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) +{ + return dev->intr[channel].st.val & GDMA_LL_TX_EVENT_MASK; +} + +/** + * @brief Enable DMA TX channel interrupt + */ +static inline void gdma_ll_tx_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) +{ + if (enable) { + dev->intr[channel].ena.val |= (mask & GDMA_LL_TX_EVENT_MASK); + } else { + dev->intr[channel].ena.val &= ~(mask & GDMA_LL_TX_EVENT_MASK); + } +} + +/** + * @brief Clear DMA TX channel interrupt + */ +static inline void gdma_ll_tx_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) +{ + dev->intr[channel].clr.val = (mask & GDMA_LL_TX_EVENT_MASK); +} + +/** + * @brief Get DMA TX channel interrupt status register address + */ +static inline volatile void *gdma_ll_tx_get_interrupt_status_reg(gdma_dev_t *dev, uint32_t channel) +{ + return (volatile void *)(&dev->intr[channel].st); +} + /** * @brief Enable DMA TX channel to check the owner bit in the descriptor, disabled by default */ diff --git a/components/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index d6c4e334f3..9483302132 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -25,21 +25,25 @@ extern "C" { #define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL) -#define GDMA_LL_EVENT_TX_L3_FIFO_UDF (1<<17) -#define GDMA_LL_EVENT_TX_L3_FIFO_OVF (1<<16) -#define GDMA_LL_EVENT_TX_L1_FIFO_UDF (1<<15) -#define GDMA_LL_EVENT_TX_L1_FIFO_OVF (1<<14) -#define GDMA_LL_EVENT_RX_L3_FIFO_UDF (1<<13) -#define GDMA_LL_EVENT_RX_L3_FIFO_OVF (1<<12) -#define GDMA_LL_EVENT_RX_L1_FIFO_UDF (1<<11) -#define GDMA_LL_EVENT_RX_L1_FIFO_OVF (1<<10) -#define GDMA_LL_EVENT_RX_WATER_MARK (1<<9) -#define GDMA_LL_EVENT_TX_TOTAL_EOF (1<<8) -#define GDMA_LL_EVENT_RX_DESC_EMPTY (1<<7) -#define GDMA_LL_EVENT_TX_DESC_ERROR (1<<6) -#define GDMA_LL_EVENT_RX_DESC_ERROR (1<<5) -#define GDMA_LL_EVENT_TX_EOF (1<<4) -#define GDMA_LL_EVENT_TX_DONE (1<<3) +#define GDMA_LL_RX_EVENT_MASK (0x3FF) +#define GDMA_LL_TX_EVENT_MASK (0xFF) + +#define GDMA_LL_EVENT_TX_L3_FIFO_UDF (1<<7) +#define GDMA_LL_EVENT_TX_L3_FIFO_OVF (1<<6) +#define GDMA_LL_EVENT_TX_L1_FIFO_UDF (1<<5) +#define GDMA_LL_EVENT_TX_L1_FIFO_OVF (1<<4) +#define GDMA_LL_EVENT_TX_TOTAL_EOF (1<<3) +#define GDMA_LL_EVENT_TX_DESC_ERROR (1<<2) +#define GDMA_LL_EVENT_TX_EOF (1<<1) +#define GDMA_LL_EVENT_TX_DONE (1<<0) + +#define GDMA_LL_EVENT_RX_L3_FIFO_UDF (1<<9) +#define GDMA_LL_EVENT_RX_L3_FIFO_OVF (1<<8) +#define GDMA_LL_EVENT_RX_L1_FIFO_UDF (1<<7) +#define GDMA_LL_EVENT_RX_L1_FIFO_OVF (1<<6) +#define GDMA_LL_EVENT_RX_WATER_MARK (1<<5) +#define GDMA_LL_EVENT_RX_DESC_EMPTY (1<<4) +#define GDMA_LL_EVENT_RX_DESC_ERROR (1<<3) #define GDMA_LL_EVENT_RX_ERR_EOF (1<<2) #define GDMA_LL_EVENT_RX_SUC_EOF (1<<1) #define GDMA_LL_EVENT_RX_DONE (1<<0) @@ -59,17 +63,26 @@ static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bo } /** - * @brief Get DMA interrupt status word + * @brief Enable DMA clock gating */ -static inline uint32_t gdma_ll_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) +static inline void gdma_ll_enable_clock(gdma_dev_t *dev, bool enable) +{ + dev->misc_conf.clk_en = enable; +} + +///////////////////////////////////// RX ///////////////////////////////////////// +/** + * @brief Get DMA RX channel interrupt status word + */ +static inline uint32_t gdma_ll_rx_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) { return dev->in[channel].int_st.val; } /** - * @brief Enable DMA interrupt + * @brief Enable DMA RX channel interrupt */ -static inline void gdma_ll_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) +static inline void gdma_ll_rx_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) { if (enable) { dev->in[channel].int_ena.val |= mask; @@ -79,22 +92,21 @@ static inline void gdma_ll_enable_interrupt(gdma_dev_t *dev, uint32_t channel, u } /** - * @brief Clear DMA interrupt + * @brief Clear DMA RX channel interrupt */ -static inline void gdma_ll_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) +static inline void gdma_ll_rx_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) { dev->in[channel].int_clr.val = mask; } /** - * @brief Enable DMA clock gating + * @brief Get DMA RX channel interrupt status register address */ -static inline void gdma_ll_enable_clock(gdma_dev_t *dev, bool enable) +static inline volatile void *gdma_ll_rx_get_interrupt_status_reg(gdma_dev_t *dev, uint32_t channel) { - dev->misc_conf.clk_en = enable; + return (volatile void *)(&dev->in[channel].int_st); } -///////////////////////////////////// RX ///////////////////////////////////////// /** * @brief Enable DMA RX channel to check the owner bit in the descriptor, disabled by default */ @@ -279,7 +291,7 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) { dev->in[channel].peri_sel.sel = periph_id; } @@ -298,6 +310,42 @@ static inline void gdma_ll_rx_extend_l2_fifo_size_to(gdma_dev_t *dev, uint32_t c ///////////////////////////////////// TX ///////////////////////////////////////// +/** + * @brief Get DMA TX channel interrupt status word + */ +static inline uint32_t gdma_ll_tx_get_interrupt_status(gdma_dev_t *dev, uint32_t channel) +{ + return dev->out[channel].int_st.val; +} + +/** + * @brief Enable DMA TX channel interrupt + */ +static inline void gdma_ll_tx_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable) +{ + if (enable) { + dev->out[channel].int_ena.val |= mask; + } else { + dev->out[channel].int_ena.val &= ~mask; + } +} + +/** + * @brief Clear DMA TX channel interrupt + */ +static inline void gdma_ll_tx_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask) +{ + dev->out[channel].int_clr.val = mask; +} + +/** + * @brief Get DMA TX channel interrupt status register address + */ +static inline volatile void *gdma_ll_tx_get_interrupt_status_reg(gdma_dev_t *dev, uint32_t channel) +{ + return (volatile void *)(&dev->out[channel].int_st); +} + /** * @brief Enable DMA TX channel to check the owner bit in the descriptor, disabled by default */ @@ -474,9 +522,9 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) { - dev->out[channel].peri_sel.sel = periph_id; + dev->out[channel].peri_sel.sel = periph_id; } /** diff --git a/components/soc/esp32c3/gdma_periph.c b/components/soc/esp32c3/gdma_periph.c index 2cb49943d1..1475487eb5 100644 --- a/components/soc/esp32c3/gdma_periph.c +++ b/components/soc/esp32c3/gdma_periph.c @@ -20,13 +20,16 @@ const gdma_signal_conn_t gdma_periph_signals = { .module = PERIPH_GDMA_MODULE, .pairs = { [0] = { - .irq_id = ETS_DMA_CH0_INTR_SOURCE + .rx_irq_id = ETS_DMA_CH0_INTR_SOURCE, + .tx_irq_id = ETS_DMA_CH0_INTR_SOURCE, }, [1] = { - .irq_id = ETS_DMA_CH1_INTR_SOURCE + .rx_irq_id = ETS_DMA_CH1_INTR_SOURCE, + .tx_irq_id = ETS_DMA_CH1_INTR_SOURCE, }, [2] = { - .irq_id = ETS_DMA_CH2_INTR_SOURCE + .rx_irq_id = ETS_DMA_CH2_INTR_SOURCE, + .tx_irq_id = ETS_DMA_CH2_INTR_SOURCE, } } } diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index df9745489c..cfda89c29f 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -14,7 +14,6 @@ #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 - /*-------------------------- COMMON CAPS ---------------------------------------*/ #define SOC_SUPPORTS_SECURE_DL_MODE 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 @@ -68,8 +67,9 @@ #define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100) /*-------------------------- GDMA CAPS -------------------------------------*/ -#define SOC_GDMA_GROUPS (1) -#define SOC_GDMA_PAIRS_PER_GROUP (3) +#define SOC_GDMA_GROUPS (1) // Number of GDMA groups +#define SOC_GDMA_PAIRS_PER_GROUP (3) // Number of GDMA pairs in each group +#define SOC_GDMA_TX_RX_SHARE_INTERRUPT (1) // TX and RX channel in the same pair will share the same interrupt source number /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C3 has 1 GPIO peripheral @@ -205,6 +205,7 @@ #define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1) #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) + /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM (2) // Number of counter units #define SOC_SYSTIMER_ALARM_NUM (3) // Number of alarm units diff --git a/components/soc/esp32s3/gdma_periph.c b/components/soc/esp32s3/gdma_periph.c index 091deca37b..b2bce8d377 100644 --- a/components/soc/esp32s3/gdma_periph.c +++ b/components/soc/esp32s3/gdma_periph.c @@ -20,19 +20,24 @@ const gdma_signal_conn_t gdma_periph_signals = { .module = PERIPH_GDMA_MODULE, .pairs = { [0] = { - .irq_id = ETS_DMA_CH0_INTR_SOURCE + .rx_irq_id = ETS_DMA_IN_CH0_INTR_SOURCE, + .tx_irq_id = ETS_DMA_OUT_CH0_INTR_SOURCE, }, [1] = { - .irq_id = ETS_DMA_CH1_INTR_SOURCE + .rx_irq_id = ETS_DMA_IN_CH1_INTR_SOURCE, + .tx_irq_id = ETS_DMA_OUT_CH1_INTR_SOURCE, }, [2] = { - .irq_id = ETS_DMA_CH2_INTR_SOURCE + .rx_irq_id = ETS_DMA_IN_CH2_INTR_SOURCE, + .tx_irq_id = ETS_DMA_OUT_CH2_INTR_SOURCE, }, [3] = { - .irq_id = ETS_DMA_CH3_INTR_SOURCE + .rx_irq_id = ETS_DMA_IN_CH3_INTR_SOURCE, + .tx_irq_id = ETS_DMA_OUT_CH3_INTR_SOURCE, }, [4] = { - .irq_id = ETS_DMA_CH4_INTR_SOURCE + .rx_irq_id = ETS_DMA_IN_CH4_INTR_SOURCE, + .tx_irq_id = ETS_DMA_OUT_CH4_INTR_SOURCE, } } } diff --git a/components/soc/esp32s3/include/soc/gdma_caps.h b/components/soc/esp32s3/include/soc/gdma_caps.h deleted file mode 100644 index 7c92fa70ef..0000000000 --- a/components/soc/esp32s3/include/soc/gdma_caps.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#define SOC_GDMA_GROUPS (1) -#define SOC_GDMA_PAIRS_PER_GROUP (5) -#define SOC_GDMA_L2_FIFO_BASE_SIZE (16) -#define SOC_GDMA_SUPPORT_EXTMEM (1) diff --git a/components/soc/esp32s3/include/soc/periph_defs.h b/components/soc/esp32s3/include/soc/periph_defs.h index 042c935062..d301ec505a 100644 --- a/components/soc/esp32s3/include/soc/periph_defs.h +++ b/components/soc/esp32s3/include/soc/periph_defs.h @@ -124,16 +124,16 @@ typedef enum { ETS_DCACHE_SYNC0_INTR_SOURCE, /**< interrupt of data cache sync done, LEVEL*/ ETS_ICACHE_SYNC0_INTR_SOURCE, /**< interrupt of instruction cache sync done, LEVEL*/ ETS_APB_ADC_INTR_SOURCE, /**< interrupt of APB ADC, LEVEL*/ - ETS_DMA_CH0_INTR_SOURCE, /**< interrupt of general DMA channel 0, LEVEL*/ - ETS_DMA_CH1_INTR_SOURCE, /**< interrupt of general DMA channel 1, LEVEL*/ - ETS_DMA_CH2_INTR_SOURCE, /**< interrupt of general DMA channel 2, LEVEL*/ - ETS_DMA_CH3_INTR_SOURCE, /**< interrupt of general DMA channel 3, LEVEL*/ - ETS_DMA_CH4_INTR_SOURCE, /**< interrupt of general DMA channel 4, LEVEL*/ - ETS_DMA_OUT_CH0_INTR_SOURCE, - ETS_DMA_OUT_CH1_INTR_SOURCE, - ETS_DMA_OUT_CH2_INTR_SOURCE, - ETS_DMA_OUT_CH3_INTR_SOURCE, - ETS_DMA_OUT_CH4_INTR_SOURCE, + ETS_DMA_IN_CH0_INTR_SOURCE, /**< interrupt of general DMA RX channel 0, LEVEL*/ + ETS_DMA_IN_CH1_INTR_SOURCE, /**< interrupt of general DMA RX channel 1, LEVEL*/ + ETS_DMA_IN_CH2_INTR_SOURCE, /**< interrupt of general DMA RX channel 2, LEVEL*/ + ETS_DMA_IN_CH3_INTR_SOURCE, /**< interrupt of general DMA RX channel 3, LEVEL*/ + ETS_DMA_IN_CH4_INTR_SOURCE, /**< interrupt of general DMA RX channel 4, LEVEL*/ + ETS_DMA_OUT_CH0_INTR_SOURCE, /**< interrupt of general DMA TX channel 0, LEVEL*/ + ETS_DMA_OUT_CH1_INTR_SOURCE, /**< interrupt of general DMA TX channel 1, LEVEL*/ + ETS_DMA_OUT_CH2_INTR_SOURCE, /**< interrupt of general DMA TX channel 2, LEVEL*/ + ETS_DMA_OUT_CH3_INTR_SOURCE, /**< interrupt of general DMA TX channel 3, LEVEL*/ + ETS_DMA_OUT_CH4_INTR_SOURCE, /**< interrupt of general DMA TX channel 4, LEVEL*/ ETS_RSA_INTR_SOURCE, /**< interrupt of RSA accelerator, level*/ ETS_AES_INTR_SOURCE, /**< interrupt of AES accelerator, level*/ ETS_SHA_INTR_SOURCE, /**< interrupt of SHA accelerator, level*/ diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 176f4a3137..231057f879 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -33,7 +33,10 @@ #include "cpu_caps.h" /*-------------------------- GDMA CAPS ---------------------------------------*/ -#include "gdma_caps.h" +#define SOC_GDMA_GROUPS (1) // Number of GDMA groups +#define SOC_GDMA_PAIRS_PER_GROUP (5) // Number of GDMA pairs in each group +#define SOC_GDMA_L2_FIFO_BASE_SIZE (16) // Basic size of GDMA Level 2 FIFO +#define SOC_GDMA_SUPPORT_EXTMEM (1) // GDMA can access external PSRAM /*-------------------------- GPIO CAPS ---------------------------------------*/ #include "gpio_caps.h" diff --git a/components/soc/include/soc/gdma_periph.h b/components/soc/include/soc/gdma_periph.h index 2ccba24480..4cc9cb1728 100644 --- a/components/soc/include/soc/gdma_periph.h +++ b/components/soc/include/soc/gdma_periph.h @@ -25,7 +25,8 @@ typedef struct { struct { const periph_module_t module; struct { - const int irq_id; + const int rx_irq_id; + const int tx_irq_id; } pairs[SOC_GDMA_PAIRS_PER_GROUP]; } groups[SOC_GDMA_GROUPS]; } gdma_signal_conn_t;