Merge branch 'bugfix/separate_gdma_tx_rx_interrupt' into 'master'

gdma: separate tx/rx channel interrupt

Closes IDF-3181

See merge request espressif/esp-idf!13367
This commit is contained in:
Michael (XIAO Xufeng)
2021-05-06 16:38:44 +00:00
11 changed files with 283 additions and 152 deletions

View File

@@ -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;

View File

@@ -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)

View File

@@ -17,7 +17,6 @@
#include <stdbool.h>
#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
*/

View File

@@ -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;
}
/**

View File

@@ -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,
}
}
}

View File

@@ -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

View File

@@ -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,
}
}
}

View File

@@ -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)

View File

@@ -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*/

View File

@@ -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"

View File

@@ -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;