mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
refactor(adc): refactor dma ll functions on adc continuous mode
This commit is contained in:
parent
0bbee51829
commit
bc98bdc087
@ -57,6 +57,54 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
||||
|
||||
#define INTERNAL_BUF_NUM 5
|
||||
|
||||
#if SOC_AHB_GDMA_VERSION == 1
|
||||
#define ADC_GDMA_HOST 0
|
||||
#define ADC_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#define ADC_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#define adc_dma_start(adc_dma, addr) gdma_start(s_adc_digi_ctx->rx_dma_channel, (intptr_t)addr)
|
||||
#define adc_dma_stop(adc_dma) gdma_stop(s_adc_digi_ctx->rx_dma_channel)
|
||||
#define adc_dma_reset(adc_dma) gdma_reset(s_adc_digi_ctx->rx_dma_channel)
|
||||
#define adc_dma_clear_intr(adc_dma)
|
||||
#define adc_dma_enable_intr(adc_dma)
|
||||
#define adc_dma_disable_intr(adc_dma)
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel); \
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel); \
|
||||
} while (0)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_DMA_SPI_HOST SPI3_HOST
|
||||
#define ADC_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF
|
||||
#define adc_dma_start(adc_dma, addr) spi_dma_ll_rx_start(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id, (lldesc_t *)addr)
|
||||
#define adc_dma_stop(adc_dma) spi_dma_ll_rx_stop(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
#define adc_dma_reset(adc_dma) spi_dma_ll_rx_reset(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
#define adc_dma_clear_intr(adc_dma) spi_ll_clear_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK)
|
||||
#define adc_dma_enable_intr(adc_dma) spi_ll_enable_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_disable_intr(adc_dma) spi_ll_disable_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl); \
|
||||
spicommon_dma_chan_free(s_adc_digi_ctx->spi_dma_ctx); \
|
||||
spicommon_periph_free(ADC_DMA_SPI_HOST); \
|
||||
} while (0)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_DMA_I2S_HOST I2S_NUM_0
|
||||
#define ADC_DMA_INTR_MASK BIT(9)
|
||||
#define adc_dma_start(adc_dma, addr) do { \
|
||||
i2s_ll_enable_dma(s_adc_digi_ctx->adc_i2s_dev, true); \
|
||||
i2s_ll_rx_start_link(s_adc_digi_ctx->adc_i2s_dev, (uint32_t)addr); \
|
||||
} while (0)
|
||||
#define adc_dma_stop(adc_dma) i2s_ll_rx_stop_link(s_adc_digi_ctx->adc_i2s_dev);
|
||||
#define adc_dma_reset(adc_dma) i2s_ll_rx_reset_dma(s_adc_digi_ctx->adc_i2s_dev);
|
||||
#define adc_dma_clear_intr(adc_dma) i2s_ll_clear_intr_status(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_enable_intr(adc_dma) i2s_ll_enable_intr(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK, true);
|
||||
#define adc_dma_disable_intr(adc_dma) i2s_ll_enable_intr(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK, false);
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl); \
|
||||
i2s_platform_release_occupation(ADC_DMA_I2S_HOST); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
@ -69,9 +117,11 @@ typedef struct adc_digi_context_t {
|
||||
spi_host_device_t spi_host; //ADC uses this SPI DMA
|
||||
spi_dma_ctx_t *spi_dma_ctx; //spi_dma context
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
spi_dev_t *adc_spi_dev ;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
i2s_port_t i2s_host; //ADC uses this I2S DMA
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
i2s_dev_t *adc_i2s_dev;
|
||||
#endif
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
@ -163,17 +213,8 @@ esp_err_t adc_digi_deinitialize(void)
|
||||
free(s_adc_digi_ctx->rx_dma_buf);
|
||||
free(s_adc_digi_ctx->hal.rx_desc);
|
||||
free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern);
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl);
|
||||
spicommon_dma_chan_free(s_adc_digi_ctx->spi_dma_ctx);
|
||||
spicommon_periph_free(s_adc_digi_ctx->spi_host);
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl);
|
||||
i2s_platform_release_occupation(s_adc_digi_ctx->i2s_host);
|
||||
#endif
|
||||
|
||||
adc_dma_deinit(s_adc_digi_ctx);
|
||||
free(s_adc_digi_ctx);
|
||||
s_adc_digi_ctx = NULL;
|
||||
|
||||
@ -266,57 +307,46 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
};
|
||||
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
|
||||
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
bool spi_success = false;
|
||||
uint32_t dma_chan = 0;
|
||||
|
||||
spi_success = spicommon_periph_claim(SPI3_HOST, "adc");
|
||||
ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &s_adc_digi_ctx->spi_dma_ctx);
|
||||
if (ret == ESP_OK) {
|
||||
s_adc_digi_ctx->spi_host = SPI3_HOST;
|
||||
}
|
||||
if (!spi_success || (s_adc_digi_ctx->spi_host != SPI3_HOST)) {
|
||||
spi_success = spicommon_periph_claim(ADC_DMA_SPI_HOST, "adc");
|
||||
ret = spicommon_dma_chan_alloc(ADC_DMA_SPI_HOST, SPI_DMA_CH_AUTO, &(s_adc_digi_ctx->spi_dma_ctx));
|
||||
if (ret != ESP_OK || spi_success != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (!spi_success || (s_adc_digi_ctx->spi_host != ADC_DMA_SPI_HOST)) {
|
||||
goto cleanup;
|
||||
}
|
||||
dma_chan = s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id;
|
||||
|
||||
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(s_adc_digi_ctx->spi_host), 0, adc_dma_intr_handler,
|
||||
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(ADC_DMA_SPI_HOST), 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s_adc_digi_ctx->adc_spi_dev = SPI_LL_GET_HW(ADC_DMA_SPI_HOST);
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
uint32_t dma_chan = 0;
|
||||
ret = i2s_platform_acquire_occupation(I2S_NUM_0, "adc");
|
||||
ret = i2s_platform_acquire_occupation(ADC_DMA_I2S_HOST, "adc");
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s_adc_digi_ctx->i2s_host = I2S_NUM_0;
|
||||
ret = esp_intr_alloc(i2s_periph_signal[s_adc_digi_ctx->i2s_host].irq, 0, adc_dma_intr_handler,
|
||||
|
||||
ret = esp_intr_alloc(i2s_periph_signal[ADC_DMA_I2S_HOST].irq, 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
s_adc_digi_ctx->adc_i2s_dev = I2S_LL_GET_HW(ADC_DMA_I2S_HOST);
|
||||
#endif
|
||||
|
||||
adc_hal_dma_config_t config = {
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
.dev = (void *)GDMA_LL_GET_HW(0),
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
.dev = (void *)SPI_LL_GET_HW(s_adc_digi_ctx->spi_host),
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
.dev = (void *)I2S_LL_GET_HW(s_adc_digi_ctx->i2s_host),
|
||||
#endif
|
||||
.eof_desc_num = INTERNAL_BUF_NUM,
|
||||
.eof_step = dma_desc_num_per_frame,
|
||||
.dma_chan = dma_chan,
|
||||
.eof_num = init_config->conv_num_each_intr / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
|
||||
};
|
||||
adc_hal_dma_ctx_config(&s_adc_digi_ctx->hal, &config);
|
||||
@ -348,16 +378,24 @@ static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
adc_digi_context_t *ctx = (adc_digi_context_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
bool conversion_finish = adc_hal_check_event(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
bool conversion_finish = spi_ll_get_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
if (conversion_finish) {
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
|
||||
intptr_t desc_addr = adc_hal_get_desc_addr(&ctx->hal);
|
||||
|
||||
spi_ll_clear_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
intptr_t desc_addr = spi_dma_ll_get_in_suc_eof_desc_addr(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
ctx->rx_eof_desc_addr = desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
bool conversion_finish = i2s_ll_get_intr_status(s_adc_digi_ctx->adc_i2s_dev) & ADC_DMA_INTR_MASK;
|
||||
if (conversion_finish) {
|
||||
i2s_ll_clear_intr_status(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
uint32_t desc_addr;
|
||||
i2s_ll_rx_get_eof_des_addr(s_adc_digi_ctx->adc_i2s_dev, &desc_addr);
|
||||
ctx->rx_eof_desc_addr = (intptr_t)desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
#endif
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
@ -433,8 +471,16 @@ esp_err_t adc_digi_start(void)
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg);
|
||||
|
||||
//start conversion
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
adc_dma_stop(s_adc_digi_ctx);
|
||||
adc_hal_digi_connect(false);
|
||||
|
||||
adc_dma_reset(s_adc_digi_ctx);
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_dma_link(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
|
||||
adc_dma_start(s_adc_digi_ctx, s_adc_digi_ctx->hal.rx_desc);
|
||||
adc_hal_digi_connect(true);
|
||||
adc_hal_digi_enable(true);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -447,14 +493,12 @@ esp_err_t adc_digi_stop(void)
|
||||
}
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||
adc_dma_stop(s_adc_digi_ctx);
|
||||
adc_hal_digi_enable(false);
|
||||
adc_hal_digi_connect(false);
|
||||
|
||||
adc_hal_digi_deinit();
|
||||
|
||||
adc_hal_digi_deinit(&s_adc_digi_ctx->hal);
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
|
@ -19,6 +19,13 @@ if(CONFIG_SOC_ADC_DMA_SUPPORTED)
|
||||
if(CONFIG_SOC_ADC_MONITOR_SUPPORTED)
|
||||
list(APPEND srcs "adc_monitor.c")
|
||||
endif()
|
||||
if(CONFIG_SOC_GDMA_SUPPORTED)
|
||||
list(APPEND srcs "gdma/adc_dma.c")
|
||||
elseif(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs "esp32/adc_dma.c")
|
||||
elseif(${target} STREQUAL "esp32s2")
|
||||
list(APPEND srcs "esp32s2/adc_dma.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED)
|
||||
|
@ -35,18 +35,8 @@
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "adc_continuous_internal.h"
|
||||
//For DMA
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "esp_private/gdma.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "hal/spi_types.h"
|
||||
#include "esp_private/spi_common_internal.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "hal/i2s_types.h"
|
||||
#include "driver/i2s_types.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "esp_private/i2s_platform.h"
|
||||
#endif
|
||||
#include "esp_private/adc_dma.h"
|
||||
#include "adc_dma_internal.h"
|
||||
|
||||
static const char *ADC_TAG = "adc_continuous";
|
||||
|
||||
@ -61,14 +51,66 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
||||
/*---------------------------------------------------------------
|
||||
ADC Continuous Read Mode (via DMA)
|
||||
---------------------------------------------------------------*/
|
||||
//Function to address transaction
|
||||
static bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx);
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||
#else
|
||||
static void adc_dma_intr_handler(void *arg);
|
||||
#endif
|
||||
static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx)
|
||||
{
|
||||
BaseType_t taskAwoken = 0;
|
||||
bool need_yield = false;
|
||||
BaseType_t ret;
|
||||
adc_hal_dma_desc_status_t status = false;
|
||||
uint8_t *finished_buffer = NULL;
|
||||
uint32_t finished_size = 0;
|
||||
|
||||
while (1) {
|
||||
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &finished_buffer, &finished_size);
|
||||
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
|
||||
need_yield |= (taskAwoken == pdTRUE);
|
||||
|
||||
if (adc_digi_ctx->cbs.on_conv_done) {
|
||||
adc_continuous_evt_data_t edata = {
|
||||
.conv_frame_buffer = finished_buffer,
|
||||
.size = finished_size,
|
||||
};
|
||||
if (adc_digi_ctx->cbs.on_conv_done(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == pdFALSE) {
|
||||
if (adc_digi_ctx->flags.flush_pool) {
|
||||
size_t actual_size = 0;
|
||||
uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size);
|
||||
/**
|
||||
* Replace by ringbuffer reset API when this API is ready.
|
||||
* Now we do mannual reset.
|
||||
* For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data,
|
||||
* as this only happens when the ringbuffer size is small, new data will be filled in soon.
|
||||
*/
|
||||
if (old_data) {
|
||||
vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken);
|
||||
xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
|
||||
if (taskAwoken == pdTRUE) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ringbuffer overflow happens before
|
||||
if (adc_digi_ctx->cbs.on_pool_ovf) {
|
||||
adc_continuous_evt_data_t edata = {};
|
||||
if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
static int8_t adc_digi_get_io_num(adc_unit_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
@ -165,80 +207,16 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ret = gdma_new_channel(&rx_alloc_config, &adc_ctx->rx_dma_channel);
|
||||
ret = adc_dma_init(&adc_ctx->adc_dma);
|
||||
adc_ctx->adc_intr_func = adc_dma_intr;
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
gdma_connect(adc_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||
|
||||
gdma_strategy_config_t strategy_config = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(adc_ctx->rx_dma_channel, &strategy_config);
|
||||
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||
};
|
||||
gdma_register_rx_event_callbacks(adc_ctx->rx_dma_channel, &cbs, adc_ctx);
|
||||
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(adc_ctx->rx_dma_channel, &dma_chan);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
bool spi_success = false;
|
||||
uint32_t dma_chan = 0;
|
||||
|
||||
spi_success = spicommon_periph_claim(SPI3_HOST, "adc");
|
||||
ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &adc_ctx->spi_dma_ctx);
|
||||
if (ret == ESP_OK) {
|
||||
adc_ctx->spi_host = SPI3_HOST;
|
||||
}
|
||||
if (!spi_success || (adc_ctx->spi_host != SPI3_HOST)) {
|
||||
goto cleanup;
|
||||
}
|
||||
dma_chan = adc_ctx->spi_dma_ctx->rx_dma_chan.chan_id;
|
||||
|
||||
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(adc_ctx->spi_host), ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
|
||||
(void *)adc_ctx, &adc_ctx->dma_intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
uint32_t dma_chan = 0;
|
||||
ret = i2s_platform_acquire_occupation(I2S_NUM_0, "adc");
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
adc_ctx->i2s_host = I2S_NUM_0;
|
||||
ret = esp_intr_alloc(i2s_periph_signal[adc_ctx->i2s_host].irq, ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
|
||||
(void *)adc_ctx, &adc_ctx->dma_intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
ret = adc_dma_intr_event_init(adc_ctx);
|
||||
|
||||
adc_hal_dma_config_t config = {
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
.dev = (void *)GDMA_LL_GET_HW(0),
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
.dev = (void *)SPI_LL_GET_HW(adc_ctx->spi_host),
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
.dev = (void *)I2S_LL_GET_HW(adc_ctx->i2s_host),
|
||||
#endif
|
||||
.eof_desc_num = INTERNAL_BUF_NUM,
|
||||
.eof_step = dma_desc_num_per_frame,
|
||||
.dma_chan = dma_chan,
|
||||
.eof_num = hdl_config->conv_frame_size / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
|
||||
};
|
||||
adc_hal_dma_ctx_config(&adc_ctx->hal, &config);
|
||||
@ -261,97 +239,6 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)user_data;
|
||||
ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return s_adc_dma_intr(user_data);
|
||||
}
|
||||
|
||||
#else
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
{
|
||||
adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
bool conversion_finish = adc_hal_check_event(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
if (conversion_finish) {
|
||||
adc_hal_digi_clr_intr(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
|
||||
intptr_t desc_addr = adc_hal_get_desc_addr(&ctx->hal);
|
||||
|
||||
ctx->rx_eof_desc_addr = desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx)
|
||||
{
|
||||
BaseType_t taskAwoken = 0;
|
||||
bool need_yield = false;
|
||||
BaseType_t ret;
|
||||
adc_hal_dma_desc_status_t status = false;
|
||||
uint8_t *finished_buffer = NULL;
|
||||
uint32_t finished_size = 0;
|
||||
|
||||
while (1) {
|
||||
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &finished_buffer, &finished_size);
|
||||
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
|
||||
need_yield |= (taskAwoken == pdTRUE);
|
||||
|
||||
if (adc_digi_ctx->cbs.on_conv_done) {
|
||||
adc_continuous_evt_data_t edata = {
|
||||
.conv_frame_buffer = finished_buffer,
|
||||
.size = finished_size,
|
||||
};
|
||||
if (adc_digi_ctx->cbs.on_conv_done(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == pdFALSE) {
|
||||
if (adc_digi_ctx->flags.flush_pool) {
|
||||
size_t actual_size = 0;
|
||||
uint8_t *old_data = xRingbufferReceiveUpToFromISR(adc_digi_ctx->ringbuf_hdl, &actual_size, adc_digi_ctx->ringbuf_size);
|
||||
/**
|
||||
* Replace by ringbuffer reset API when this API is ready.
|
||||
* Now we do mannual reset.
|
||||
* For old_data == NULL condition (equals to the future ringbuffer reset fail condition), we don't care this time data,
|
||||
* as this only happens when the ringbuffer size is small, new data will be filled in soon.
|
||||
*/
|
||||
if (old_data) {
|
||||
vRingbufferReturnItemFromISR(adc_digi_ctx->ringbuf_hdl, old_data, &taskAwoken);
|
||||
xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
|
||||
if (taskAwoken == pdTRUE) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ringbuffer overflow happens before
|
||||
if (adc_digi_ctx->cbs.on_pool_ovf) {
|
||||
adc_continuous_evt_data_t edata = {};
|
||||
if (adc_digi_ctx->cbs.on_pool_ovf(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
|
||||
need_yield |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
|
||||
@ -398,10 +285,20 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
|
||||
}
|
||||
|
||||
adc_hal_digi_init(&handle->hal);
|
||||
adc_hal_digi_controller_config(&handle->hal, &handle->hal_digi_ctrlr_cfg);
|
||||
|
||||
//start conversion
|
||||
adc_hal_digi_start(&handle->hal, handle->rx_dma_buf);
|
||||
adc_hal_digi_controller_config(&handle->hal, &handle->hal_digi_ctrlr_cfg);
|
||||
adc_hal_digi_enable(false);
|
||||
|
||||
adc_dma_stop(handle->adc_dma);
|
||||
adc_hal_digi_connect(false);
|
||||
|
||||
adc_dma_reset(handle->adc_dma);
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_dma_link(&handle->hal, handle->rx_dma_buf);
|
||||
|
||||
adc_dma_start(handle->adc_dma, handle->hal.rx_desc);
|
||||
adc_hal_digi_connect(true);
|
||||
adc_hal_digi_enable(true);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -412,19 +309,16 @@ esp_err_t adc_continuous_stop(adc_continuous_handle_t handle)
|
||||
ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_STARTED, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver is already stopped");
|
||||
|
||||
handle->fsm = ADC_FSM_INIT;
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&handle->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&handle->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&handle->hal);
|
||||
|
||||
adc_dma_stop(handle->adc_dma);
|
||||
adc_hal_digi_enable(false);
|
||||
adc_hal_digi_connect(false);
|
||||
#if ADC_LL_WORKAROUND_CLEAR_EOF_COUNTER
|
||||
periph_module_reset(PERIPH_SARADC_MODULE);
|
||||
adc_hal_digi_clr_eof();
|
||||
#endif
|
||||
|
||||
adc_hal_digi_deinit(&handle->hal);
|
||||
adc_hal_digi_deinit();
|
||||
|
||||
if (handle->use_adc2) {
|
||||
adc_lock_release(ADC_UNIT_2);
|
||||
@ -492,17 +386,7 @@ esp_err_t adc_continuous_deinit(adc_continuous_handle_t handle)
|
||||
free(handle->rx_dma_buf);
|
||||
free(handle->hal.rx_desc);
|
||||
free(handle->hal_digi_ctrlr_cfg.adc_pattern);
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_disconnect(handle->rx_dma_channel);
|
||||
gdma_del_channel(handle->rx_dma_channel);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
esp_intr_free(handle->dma_intr_hdl);
|
||||
spicommon_dma_chan_free(handle->spi_dma_ctx);
|
||||
spicommon_periph_free(handle->spi_host);
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_intr_free(handle->dma_intr_hdl);
|
||||
i2s_platform_release_occupation(handle->i2s_host);
|
||||
#endif
|
||||
adc_dma_deinit(handle->adc_dma);
|
||||
free(handle);
|
||||
handle = NULL;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
#include "esp_adc/adc_filter.h"
|
||||
#include "esp_adc/adc_monitor.h"
|
||||
#include "adc_dma_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -47,6 +48,7 @@ typedef enum {
|
||||
typedef struct adc_iir_filter_t adc_iir_filter_t;
|
||||
typedef struct adc_monitor_t adc_monitor_t;
|
||||
typedef struct adc_continuous_ctx_t adc_continuous_ctx_t;
|
||||
typedef bool (*adc_dma_intr_func_t)(adc_continuous_ctx_t *adc_digi_ctx);
|
||||
|
||||
/**
|
||||
* @brief ADC iir filter context
|
||||
@ -74,15 +76,6 @@ struct adc_monitor_t {
|
||||
struct adc_continuous_ctx_t {
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_hal_dma_ctx_t hal; //hal context
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
spi_host_device_t spi_host; //ADC uses this SPI DMA
|
||||
spi_dma_ctx_t *spi_dma_ctx; //spi_dma context
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
i2s_port_t i2s_host; //ADC uses this I2S DMA
|
||||
#endif
|
||||
intr_handle_t dma_intr_hdl; //DMA Interrupt handler
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
void* ringbuf_storage; //Ringbuffer storage buffer
|
||||
void* ringbuf_struct; //Ringbuffer structure buffer
|
||||
@ -106,6 +99,8 @@ struct adc_continuous_ctx_t {
|
||||
#if SOC_ADC_MONITOR_SUPPORTED
|
||||
adc_monitor_t *adc_monitor[SOC_ADC_DIGI_MONITOR_NUM]; // adc monitor context
|
||||
#endif
|
||||
adc_dma_t adc_dma;
|
||||
adc_dma_intr_func_t adc_intr_func;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
37
components/esp_adc/adc_dma_internal.h
Normal file
37
components/esp_adc/adc_dma_internal.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "adc_continuous_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC DMA context
|
||||
*/
|
||||
typedef struct {
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_channel_handle_t gdma_chan;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//On ESP32S2, there is no gdma, so use SPI DMA to transmit data
|
||||
spi_dma_ctx_t *spi_dma_ctx;
|
||||
spi_dev_t *adc_spi_dev;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
//On ESP32, there is no gdma, so use I2S DMA to transmit data
|
||||
i2s_dev_t *adc_i2s_dev;
|
||||
#endif
|
||||
intr_handle_t dma_intr_hdl;
|
||||
} adc_dma_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
91
components/esp_adc/esp32/adc_dma.c
Normal file
91
components/esp_adc/esp32/adc_dma.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is a target specific for DAC DMA peripheral
|
||||
* Target: ESP32
|
||||
* DAC DMA peripheral (data source): I2S0 (i.e. use I2S DMA to transmit data)
|
||||
* DAC DMA interrupt source: I2S0
|
||||
* DAC digital controller clock source: I2S ws signal (root clock: D2PLL or APLL)
|
||||
*/
|
||||
|
||||
#include "hal/i2s_types.h"
|
||||
#include "driver/i2s_types.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "esp_private/i2s_platform.h"
|
||||
#include "esp_private/adc_dma.h"
|
||||
#include "hal/i2s_ll.h"
|
||||
|
||||
#define ADC_DMA_I2S_HOST ADC_HAL_DMA_I2S_HOST
|
||||
#define ADC_DMA_INTR_MASK BIT(9)
|
||||
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
{
|
||||
adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
bool conversion_finish = i2s_ll_get_intr_status(ctx->adc_dma.adc_i2s_dev) & ADC_DMA_INTR_MASK;
|
||||
if (conversion_finish) {
|
||||
i2s_ll_clear_intr_status(ctx->adc_dma.adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
uint32_t desc_addr;
|
||||
i2s_ll_rx_get_eof_des_addr(ctx->adc_dma.adc_i2s_dev, &desc_addr);
|
||||
ctx->rx_eof_desc_addr = (intptr_t)desc_addr;
|
||||
need_yield = ctx->adc_intr_func(ctx);
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_intr_event_init(adc_continuous_ctx_t *adc_ctx)
|
||||
{
|
||||
return (esp_intr_alloc(i2s_periph_signal[ADC_DMA_I2S_HOST].irq, ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
|
||||
(void *)adc_ctx, &adc_ctx->adc_dma.dma_intr_hdl));
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_init(adc_dma_t *adc_dma)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
ret = i2s_platform_acquire_occupation(ADC_DMA_I2S_HOST, "adc");
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
adc_dma->adc_i2s_dev = I2S_LL_GET_HW(ADC_DMA_I2S_HOST);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_deinit(adc_dma_t adc_dma)
|
||||
{
|
||||
esp_intr_free(adc_dma.dma_intr_hdl);
|
||||
i2s_platform_release_occupation(ADC_DMA_I2S_HOST);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_start(adc_dma_t adc_dma, dma_descriptor_t *addr)
|
||||
{
|
||||
i2s_ll_clear_intr_status(adc_dma.adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
i2s_ll_enable_intr(adc_dma.adc_i2s_dev, ADC_DMA_INTR_MASK, true);
|
||||
|
||||
i2s_ll_enable_dma(adc_dma.adc_i2s_dev, true);
|
||||
i2s_ll_rx_start_link(adc_dma.adc_i2s_dev, (uint32_t)addr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_stop(adc_dma_t adc_dma)
|
||||
{
|
||||
i2s_ll_enable_intr(adc_dma.adc_i2s_dev, ADC_DMA_INTR_MASK, false);
|
||||
i2s_ll_clear_intr_status(adc_dma.adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
i2s_ll_rx_stop_link(adc_dma.adc_i2s_dev);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_reset(adc_dma_t adc_dma)
|
||||
{
|
||||
i2s_ll_rx_reset_dma(adc_dma.adc_i2s_dev);
|
||||
return ESP_OK;
|
||||
}
|
93
components/esp_adc/esp32s2/adc_dma.c
Normal file
93
components/esp_adc/esp32s2/adc_dma.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is a target specific for DAC DMA peripheral
|
||||
* Target: ESP32-S2
|
||||
* DAC DMA peripheral (data source): SPI3 (i.e. use SPI DMA to transmit data)
|
||||
* DAC DMA interrupt source: SPI3
|
||||
* DAC digital controller clock source: DIG_SARADC_CLK (root clock: APB or APLL)
|
||||
*/
|
||||
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_ll.h"
|
||||
#include "esp_private/spi_common_internal.h"
|
||||
#include "esp_private/adc_dma.h"
|
||||
|
||||
#define ADC_DMA_SPI_HOST SPI3_HOST
|
||||
#define ADC_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF
|
||||
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
{
|
||||
adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
bool conversion_finish = spi_ll_get_intr(ctx->adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
if (conversion_finish) {
|
||||
spi_ll_clear_intr(ctx->adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
intptr_t desc_addr = spi_dma_ll_get_in_suc_eof_desc_addr(ctx->adc_dma.adc_spi_dev, ctx->adc_dma.spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
ctx->rx_eof_desc_addr = desc_addr;
|
||||
need_yield = ctx->adc_intr_func(ctx);
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_intr_event_init(adc_continuous_ctx_t *adc_ctx)
|
||||
{
|
||||
return (esp_intr_alloc(spicommon_irqdma_source_for_host(ADC_DMA_SPI_HOST), ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
|
||||
(void *)adc_ctx, &adc_ctx->adc_dma.dma_intr_hdl));
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_init(adc_dma_t *adc_dma)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
bool spi_success = false;
|
||||
spi_success = spicommon_periph_claim(ADC_DMA_SPI_HOST, "adc");
|
||||
if (spi_success != true) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &(adc_dma->spi_dma_ctx));
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
adc_dma->adc_spi_dev = SPI_LL_GET_HW(ADC_DMA_SPI_HOST);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_deinit(adc_dma_t adc_dma)
|
||||
{
|
||||
esp_intr_free(adc_dma.dma_intr_hdl);
|
||||
spicommon_dma_chan_free(adc_dma.spi_dma_ctx);
|
||||
spicommon_periph_free(ADC_DMA_SPI_HOST);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_start(adc_dma_t adc_dma, dma_descriptor_t *addr)
|
||||
{
|
||||
spi_ll_clear_intr(adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
spi_ll_enable_intr(adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
spi_dma_ll_rx_start(adc_dma.adc_spi_dev, adc_dma.spi_dma_ctx->rx_dma_chan.chan_id, (lldesc_t *)addr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_stop(adc_dma_t adc_dma)
|
||||
{
|
||||
spi_ll_disable_intr(adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
spi_ll_clear_intr(adc_dma.adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
spi_dma_ll_rx_stop(adc_dma.adc_spi_dev, adc_dma.spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_reset(adc_dma_t adc_dma)
|
||||
{
|
||||
spi_dma_ll_rx_reset(adc_dma.adc_spi_dev, adc_dma.spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
return ESP_OK;
|
||||
}
|
69
components/esp_adc/gdma/adc_dma.c
Normal file
69
components/esp_adc/gdma/adc_dma.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_private/adc_dma.h"
|
||||
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)user_data;
|
||||
ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return ctx->adc_intr_func(user_data);
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_intr_event_init(adc_continuous_ctx_t *adc_ctx)
|
||||
{
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||
};
|
||||
gdma_register_rx_event_callbacks(adc_ctx->adc_dma.gdma_chan, &cbs, adc_ctx);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_init(adc_dma_t *adc_dma)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ret = gdma_new_channel(&rx_alloc_config, &(adc_dma->gdma_chan));
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
gdma_connect(adc_dma->gdma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||
|
||||
gdma_strategy_config_t strategy_config = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(adc_dma->gdma_chan, &strategy_config);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_deinit(adc_dma_t adc_dma)
|
||||
{
|
||||
gdma_disconnect(adc_dma.gdma_chan);
|
||||
gdma_del_channel(adc_dma.gdma_chan);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_start(adc_dma_t adc_dma, dma_descriptor_t *addr)
|
||||
{
|
||||
return gdma_start(adc_dma.gdma_chan, (intptr_t)addr);
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_stop(adc_dma_t adc_dma)
|
||||
{
|
||||
return gdma_stop(adc_dma.gdma_chan);
|
||||
}
|
||||
|
||||
esp_err_t adc_dma_reset(adc_dma_t adc_dma)
|
||||
{
|
||||
return gdma_reset(adc_dma.gdma_chan);
|
||||
}
|
81
components/esp_adc/include/esp_private/adc_dma.h
Normal file
81
components/esp_adc/include/esp_private/adc_dma.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "../adc_continuous_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA interrupt event
|
||||
*
|
||||
* @param[in] adc_ctx ADC continuous mode driver handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_intr_event_init(adc_continuous_ctx_t *adc_ctx);
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA on ADC continuous mode
|
||||
*
|
||||
* @param[in] adc_dma ADC DMA context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_init(adc_dma_t *adc_dma);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize DMA on ADC continuous mode
|
||||
*
|
||||
* @param[in] adc_dma ADC DMA context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_deinit(adc_dma_t adc_dma);
|
||||
|
||||
/**
|
||||
* @brief Start DMA on ADC continuous mode
|
||||
*
|
||||
* @param[in] adc_dma ADC DMA context
|
||||
* @param[in] addr ADC DMA descriptor
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_start(adc_dma_t adc_dma, dma_descriptor_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Stop DMA on ADC continuous mode
|
||||
*
|
||||
* @param[in] adc_dma ADC DMA context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_stop(adc_dma_t adc_dma);
|
||||
|
||||
/**
|
||||
* @brief Reset DMA on ADC continuous mode
|
||||
*
|
||||
* @param[in] adc_dma ADC DMA context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t adc_dma_reset(adc_dma_t adc_dma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -19,7 +19,3 @@ entries:
|
||||
adc_hal_common: adc_hal_calibration_init (noflash)
|
||||
if ADC_CONTINUOUS_ISR_IRAM_SAFE = y || GDMA_ISR_IRAM_SAFE = y:
|
||||
adc_hal: adc_hal_get_reading_result (noflash)
|
||||
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y:
|
||||
adc_hal: adc_hal_check_event (noflash)
|
||||
adc_hal: adc_hal_digi_clr_intr (noflash)
|
||||
adc_hal: adc_hal_get_desc_addr (noflash)
|
||||
|
@ -16,70 +16,6 @@
|
||||
#include "hal/i2s_hal.h"
|
||||
#include "hal/i2s_types.h"
|
||||
#include "soc/i2s_struct.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
#include "hal/spi_ll.h"
|
||||
#include "soc/spi_struct.h"
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Define all ADC DMA required operations here
|
||||
---------------------------------------------------------------*/
|
||||
#if SOC_AHB_GDMA_VERSION == 1
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) gdma_ll_rx_clear_interrupt_status(dev, chan, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, true)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, false)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) gdma_ll_rx_reset_channel(dev, chan)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) gdma_ll_rx_stop(dev, chan)
|
||||
#define adc_dma_ll_rx_start(dev, chan, addr) do { \
|
||||
gdma_ll_rx_set_desc_addr(dev, chan, (uint32_t)addr); \
|
||||
gdma_ll_rx_start(dev, chan); \
|
||||
} while (0)
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num)
|
||||
#define adc_ll_digi_reset(dev) adc_ll_digi_reset()
|
||||
#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable()
|
||||
#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable()
|
||||
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define adc_dma_ll_rx_get_intr(dev, mask) spi_ll_get_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) spi_ll_clear_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) spi_ll_enable_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) spi_ll_disable_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) spi_dma_ll_rx_reset(dev, chan)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) spi_dma_ll_rx_stop(dev, chan)
|
||||
#define adc_dma_ll_rx_start(dev, chan, addr) spi_dma_ll_rx_start(dev, chan, addr)
|
||||
#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) spi_dma_ll_get_in_suc_eof_desc_addr(dev, chan)
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num)
|
||||
#define adc_ll_digi_reset(dev) adc_ll_digi_reset()
|
||||
#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable()
|
||||
#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable()
|
||||
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
#else //CONFIG_IDF_TARGET_ESP32
|
||||
#define adc_dma_ll_rx_get_intr(dev, mask) ({i2s_ll_get_intr_status(dev) & mask;})
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) i2s_ll_clear_intr_status(dev, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val |= mask;} while (0)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val &= ~mask;} while (0)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) i2s_ll_rx_reset_dma(dev)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) i2s_ll_rx_stop_link(dev)
|
||||
#define adc_dma_ll_rx_start(dev, chan, address) do { \
|
||||
((i2s_dev_t *)(dev))->in_link.addr = (uint32_t)(address); \
|
||||
i2s_ll_enable_dma(dev, 1); \
|
||||
((i2s_dev_t *)(dev))->in_link.start = 1; \
|
||||
} while (0)
|
||||
#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) ({uint32_t addr; i2s_ll_rx_get_eof_des_addr(dev, &addr); addr;})
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) do {((i2s_dev_t *)(dev))->rx_eof_num = num;} while (0)
|
||||
#define adc_ll_digi_reset(dev) do { \
|
||||
i2s_ll_rx_reset(dev); \
|
||||
i2s_ll_rx_reset_fifo(dev); \
|
||||
} while (0)
|
||||
#define adc_ll_digi_trigger_enable(dev) i2s_ll_rx_start(dev)
|
||||
#define adc_ll_digi_trigger_disable(dev) i2s_ll_rx_stop(dev)
|
||||
#define adc_ll_digi_dma_enable() adc_ll_digi_set_data_source(1) //Will this influence I2S0
|
||||
#define adc_ll_digi_dma_disable() adc_ll_digi_set_data_source(0)
|
||||
|
||||
//ESP32 ADC uses the DMA through I2S. The I2S needs to be configured.
|
||||
#define I2S_BASE_CLK (160 * 1000 * 1000)
|
||||
@ -88,17 +24,25 @@
|
||||
#define ADC_LL_CLKM_DIV_B_DEFAULT 0
|
||||
#define ADC_LL_CLKM_DIV_A_DEFAULT 1
|
||||
|
||||
i2s_dev_t *adc_hal_i2s_dev = I2S_LL_GET_HW(ADC_HAL_DMA_I2S_HOST);
|
||||
|
||||
#define adc_ll_digi_dma_set_eof_num(num) i2s_ll_rx_set_eof_num(adc_hal_i2s_dev, (num) * 4)
|
||||
#define adc_ll_digi_reset() do { \
|
||||
i2s_ll_rx_reset(adc_hal_i2s_dev); \
|
||||
i2s_ll_rx_reset_fifo(adc_hal_i2s_dev); \
|
||||
} while (0)
|
||||
#define adc_ll_digi_trigger_enable() i2s_ll_rx_start(adc_hal_i2s_dev)
|
||||
#define adc_ll_digi_trigger_disable() i2s_ll_rx_stop(adc_hal_i2s_dev)
|
||||
#define adc_ll_digi_dma_enable() adc_ll_digi_set_data_source(1) //Will this influence I2S0
|
||||
#define adc_ll_digi_dma_disable() adc_ll_digi_set_data_source(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void adc_hal_dma_ctx_config(adc_hal_dma_ctx_t *hal, const adc_hal_dma_config_t *config)
|
||||
{
|
||||
hal->desc_dummy_head.next = hal->rx_desc;
|
||||
hal->dev = config->dev;
|
||||
hal->eof_desc_num = config->eof_desc_num;
|
||||
hal->eof_step = config->eof_step;
|
||||
hal->dma_chan = config->dma_chan;
|
||||
hal->eof_num = config->eof_num;
|
||||
}
|
||||
|
||||
@ -113,30 +57,28 @@ void adc_hal_digi_init(adc_hal_dma_ctx_t *hal)
|
||||
adc_ll_digi_output_invert(ADC_UNIT_2, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
|
||||
adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT);
|
||||
|
||||
adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK);
|
||||
adc_dma_ll_rx_enable_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK);
|
||||
adc_ll_digi_dma_set_eof_num(hal->dev, hal->eof_num);
|
||||
adc_ll_digi_dma_set_eof_num(hal->eof_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
i2s_ll_rx_set_sample_bit(hal->dev, SAMPLE_BITS, SAMPLE_BITS);
|
||||
i2s_ll_rx_enable_mono_mode(hal->dev, 1);
|
||||
i2s_ll_rx_force_enable_fifo_mod(hal->dev, 1);
|
||||
i2s_ll_rx_enable_right_first(hal->dev, false);
|
||||
i2s_ll_rx_enable_msb_shift(hal->dev, false);
|
||||
i2s_ll_rx_set_ws_width(hal->dev, 16);
|
||||
i2s_ll_rx_select_std_slot(hal->dev, I2S_STD_SLOT_LEFT, false);
|
||||
i2s_ll_enable_builtin_adc_dac(hal->dev, 1);
|
||||
i2s_ll_rx_set_sample_bit(adc_hal_i2s_dev, SAMPLE_BITS, SAMPLE_BITS);
|
||||
i2s_ll_rx_enable_mono_mode(adc_hal_i2s_dev, 1);
|
||||
i2s_ll_rx_force_enable_fifo_mod(adc_hal_i2s_dev, 1);
|
||||
i2s_ll_rx_enable_right_first(adc_hal_i2s_dev, false);
|
||||
i2s_ll_rx_enable_msb_shift(adc_hal_i2s_dev, false);
|
||||
i2s_ll_rx_set_ws_width(adc_hal_i2s_dev, 16);
|
||||
i2s_ll_rx_select_std_slot(adc_hal_i2s_dev, I2S_STD_SLOT_LEFT, false);
|
||||
i2s_ll_enable_builtin_adc_dac(adc_hal_i2s_dev, 1);
|
||||
#endif
|
||||
|
||||
adc_oneshot_ll_disable_all_unit();
|
||||
}
|
||||
|
||||
void adc_hal_digi_deinit(adc_hal_dma_ctx_t *hal)
|
||||
void adc_hal_digi_deinit()
|
||||
{
|
||||
adc_ll_digi_trigger_disable(hal->dev);
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
|
||||
adc_ll_digi_reset(hal->dev);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
@ -180,14 +122,14 @@ static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, adc_continuo
|
||||
adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT);
|
||||
adc_ll_digi_clk_sel(clk_src);
|
||||
#else
|
||||
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_SRC_DEFAULT); /*!< Clock from PLL_D2_CLK(160M)*/
|
||||
i2s_ll_rx_clk_set_src(adc_hal_i2s_dev, I2S_CLK_SRC_DEFAULT); /*!< Clock from PLL_D2_CLK(160M)*/
|
||||
uint32_t bclk_div = 16;
|
||||
uint32_t bclk = sample_freq_hz * 2;
|
||||
uint32_t mclk = bclk * bclk_div;
|
||||
hal_utils_clk_div_t mclk_div = {};
|
||||
i2s_hal_calc_mclk_precise_division(I2S_BASE_CLK, mclk, &mclk_div);
|
||||
i2s_ll_rx_set_mclk(hal->dev, &mclk_div);
|
||||
i2s_ll_rx_set_bck_div_num(hal->dev, bclk_div);
|
||||
i2s_ll_rx_set_mclk(adc_hal_i2s_dev, &mclk_div);
|
||||
i2s_ll_rx_set_bck_div_num(adc_hal_i2s_dev, bclk_div);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -234,13 +176,20 @@ void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_c
|
||||
adc_hal_digi_sample_freq_config(hal, cfg->clk_src, cfg->clk_src_freq_hz, cfg->sample_freq_hz);
|
||||
}
|
||||
|
||||
static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t per_eof_size, uint32_t eof_step, uint32_t eof_num)
|
||||
|
||||
void adc_hal_digi_dma_link(adc_hal_dma_ctx_t *hal, uint8_t *data_buf)
|
||||
{
|
||||
dma_descriptor_t *desc = hal->rx_desc;
|
||||
uint32_t per_eof_size = hal->eof_num * SOC_ADC_DIGI_DATA_BYTES_PER_CONV;
|
||||
uint32_t eof_step = hal->eof_step;
|
||||
uint32_t eof_num = hal->eof_desc_num;
|
||||
|
||||
HAL_ASSERT(((uint32_t)data_buf % 4) == 0);
|
||||
HAL_ASSERT((per_eof_size % 4) == 0);
|
||||
uint32_t n = 0;
|
||||
dma_descriptor_t *desc_head = desc;
|
||||
|
||||
hal->cur_desc_ptr = &hal->desc_dummy_head;
|
||||
while (eof_num--) {
|
||||
uint32_t eof_size = per_eof_size;
|
||||
|
||||
@ -266,40 +215,6 @@ static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *d
|
||||
desc[n-1].next = desc_head;
|
||||
}
|
||||
|
||||
void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf)
|
||||
{
|
||||
//stop peripheral and DMA
|
||||
adc_hal_digi_stop(hal);
|
||||
|
||||
//reset DMA
|
||||
adc_dma_ll_rx_reset_channel(hal->dev, hal->dma_chan);
|
||||
//reset peripheral
|
||||
adc_ll_digi_reset(hal->dev);
|
||||
|
||||
//reset the current descriptor address
|
||||
hal->cur_desc_ptr = &hal->desc_dummy_head;
|
||||
adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * SOC_ADC_DIGI_DATA_BYTES_PER_CONV, hal->eof_step, hal->eof_desc_num);
|
||||
|
||||
//start DMA
|
||||
adc_dma_ll_rx_start(hal->dev, hal->dma_chan, (lldesc_t *)hal->rx_desc);
|
||||
//connect DMA and peripheral
|
||||
adc_ll_digi_dma_enable();
|
||||
//start ADC
|
||||
adc_ll_digi_trigger_enable(hal->dev);
|
||||
}
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
intptr_t adc_hal_get_desc_addr(adc_hal_dma_ctx_t *hal)
|
||||
{
|
||||
return adc_dma_ll_get_in_suc_eof_desc_addr(hal->dev, hal->dma_chan);
|
||||
}
|
||||
|
||||
bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask)
|
||||
{
|
||||
return adc_dma_ll_rx_get_intr(hal->dev, mask);
|
||||
}
|
||||
#endif //#if !SOC_GDMA_SUPPORTED
|
||||
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len)
|
||||
{
|
||||
HAL_ASSERT(hal->cur_desc_ptr);
|
||||
@ -343,24 +258,27 @@ valid:
|
||||
return ADC_HAL_DMA_DESC_VALID;
|
||||
}
|
||||
|
||||
void adc_hal_digi_clr_intr(adc_hal_dma_ctx_t *hal, uint32_t mask)
|
||||
void adc_hal_digi_enable(bool enable)
|
||||
{
|
||||
adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, mask);
|
||||
if (enable) {
|
||||
adc_ll_digi_trigger_enable();
|
||||
} else {
|
||||
adc_ll_digi_trigger_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void adc_hal_digi_dis_intr(adc_hal_dma_ctx_t *hal, uint32_t mask)
|
||||
void adc_hal_digi_connect(bool enable)
|
||||
{
|
||||
adc_dma_ll_rx_disable_intr(hal->dev, hal->dma_chan, mask);
|
||||
if (enable) {
|
||||
adc_ll_digi_dma_enable();
|
||||
} else {
|
||||
adc_ll_digi_dma_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void adc_hal_digi_stop(adc_hal_dma_ctx_t *hal)
|
||||
void adc_hal_digi_reset(void)
|
||||
{
|
||||
//stop ADC
|
||||
adc_ll_digi_trigger_disable(hal->dev);
|
||||
//stop DMA
|
||||
adc_dma_ll_rx_stop(hal->dev, hal->dma_chan);
|
||||
//disconnect DMA and peripheral
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_reset();
|
||||
}
|
||||
|
||||
#if ADC_LL_WORKAROUND_CLEAR_EOF_COUNTER
|
||||
|
@ -33,12 +33,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#define ADC_HAL_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_HAL_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF
|
||||
#else //CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_HAL_DMA_INTR_MASK BIT(9)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_HAL_DMA_I2S_HOST 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -54,10 +50,8 @@ typedef enum adc_hal_dma_desc_status_t {
|
||||
* @brief Configuration of the HAL
|
||||
*/
|
||||
typedef struct adc_hal_dma_config_t {
|
||||
void *dev; ///< DMA peripheral address
|
||||
uint32_t eof_desc_num; ///< Number of dma descriptors that is eof
|
||||
uint32_t eof_step; ///< Number of linked descriptors that is one eof
|
||||
uint32_t dma_chan; ///< DMA channel to be used
|
||||
uint32_t eof_num; ///< Bytes between 2 in_suc_eof interrupts
|
||||
} adc_hal_dma_config_t;
|
||||
|
||||
@ -73,10 +67,8 @@ typedef struct adc_hal_dma_ctx_t {
|
||||
dma_descriptor_t *cur_desc_ptr; ///< Pointer to the current descriptor
|
||||
|
||||
/**< these need to be configured by `adc_hal_dma_config_t` via driver layer*/
|
||||
void *dev; ///< DMA address
|
||||
uint32_t eof_desc_num; ///< Number of dma descriptors that is eof
|
||||
uint32_t eof_step; ///< Number of linked descriptors that is one eof
|
||||
uint32_t dma_chan; ///< DMA channel to be used
|
||||
uint32_t eof_num; ///< Words between 2 in_suc_eof interrupts
|
||||
} adc_hal_dma_ctx_t;
|
||||
|
||||
@ -123,9 +115,8 @@ void adc_hal_digi_init(adc_hal_dma_ctx_t *hal);
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_deinit(adc_hal_dma_ctx_t *hal);
|
||||
void adc_hal_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize the hal context
|
||||
@ -144,33 +135,12 @@ void adc_hal_dma_ctx_config(adc_hal_dma_ctx_t *hal, const adc_hal_dma_config_t *
|
||||
void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_ctrlr_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Start Conversion
|
||||
* @brief Link DMA descriptor
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param data_buf Pointer to the data buffer, the length should be multiple of ``desc_max_num`` and ``eof_num`` in ``adc_hal_dma_ctx_t``
|
||||
*/
|
||||
void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf);
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
/**
|
||||
* @brief Get the DMA descriptor that Hardware has finished processing.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*
|
||||
* @return DMA descriptor address
|
||||
*/
|
||||
intptr_t adc_hal_get_desc_addr(adc_hal_dma_ctx_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Check the hardware interrupt event
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask Event mask
|
||||
*
|
||||
* @return True: the event is triggered. False: the event is not triggered yet.
|
||||
*/
|
||||
bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask);
|
||||
#endif
|
||||
void adc_hal_digi_dma_link(adc_hal_dma_ctx_t *hal, uint8_t *data_buf);
|
||||
|
||||
/**
|
||||
* @brief Get the ADC reading result
|
||||
@ -185,27 +155,23 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask);
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt
|
||||
* @brief Enable or disable ADC digital controller
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void adc_hal_digi_clr_intr(adc_hal_dma_ctx_t *hal, uint32_t mask);
|
||||
void adc_hal_digi_enable(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt
|
||||
* @brief Enable pr disable output data to DMA from adc digital controller.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void adc_hal_digi_dis_intr(adc_hal_dma_ctx_t *hal, uint32_t mask);
|
||||
void adc_hal_digi_connect(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Stop conversion
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @brief Reset adc digital controller.
|
||||
*/
|
||||
void adc_hal_digi_stop(adc_hal_dma_ctx_t *hal);
|
||||
void adc_hal_digi_reset(void);
|
||||
|
||||
#if ADC_LL_WORKAROUND_CLEAR_EOF_COUNTER
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user