gdma: prevent mutli-channels connect to the same peripheral

1. add check in the gdma driver, to prevent multiple channels connecting
   to the same peripheral
2. memory copy DMA ID will occupy the peripheral's DMA ID on some ESP
   targets (e.g. esp32c3/s3). We should search for a free one when
install async memcpy driver.

Closes https://github.com/espressif/esp-idf/issues/10575
This commit is contained in:
morris
2023-01-20 10:49:43 +08:00
parent 1195b6cb2b
commit dbca74f1ef
17 changed files with 298 additions and 164 deletions

View File

@@ -8,6 +8,7 @@
#include <stddef.h> /* Required for NULL constant */
#include <stdint.h>
#include <stdbool.h>
#include "hal/gdma_types.h"
#include "soc/gdma_struct.h"
#include "soc/gdma_reg.h"
@@ -20,6 +21,10 @@ extern "C" {
#define GDMA_LL_RX_EVENT_MASK (0x06A7)
#define GDMA_LL_TX_EVENT_MASK (0x1958)
// any "valid" peripheral ID can be used for M2M mode
#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0x185)
#define GDMA_LL_INVALID_PERIPH_ID (0x3F)
#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)
@@ -35,19 +40,6 @@ extern "C" {
#define GDMA_LL_EVENT_RX_DONE (1<<0)
///////////////////////////////////// Common /////////////////////////////////////////
/**
* @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default
*/
static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable)
{
dev->channel[channel].in.in_conf0.mem_trans_en = enable;
if (enable) {
// 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 Enable DMA clock gating
*/
@@ -255,9 +247,19 @@ 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, int periph_id)
static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id)
{
dev->channel[channel].in.in_peri_sel.sel = periph_id;
dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M);
}
/**
* @brief Disconnect DMA RX channel from peripheral
*/
static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel)
{
dev->channel[channel].in.in_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID;
dev->channel[channel].in.in_conf0.mem_trans_en = false;
}
///////////////////////////////////// TX /////////////////////////////////////////
@@ -458,11 +460,20 @@ 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, int periph_id)
static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id)
{
(void)periph;
dev->channel[channel].out.out_peri_sel.sel = periph_id;
}
/**
* @brief Disconnect DMA TX channel from peripheral
*/
static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel)
{
dev->channel[channel].out.out_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID;
}
#ifdef __cplusplus
}
#endif