mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 21:54:33 +02:00
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:
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
@@ -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*/
|
||||
|
@@ -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"
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user