diff --git a/components/driver/esp32s2/dac.c b/components/driver/esp32s2/dac.c index 7015ed463c..19688fa41f 100644 --- a/components/driver/esp32s2/dac.c +++ b/components/driver/esp32s2/dac.c @@ -10,38 +10,36 @@ #include "esp_err.h" #include "esp_check.h" #include "esp_pm.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" -#include "freertos/task.h" #include "freertos/queue.h" #include "driver/rtc_io.h" #include "driver/dac.h" #include "soc/dac_periph.h" #include "soc/lldesc.h" -#include "soc/system_reg.h" -#include "soc/periph_defs.h" -#include "soc/cp_dma_reg.h" #include "hal/dac_hal.h" #include "periph_ctrl.h" -#include "sys/queue.h" +#include "driver/spi_common_internal.h" -static __attribute__((unused)) const char *TAG = "DAC"; +static const char *DAC_TAG = "DAC"; + +/* On ESP32-S2, DAC-DMA shares the SPI3-DMA channel */ +#define DAC_USE_SPI3_DMA_CHANNEL SPI3_HOST extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) -portMUX_TYPE dac_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED; -#define DAC_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&dac_isr_handler_list_lock) -#define DAC_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&dac_isr_handler_list_lock) typedef struct { - uint32_t int_msk; + bool intr_trigger; uint8_t *data; uint32_t data_len; } dac_dma_event_t; typedef struct { + dac_hal_context_t *hal; /*!< HAL pointer of DAC */ QueueHandle_t que_dac_hdl; /*!< DAC queue handler */ uint32_t dma_buffer_cnt; /*!< DMA buffer count, number of buffer. */ uint32_t dma_buffer_length; /*!< DMA buffer length, length of each buffer. */ @@ -49,172 +47,43 @@ typedef struct { bool dac_start_en; /*!< The status of the DAC, 0: stop, 1: start */ dac_dma_link_type_t dac_dma_link_type; /*!< The type of the link, see `dac_dma_link_type_t` */ esp_pm_lock_handle_t pm_lock; /*!< Spinlock for DAC */ + spi_host_device_t spi_host; /*!< spi host */ intr_handle_t dac_isr_handle; /*!< DAC interrupt handler */ - uint32_t dac_isr; /*!< DAC interrupt mask */ } dac_digi_context_t; -dac_digi_context_t *s_dac_digi_ctx = NULL; +static dac_digi_context_t *s_dac_digi_ctx = NULL; /*--------------------------------------------------------------- INTERRUPT HANDLER ---------------------------------------------------------------*/ -typedef struct dac_dma_isr_handler { - uint32_t mask; - intr_handler_t handler; - void* handler_arg; - SLIST_ENTRY(dac_dma_isr_handler) next; -} dac_dma_isr_handler_t; - -static SLIST_HEAD(dac_dma_isr_handler_list_, dac_dma_isr_handler) s_dac_dma_isr_handler_list = - SLIST_HEAD_INITIALIZER(s_dac_dma_isr_handler_list); - -static IRAM_ATTR void dac_dma_isr(void * arg) +static IRAM_ATTR void dac_dma_isr_default(void *arg) { - uint32_t int_st = dac_hal_digi_read_intr_status(); + dac_digi_context_t *p_dac = (dac_digi_context_t *) arg; + bool status = dac_dma_hal_get_intr_status(p_dac->hal); + dac_dma_hal_clr_intr(p_dac->hal); int task_awoken = pdFALSE; dac_dma_event_t dac_evt; - dac_evt.int_msk = int_st; - REG_WRITE(SPI_DMA_INT_CLR_REG(3), int_st); + dac_evt.intr_trigger = status; xQueueSendFromISR(s_dac_digi_ctx->que_dac_hdl, &dac_evt, &task_awoken); - - if (task_awoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -static IRAM_ATTR void dac_dma_isr_default(void* arg) -{ - uint32_t status = dac_hal_digi_read_intr_status(); - dac_dma_isr_handler_t* it; - DAC_ENTER_CRITICAL_ISR(); - SLIST_FOREACH(it, &s_dac_dma_isr_handler_list, next) { - if (it->mask & status) { - DAC_EXIT_CRITICAL_ISR(); - (*it->handler)(it->handler_arg); - DAC_ENTER_CRITICAL_ISR(); - } - } - DAC_EXIT_CRITICAL_ISR(); - dac_hal_digi_clear_intr(status); -} - -static esp_err_t dac_dma_isr_ensure_installed(void) -{ - esp_err_t err = ESP_OK; - DAC_ENTER_CRITICAL_ISR(); - dac_hal_digi_clear_intr(UINT32_MAX); - dac_hal_digi_enable_intr(0); - err = esp_intr_alloc(ETS_SPI3_DMA_INTR_SOURCE, 0, &dac_dma_isr_default, NULL, &s_dac_digi_ctx->dac_isr_handle); - if (err != ESP_OK) { - goto out; - } - -out: - DAC_EXIT_CRITICAL_ISR(); - return err; -} - -esp_err_t dac_dma_isr_register(intr_handler_t handler, void* handler_arg, uint32_t intr_mask) -{ - esp_err_t err = dac_dma_isr_ensure_installed(); - if (err != ESP_OK) { - return err; - } - - dac_dma_isr_handler_t* item = malloc(sizeof(*item)); - if (item == NULL) { - return ESP_ERR_NO_MEM; - } - item->handler = handler; - item->handler_arg = handler_arg; - item->mask = intr_mask; - DAC_ENTER_CRITICAL_ISR(); - SLIST_INSERT_HEAD(&s_dac_dma_isr_handler_list, item, next); - DAC_EXIT_CRITICAL_ISR(); - return ESP_OK; -} - -esp_err_t dac_dma_isr_deregister(intr_handler_t handler, void* handler_arg) -{ - dac_dma_isr_handler_t* it; - dac_dma_isr_handler_t* prev = NULL; - bool found = false; - esp_intr_free(s_dac_digi_ctx->dac_isr_handle); - - DAC_ENTER_CRITICAL_ISR(); - SLIST_FOREACH(it, &s_dac_dma_isr_handler_list, next) { - if (it->handler == handler && it->handler_arg == handler_arg) { - if (it == SLIST_FIRST(&s_dac_dma_isr_handler_list)) { - SLIST_REMOVE_HEAD(&s_dac_dma_isr_handler_list, next); - } else { - SLIST_REMOVE_AFTER(prev, next); - } - found = true; - free(it); - break; - } - prev = it; - } - DAC_EXIT_CRITICAL_ISR(); - return found ? ESP_OK : ESP_ERR_INVALID_STATE; -} - -void dac_dma_linker_stop(void) -{ - dac_hal_dma_disable(); -} - -void dac_dma_linker_deinit(void) -{ - dac_dma_linker_stop(); - dac_hal_digi_clear_intr(UINT32_MAX); - dac_hal_digi_enable_intr(0); } /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ - -esp_err_t __attribute__((unused)) dac_digi_init(void) -{ - s_dac_digi_ctx = calloc(1, sizeof(dac_digi_context_t)); - s_dac_digi_ctx->dac_start_en = false; - DAC_ENTER_CRITICAL(); - dac_hal_digi_init(); - DAC_EXIT_CRITICAL(); - - return ESP_OK; -} - -static lldesc_t** dac_dma_desc_buf_create(int desc_cnt, size_t buf_size, const void *data) +static lldesc_t** dac_dma_desc_buf_create(int desc_cnt, size_t buf_size) { lldesc_t** pdesc = (lldesc_t**)heap_caps_calloc(1, sizeof(lldesc_t*) * desc_cnt, MALLOC_CAP_DMA); if (pdesc == NULL) { goto _exit; } for (int i = 0; i < desc_cnt; i++) { - pdesc[i] = (lldesc_t*)malloc(sizeof(lldesc_t)); + pdesc[i] = (lldesc_t*)heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); if (pdesc[i] == NULL) { goto _exit; } memset(pdesc[i], 0, sizeof(lldesc_t)); } - for (int bux_idx = 0; bux_idx < desc_cnt; bux_idx++) { - pdesc[bux_idx]->owner = 1; - pdesc[bux_idx]->eof = 1; - pdesc[bux_idx]->length = buf_size; - pdesc[bux_idx]->size = buf_size; - pdesc[bux_idx]->buf = (uint8_t *) data; - data += buf_size; - if (s_dac_digi_ctx->dac_dma_link_type == DAC_DMA_LINK_RECURSIVE) { - WRITE_PERI_REG(CP_DMA_OUTLINK_START, 1); - pdesc[bux_idx]->qe.stqe_next = ((bux_idx < (desc_cnt - 1)) ? (pdesc[bux_idx + 1]) : pdesc[0]); - } else { - pdesc[bux_idx]->qe.stqe_next = ((bux_idx < (desc_cnt - 1)) ? (pdesc[bux_idx + 1]) : NULL); - } - - } return pdesc; _exit: for (int i = 0; i < desc_cnt; i++) { @@ -224,15 +93,31 @@ _exit: return NULL; } -esp_err_t dac_digi_initialize(const dac_digi_config_t *init_cfg) +static void dac_dma_write(lldesc_t** pdesc, int desc_cnt, size_t buf_size, const void *buffer) { - DAC_CHECK(init_cfg->mode < DAC_CONV_MAX, "DAC mode error", ESP_ERR_INVALID_ARG); - DAC_CHECK(init_cfg->interval > 0 && init_cfg->interval < 4096, "DAC interval error", ESP_ERR_INVALID_ARG); - DAC_CHECK(init_cfg->dig_clk.div_num < 256, "DAC clk div_num error", ESP_ERR_INVALID_ARG); - DAC_CHECK(init_cfg->dig_clk.div_b > 0 && init_cfg->dig_clk.div_b < 64, "DAC clk div_b error", ESP_ERR_INVALID_ARG); - DAC_CHECK(init_cfg->dig_clk.div_a < 64, "DAC clk div_a error", ESP_ERR_INVALID_ARG); + for (int bux_idx = 0; bux_idx < desc_cnt; bux_idx++) { + pdesc[bux_idx]->owner = 1; + pdesc[bux_idx]->eof = 1; + pdesc[bux_idx]->length = buf_size; + pdesc[bux_idx]->size = buf_size; + pdesc[bux_idx]->buf = (uint8_t *) buffer; + buffer += buf_size; + if (s_dac_digi_ctx->dac_dma_link_type == DAC_DMA_LINK_RECURSIVE) { + pdesc[bux_idx]->qe.stqe_next = ((bux_idx < (desc_cnt - 1)) ? (pdesc[bux_idx + 1]) : pdesc[0]); + } else { + pdesc[bux_idx]->qe.stqe_next = ((bux_idx < (desc_cnt - 1)) ? (pdesc[bux_idx + 1]) : NULL); + } + } +} + +esp_err_t dac_digi_initialize(const dac_digi_init_config_t *init_cfg) +{ + ESP_RETURN_ON_FALSE(init_cfg->mode < DAC_CONV_MAX, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC mode error"); + ESP_RETURN_ON_FALSE((init_cfg->interval > 0) && (init_cfg->interval < 4096), ESP_ERR_INVALID_ARG, DAC_TAG, "DAC interval error"); esp_err_t err = ESP_OK; + uint32_t dma_chan = 0; + uint32_t dac_chan = 0; if (s_dac_digi_ctx != NULL) { ESP_LOGE(DAC_TAG, "DAC has been installed"); err = ESP_FAIL; @@ -248,11 +133,7 @@ esp_err_t dac_digi_initialize(const dac_digi_config_t *init_cfg) #ifdef CONFIG_PM_ENABLE if (s_dac_digi_ctx->pm_lock == NULL) { - if (init_cfg->dig_clk.use_apll) { - err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "dac_dma", &s_dac_digi_ctx->pm_lock); - } else { - err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_ctx->pm_lock); - } + err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_ctx->pm_lock); if (err != ESP_OK) { s_dac_digi_ctx->pm_lock = NULL; ESP_LOGE(DAC_TAG, "DAC-DMA pm lock error"); @@ -266,16 +147,43 @@ esp_err_t dac_digi_initialize(const dac_digi_config_t *init_cfg) } else { xQueueReset(s_dac_digi_ctx->que_dac_hdl); } - periph_module_enable(PERIPH_SPI3_DMA_MODULE); - periph_module_enable(PERIPH_HSPI_MODULE); + periph_module_enable(PERIPH_SARADC_MODULE); - dac_hal_digi_controller_config(init_cfg); + do { + if ((init_cfg->dac_chan_msk >> dac_chan) & BIT(0)) { + dac_output_enable(dac_chan); + dac_chan++; + } + } while (dac_chan < DAC_CHANNEL_MAX); + + dac_hal_ctrl_config_t ctrl_hal_cfg = { + .mode = init_cfg->mode, + .interval = init_cfg->interval, + }; + + dac_hal_digi_controller_configure(&ctrl_hal_cfg); s_dac_digi_ctx->dma_buffer_cnt = init_cfg->dac_dma_cnt; s_dac_digi_ctx->dma_buffer_length = init_cfg->dac_dma_length; s_dac_digi_ctx->dac_dma_link_type = init_cfg->dac_dma_link_type; - s_dac_digi_ctx->dac_isr = SPI_OUT_EOF_INT_ENA | SPI_OUT_TOTAL_EOF_INT_ENA; - dac_dma_isr_register(dac_dma_isr, NULL, s_dac_digi_ctx->dac_isr); + s_dac_digi_ctx->spi_host = DAC_USE_SPI3_DMA_CHANNEL; + + spicommon_periph_claim(s_dac_digi_ctx->spi_host, "dac"); + err = spicommon_slave_dma_chan_alloc(s_dac_digi_ctx->spi_host, SPI_DMA_CH_AUTO, &dma_chan, &dma_chan); + if (err != ESP_OK) { + goto _exit; + } + + s_dac_digi_ctx->hal = calloc(1, sizeof(dac_hal_context_t)); + s_dac_digi_ctx->hal->dev = (void *)SPI_LL_GET_HW(s_dac_digi_ctx->spi_host); + s_dac_digi_ctx->hal->dma_chan = dma_chan; + + dac_dma_hal_init(s_dac_digi_ctx->hal); + err = esp_intr_alloc(spicommon_irqdma_source_for_host(s_dac_digi_ctx->spi_host), 0, dac_dma_isr_default, s_dac_digi_ctx, &s_dac_digi_ctx->dac_isr_handle); + if(err != ESP_OK){ + goto _exit; + } + s_dac_digi_ctx->desc = dac_dma_desc_buf_create(s_dac_digi_ctx->dma_buffer_cnt, s_dac_digi_ctx->dma_buffer_length); return err; _exit: @@ -283,22 +191,20 @@ _exit: return err; } -esp_err_t dac_digi_write_bytes(const void *buffer) +esp_err_t dac_digi_write_bytes(uint32_t length, const void *buffer, TickType_t ticks_to_wait) { - dac_hal_digi_clear_intr(UINT32_MAX); - dac_hal_digi_enable_intr(SPI_LL_INTR_OUT_TOTAL_EOF | SPI_LL_INTR_OUT_EOF); + ESP_RETURN_ON_FALSE(length <= (s_dac_digi_ctx->dma_buffer_cnt * s_dac_digi_ctx->dma_buffer_length), ESP_ERR_INVALID_ARG, DAC_TAG, "DAC DMA buffer length is larger than DMA buffer."); dac_dma_event_t dac_evt; - s_dac_digi_ctx->desc = dac_dma_desc_buf_create(s_dac_digi_ctx->dma_buffer_cnt, s_dac_digi_ctx->dma_buffer_length, (uint32_t*)buffer); + bool dac_isr_flag = 1; - dac_hal_dma_reset(0); - dac_hal_dma_fifo_reset(); - dac_hal_dma_start(0, s_dac_digi_ctx->desc[0]); - while (s_dac_digi_ctx->dac_isr) { - xQueueReceive(s_dac_digi_ctx->que_dac_hdl, &dac_evt, 2000 / portTICK_RATE_MS); - ESP_LOGV(DAC_TAG, "DAC-DMA intr type 0x%x", dac_evt.int_msk); - if (dac_evt.int_msk & s_dac_digi_ctx->dac_isr) { - s_dac_digi_ctx->dac_isr &= (~dac_evt.int_msk); + dac_dma_write(s_dac_digi_ctx->desc, s_dac_digi_ctx->dma_buffer_cnt, s_dac_digi_ctx->dma_buffer_length, buffer); + + dac_dma_hal_trans_start(s_dac_digi_ctx->hal, s_dac_digi_ctx->desc[0]); + while (dac_isr_flag) { + xQueueReceive(s_dac_digi_ctx->que_dac_hdl, &dac_evt, ticks_to_wait); + if (dac_evt.intr_trigger & dac_isr_flag) { + dac_isr_flag &= (!dac_evt.intr_trigger); } } return ESP_OK; @@ -314,22 +220,24 @@ esp_err_t dac_digi_deinitialize(void) ESP_LOGE(DAC_TAG, "DAC is still working"); return ESP_ERR_INVALID_STATE; } - periph_module_disable(PERIPH_SPI3_DMA_MODULE); - periph_module_disable(PERIPH_HSPI_MODULE); periph_module_disable(PERIPH_SARADC_MODULE); - dac_dma_linker_deinit(); - dac_dma_isr_deregister(dac_dma_isr, NULL); + spicommon_periph_free(s_dac_digi_ctx->spi_host); + spicommon_slave_free_dma(s_dac_digi_ctx->spi_host); + if (s_dac_digi_ctx->que_dac_hdl) { vQueueDelete(s_dac_digi_ctx->que_dac_hdl); s_dac_digi_ctx->que_dac_hdl = NULL; } + dac_dma_hal_deinit(s_dac_digi_ctx->hal); + for (int i = 0; i < s_dac_digi_ctx->dma_buffer_cnt; i++) { free(s_dac_digi_ctx->desc[i]); } + free(s_dac_digi_ctx->hal); free(s_dac_digi_ctx); s_dac_digi_ctx = NULL; #ifdef CONFIG_PM_ENABLE @@ -399,7 +307,7 @@ esp_err_t dac_digi_start(void) } s_dac_digi_ctx->dac_start_en = true; #ifdef CONFIG_PM_ENABLE - DAC_CHECK((s_dac_digi_ctx->pm_lock), "Should start after call `dac_digi_controller_config`", ESP_FAIL); + ESP_RETURN_ON_FALSE((s_dac_digi_ctx->pm_lock), ESP_ERR_INVALID_STATE, DAC_TAG, "Should start after call `dac_digi_controller_config`"); esp_pm_lock_acquire(s_dac_digi_ctx->pm_lock); #endif DAC_ENTER_CRITICAL(); @@ -445,3 +353,62 @@ esp_err_t dac_digi_reset(void) return ESP_OK; } + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +esp_err_t __attribute__((deprecated)) dac_digi_init(void) +{ + s_dac_digi_ctx = calloc(1, sizeof(dac_digi_context_t)); + s_dac_digi_ctx->dac_start_en = false; + DAC_ENTER_CRITICAL(); + dac_hal_digi_init(); + DAC_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t __attribute__((deprecated)) dac_digi_deinit(void) +{ +#ifdef CONFIG_PM_ENABLE + if (s_dac_digi_ctx->pm_lock) { + esp_pm_lock_delete(s_dac_digi_ctx->pm_lock); + s_dac_digi_ctx->pm_lock = NULL; + } + +#endif + free(s_dac_digi_ctx); + DAC_ENTER_CRITICAL(); + dac_hal_digi_deinit(); + DAC_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t __attribute__((deprecated)) dac_digi_controller_config(const dac_digi_config_t *cfg) +{ + ESP_RETURN_ON_FALSE(cfg->mode < DAC_CONV_MAX, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC mode error"); + ESP_RETURN_ON_FALSE(cfg->interval > 0 && cfg->interval < 4096, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC interval error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_num < 256, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC clk div_num error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC clk div_b error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_a < 64, ESP_ERR_INVALID_ARG, DAC_TAG, "DAC clk div_a error"); +#ifdef CONFIG_PM_ENABLE + esp_err_t err; + if (s_dac_digi_ctx->pm_lock == NULL) { + if (cfg->dig_clk.use_apll) { + err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "dac_dma", &s_dac_digi_ctx->pm_lock); + } else { + err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_ctx->pm_lock); + } + if (err != ESP_OK) { + s_dac_digi_ctx->pm_lock = NULL; + ESP_LOGE(DAC_TAG, "DAC-DMA pm lock error"); + return err; + } + } +#endif //CONFIG_PM_ENABLE + + DAC_ENTER_CRITICAL(); + dac_hal_digi_controller_config(cfg); + DAC_EXIT_CRITICAL(); + + return ESP_OK; +} diff --git a/components/driver/esp32s2/include/driver/dac.h b/components/driver/esp32s2/include/driver/dac.h index ef6bb96fa4..695e5c3f9f 100644 --- a/components/driver/esp32s2/include/driver/dac.h +++ b/components/driver/esp32s2/include/driver/dac.h @@ -11,21 +11,30 @@ #ifdef __cplusplus extern "C" { #endif + +/** + * @brief DAC digital controller (DMA mode) configuration parameters. + */ +typedef struct { + dac_digi_convert_mode_t mode; /*!< DAC digital controller (DMA mode) work mode. See ``dac_digi_convert_mode_t``. */ + uint32_t dac_chan_msk; /*!< DAC channel select mask, use BIT(CHAN_X) to mask the channesl */ + uint32_t interval; /*!< The number of interval clock cycles for the DAC digital controller to output voltage. + The unit is the divided clock. Range: 1 ~ 4095. + Expression: `dac_output_freq` = `controller_clk` / interval. Refer to ``adc_digi_clk_t``. + Note: The sampling rate of each channel is also related to the conversion mode (See ``dac_digi_convert_mode_t``) and pattern table settings. */ + uint32_t dac_dma_cnt; /*!< DMA buffer count, number of buffer. */ + uint32_t dac_dma_length; /*!< DMA buffer length, length of each buffer. */ + dac_dma_link_type_t dac_dma_link_type; /*!< The type of the link, see `dac_dma_link_type_t` */ +} dac_digi_init_config_t; + /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ /** - * @brief DAC digital controller initialization. - * @return - * - ESP_OK success - */ -esp_err_t __attribute__((unused)) dac_digi_init(void); - -/** - * @brief Initialize the Digital DAC. + * @brief Initialize the Digital DAC controller. * - * @param init_cfg Pointer to Digital DAC initilization config. Refer to ``dac_digi_config_t``. + * @param init_cfg Pointer to Digital DAC initialization config. Refer to ``dac_digi_config_t``. * * @return * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. @@ -33,17 +42,10 @@ esp_err_t __attribute__((unused)) dac_digi_init(void); * - ESP_ERR_NO_MEM If out of memory * - ESP_OK On success */ -esp_err_t dac_digi_initialize(const dac_digi_config_t *init_cfg); +esp_err_t dac_digi_initialize(const dac_digi_init_config_t *init_cfg); /** - * @brief DAC digital controller deinitialization. - * @return - * - ESP_OK success - */ -esp_err_t __attribute__((unused)) dac_digi_deinit(void); - -/** - * @brief Deinitialize the Digital DAC. + * @brief Deinitialize the Digital DAC controller. * * @return * - ESP_ERR_INVALID_STATE Driver state is invalid. @@ -54,25 +56,17 @@ esp_err_t dac_digi_deinitialize(void); /** * @brief Write bytes to Digital DAC through DMA. * - * @param[in] buffer Buffer to write to DAC. + * @param length the buffer length. + * @param[in] buffer Buffer to write to DAC. + * @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to + * never time out. * * @return * - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate. * - ESP_ERR_TIMEOUT Operation timed out * - ESP_OK On success */ -esp_err_t dac_digi_write_bytes(const void *buffer); - -/** - * @brief Setting the DAC digital controller. - * - * @param cfg Pointer to digital controller paramter. See ``dac_digi_config_t``. - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t __attribute__((unused)) dac_digi_controller_config(const dac_digi_config_t *cfg); +esp_err_t dac_digi_write_bytes(uint32_t length, const void *buffer, TickType_t ticks_to_wait); /** * @brief DAC digital controller start output voltage. @@ -102,6 +96,35 @@ esp_err_t dac_digi_fifo_reset(void); */ esp_err_t dac_digi_reset(void); +/************************************************************ + * Deprecated APIs + ***********************************************************/ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +/** + * @brief Setting the DAC digital controller. + * + * @param cfg Pointer to digital controller paramter. See ``dac_digi_config_t``. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t __attribute__((deprecated)) dac_digi_controller_config(const dac_digi_config_t *cfg); + +/** + * @brief DAC digital controller deinitialization. + * @return + * - ESP_OK success + */ +esp_err_t __attribute__((deprecated)) dac_digi_deinit(void); + +/** + * @brief DAC digital controller initialization. + * @return + * - ESP_OK success + */ +esp_err_t __attribute__((deprecated)) dac_digi_init(void); + #ifdef __cplusplus } #endif diff --git a/components/driver/test/dac_dma_test/test_esp32s2.c b/components/driver/test/dac_dma_test/test_esp32s2.c new file mode 100644 index 0000000000..9b44acd095 --- /dev/null +++ b/components/driver/test/dac_dma_test/test_esp32s2.c @@ -0,0 +1,363 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + Tests for the dac device driver on ESP32-S2 only +*/ +#include "sdkconfig.h" +#if CONFIG_IDF_TARGET_ESP32S2 + +#include "esp_system.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "driver/adc.h" +#include "driver/rtc_io.h" +#include "driver/gpio.h" +#include "unity.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "test_utils.h" +#include "soc/soc.h" +#include "soc/spi_reg.h" +#include "soc/adc_periph.h" +#include "soc/dac_periph.h" +#include "soc/spi_periph.h" +#include "test/test_common_adc.h" +#include "driver/dac.h" +#include "soc/system_reg.h" +#include "esp32s2/rom/lldesc.h" +#include "test/test_adc_dac_dma.h" + +/******************************************************** + * This test is left for testing the legacy DAC-DMA APIs + *******************************************************/ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +static const char *TAG = "test_adc"; + +#define PLATFORM_SELECT (1) //0: pxp; 1: chip +#if (PLATFORM_SELECT == 0) //PXP platform +#include "soc/apb_ctrl_reg.h" +#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag) +//PXP clk is slower. +#define SYS_DELAY_TIME_MOM (1/40) +#define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz. +static void test_pxp_deinit_io(void) +{ + for (int i = 0; i < 22; i++) { + rtc_gpio_init(i); + } +} +#else +//PXP clk is slower. +#define SET_BREAK_POINT(flag) +#define SYS_DELAY_TIME_MOM (1) +#define RTC_SLOW_CLK_FLAG 0 // Slow clock is 32KHz. +#endif + +#define SAR_SIMPLE_NUM 512 // Set out number of enabled unit. + +typedef struct dma_msg { + uint32_t int_msk; + uint8_t *data; + uint32_t data_len; +} dac_dma_event_t; + +static QueueHandle_t que_dac = NULL; +static uint8_t link_buf[2][SAR_SIMPLE_NUM*2] = {0}; +static lldesc_t dma1 = {0}; +static lldesc_t dma2 = {0}; + +/*******************************************/ +/** DAC-DMA INIT CODE */ +/*******************************************/ + +/** + * DMA liner initialization and start. + * @param is_loop + * - true: The two dma linked lists are connected end to end, with no end mark (eof). + * - false: The two dma linked lists are connected end to end, with end mark (eof). + * @param int_mask DMA interrupt types. + */ +uint32_t dac_dma_linker_init(bool is_alter, bool is_loop) +{ + /* The DAC output is a sawtooth wave. */ + if (is_alter) { + for(int i=0; i> %s - dac mode %d<< ", __func__, mode); + + dac_dma_event_t evt; + + dac_digi_init(); + const dac_digi_config_t cfg = { + .mode = mode, + .interval = 100, + .dig_clk.use_apll = false, // APB clk + .dig_clk.div_num = 79, + .dig_clk.div_b = 1, + .dig_clk.div_a = 0, + }; + dac_digi_controller_config(&cfg); + dac_output_enable(DAC_CHANNEL_1); + dac_output_enable(DAC_CHANNEL_2); + + /* DAC-DMA linker init */ + if (que_dac == NULL) { + que_dac = xQueueCreate(5, sizeof(dac_dma_event_t)); + } else { + xQueueReset(que_dac); + } + uint32_t int_mask = SPI_OUT_DONE_INT_ENA | SPI_OUT_EOF_INT_ENA | SPI_OUT_TOTAL_EOF_INT_ENA; + uint32_t dma_addr = dac_dma_linker_init(mode, false); + adc_dac_dma_isr_register(dac_dma_isr, NULL, int_mask); + adc_dac_dma_linker_start(DMA_ONLY_DAC_OUTLINK, (void *)dma_addr, int_mask); + + /* ADC-DMA start output */ + dac_digi_start(); + + /* Check interrupt type */ + while (int_mask) { + TEST_ASSERT_EQUAL( xQueueReceive(que_dac, &evt, 2000 / portTICK_RATE_MS), pdTRUE ); + ESP_LOGI(TAG, "DAC-DMA intr type 0x%x", evt.int_msk); + if (evt.int_msk & int_mask) { + int_mask &= (~evt.int_msk); + } + } + + ESP_LOGI(TAG, "DAC-DMA intr test over"); + adc_dac_dma_linker_deinit(); + adc_dac_dma_isr_deregister(dac_dma_isr, NULL); + TEST_ESP_OK( dac_digi_deinit() ); +} + +TEST_CASE("DAC-DMA interrupt test", "[dac]") +{ + test_dac_dig_dma_intr_check(DAC_CONV_NORMAL); + test_dac_dig_dma_intr_check(DAC_CONV_ALTER); +} + +/*******************************************/ +/** SPI DMA INIT CODE */ +/*******************************************/ + +#include "sys/queue.h" +static bool adc_dac_dma_isr_flag = false; + +/*--------------------------------------------------------------- + INTERRUPT HANDLER +---------------------------------------------------------------*/ + +typedef struct adc_dac_dma_isr_handler_ { + uint32_t mask; + intr_handler_t handler; + void* handler_arg; + SLIST_ENTRY(adc_dac_dma_isr_handler_) next; +} adc_dac_dma_isr_handler_t; + +static SLIST_HEAD(adc_dac_dma_isr_handler_list_, adc_dac_dma_isr_handler_) s_adc_dac_dma_isr_handler_list = + SLIST_HEAD_INITIALIZER(s_adc_dac_dma_isr_handler_list); +portMUX_TYPE s_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED; +static intr_handle_t s_adc_dac_dma_isr_handle; + +static IRAM_ATTR void adc_dac_dma_isr_default(void* arg) +{ + uint32_t status = REG_READ(SPI_DMA_INT_ST_REG(3)); + adc_dac_dma_isr_handler_t* it; + portENTER_CRITICAL_ISR(&s_isr_handler_list_lock); + SLIST_FOREACH(it, &s_adc_dac_dma_isr_handler_list, next) { + if (it->mask & status) { + portEXIT_CRITICAL_ISR(&s_isr_handler_list_lock); + (*it->handler)(it->handler_arg); + portENTER_CRITICAL_ISR(&s_isr_handler_list_lock); + } + } + portEXIT_CRITICAL_ISR(&s_isr_handler_list_lock); + REG_WRITE(SPI_DMA_INT_CLR_REG(3), status); +} + +static esp_err_t adc_dac_dma_isr_ensure_installed(void) +{ + esp_err_t err = ESP_OK; + portENTER_CRITICAL(&s_isr_handler_list_lock); + if (s_adc_dac_dma_isr_handle) { + goto out; + } + REG_WRITE(SPI_DMA_INT_ENA_REG(3), 0); + REG_WRITE(SPI_DMA_INT_CLR_REG(3), UINT32_MAX); + err = esp_intr_alloc(ETS_SPI3_DMA_INTR_SOURCE, 0, &adc_dac_dma_isr_default, NULL, &s_adc_dac_dma_isr_handle); + if (err != ESP_OK) { + goto out; + } + +out: + portEXIT_CRITICAL(&s_isr_handler_list_lock); + return err; +} + +esp_err_t adc_dac_dma_isr_register(intr_handler_t handler, void* handler_arg, uint32_t intr_mask) +{ + esp_err_t err = adc_dac_dma_isr_ensure_installed(); + if (err != ESP_OK) { + return err; + } + + adc_dac_dma_isr_handler_t* item = malloc(sizeof(*item)); + if (item == NULL) { + return ESP_ERR_NO_MEM; + } + item->handler = handler; + item->handler_arg = handler_arg; + item->mask = intr_mask; + portENTER_CRITICAL(&s_isr_handler_list_lock); + SLIST_INSERT_HEAD(&s_adc_dac_dma_isr_handler_list, item, next); + portEXIT_CRITICAL(&s_isr_handler_list_lock); + return ESP_OK; +} + +esp_err_t adc_dac_dma_isr_deregister(intr_handler_t handler, void* handler_arg) +{ + adc_dac_dma_isr_handler_t* it; + adc_dac_dma_isr_handler_t* prev = NULL; + bool found = false; + portENTER_CRITICAL(&s_isr_handler_list_lock); + SLIST_FOREACH(it, &s_adc_dac_dma_isr_handler_list, next) { + if (it->handler == handler && it->handler_arg == handler_arg) { + if (it == SLIST_FIRST(&s_adc_dac_dma_isr_handler_list)) { + SLIST_REMOVE_HEAD(&s_adc_dac_dma_isr_handler_list, next); + } else { + SLIST_REMOVE_AFTER(prev, next); + } + found = true; + free(it); + break; + } + prev = it; + } + portEXIT_CRITICAL(&s_isr_handler_list_lock); + return found ? ESP_OK : ESP_ERR_INVALID_STATE; +} + +void adc_dac_dma_linker_start(spi_dma_link_type_t type, void *dma_addr, uint32_t int_msk) +{ + REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_APB_SARADC_CLK_EN_M); + REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN_M); + REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST_M); + REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST_M); + REG_WRITE(SPI_DMA_INT_CLR_REG(3), 0xFFFFFFFF); + REG_WRITE(SPI_DMA_INT_ENA_REG(3), int_msk | REG_READ(SPI_DMA_INT_ENA_REG(3))); + if (type & DMA_ONLY_ADC_INLINK) { + REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); + REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); + SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_ADDR, (uint32_t)dma_addr, 0); + REG_SET_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST); + REG_CLR_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST); + REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); + REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); + } + if (type & DMA_ONLY_DAC_OUTLINK) { + REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP); + REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START); + SET_PERI_REG_BITS(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_ADDR, (uint32_t)dma_addr, 0); + REG_SET_BIT(SPI_DMA_CONF_REG(3), SPI_OUT_RST); + REG_CLR_BIT(SPI_DMA_CONF_REG(3), SPI_OUT_RST); + REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP); + REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START); + } +} + +void adc_dac_dma_linker_stop(spi_dma_link_type_t type) +{ + if (type & DMA_ONLY_ADC_INLINK) { + REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); + REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); + } + if (type & DMA_ONLY_DAC_OUTLINK) { + REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP); + REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START); + } +} + +void adc_dac_dma_linker_deinit(void) +{ + adc_dac_dma_linker_stop(DMA_BOTH_ADC_DAC); + REG_WRITE(SPI_DMA_INT_CLR_REG(3), 0xFFFFFFFF); + REG_WRITE(SPI_DMA_INT_ENA_REG(3), 0); + adc_dac_dma_isr_flag = false; +} + +/*******************************************/ +/** SPI DMA INIT CODE END */ +/*******************************************/ + +#endif // CONFIG_IDF_TARGET_ESP32S2 diff --git a/components/driver/test/test_dac_dma.c b/components/driver/test/test_dac_dma.c index 12722e1679..89e60b2cca 100644 --- a/components/driver/test/test_dac_dma.c +++ b/components/driver/test/test_dac_dma.c @@ -61,6 +61,8 @@ static void test_pxp_deinit_io(void) #define SAR_SIMPLE_NUM 512 // Set out number of enabled unit. +static const char *TAG = "test_adc"; + /*******************************************/ /** DAC-DMA INIT CODE */ /*******************************************/ @@ -98,28 +100,24 @@ void dac_dma_test_create_buffer(dac_digi_convert_mode_t mode) /** * Testcase: Check the interrupt types of DAC-DMA. */ -void test_dac_dig_dma_intr_check(dac_digi_convert_mode_t mode) +void test_dac_dma(dac_digi_convert_mode_t mode) { ESP_LOGI(TAG, " >> %s - dac mode %d<< ", __func__, mode); - const dac_digi_config_t cfg = { + const dac_digi_init_config_t cfg = { .mode = mode, + .dac_chan_msk = BIT(DAC_CHANNEL_1) | BIT(DAC_CHANNEL_2), .interval = 100, - .dig_clk.use_apll = false, // APB clk - .dig_clk.div_num = 79, - .dig_clk.div_b = 1, - .dig_clk.div_a = 0, .dac_dma_cnt = 4, .dac_dma_length = 128, - .dac_dma_link_type = DAC_DMA_LINK_LINE, + .dac_dma_link_type = DAC_DMA_LINK_RECURSIVE, }; dac_digi_initialize(&cfg); - dac_output_enable(DAC_CHANNEL_1); - dac_output_enable(DAC_CHANNEL_2); dac_dma_test_create_buffer(mode); dac_digi_start(); - dac_digi_write_bytes((uint8_t*)_buf); + uint32_t length = sizeof(_buf); + dac_digi_write_bytes(length, (uint8_t*)_buf, portMAX_DELAY); // /* Check interrupt type */ ESP_LOGI(TAG, "DAC-DMA intr test over"); @@ -127,87 +125,10 @@ void test_dac_dig_dma_intr_check(dac_digi_convert_mode_t mode) dac_digi_deinitialize(); } -TEST_CASE("DAC-DMA interrupt test", "[dac]") +TEST_CASE("DAC with DMA test", "[dac]") { - test_dac_dig_dma_intr_check(DAC_CONV_NORMAL); - test_dac_dig_dma_intr_check(DAC_CONV_ALTER); -} - -/**************************************************** - * The code below is used for legacy implementation - ***************************************************/ -#ifndef DAC_DMA_LEGACY_IMPL -#define DAC_DMA_LEGACY_IMPL 1 -#endif - -#if DAC_DMA_LEGACY_IMPL - -typedef struct dma_msg { - uint32_t int_msk; - uint8_t *data; - uint32_t data_len; -} dac_dma_event_t; - -static QueueHandle_t que_dac = NULL; -static uint8_t link_buf[2][SAR_SIMPLE_NUM*2] = {0}; -static lldesc_t dma1 = {0}; -static lldesc_t dma2 = {0}; - -/*******************************************/ -/** DAC-DMA INIT CODE */ -/*******************************************/ - -/** - * DMA liner initialization and start. - * @param is_loop - * - true: The two dma linked lists are connected end to end, with no end mark (eof). - * - false: The two dma linked lists are connected end to end, with end mark (eof). - * @param is_alter Is alter or not. - */ -uint32_t dac_dma_linker_init(bool is_alter, bool is_loop) -{ - /* The DAC output is a sawtooth wave. */ - if (is_alter) { - for(int i=0; idev, DAC_DMA_HAL_INTR); } -void dac_hal_digi_deinit(void) +bool dac_dma_hal_get_intr_status(dac_hal_context_t *hal) +{ + return spi_ll_get_intr(hal->dev, DAC_DMA_HAL_INTR); +} + + +void dac_dma_hal_init(dac_hal_context_t *hal) +{ + dac_ll_dma_clear_intr(hal->dev, DAC_DMA_HAL_INTR); + dac_ll_dma_enable_intr(hal->dev, DAC_DMA_HAL_INTR); + +} + +void dac_dma_hal_deinit(dac_hal_context_t *hal) { dac_ll_digi_trigger_output(false); dac_ll_digi_enable_dma(false); - dac_ll_digi_fifo_reset(); - dac_ll_digi_reset(); + dac_ll_dma_clear_intr(hal->dev, DAC_DMA_HAL_INTR); + dac_ll_dma_disable(hal->dev); } -void dac_hal_digi_controller_config(const dac_digi_config_t *cfg) +void dac_dma_hal_trans_start(dac_hal_context_t *hal, lldesc_t *desc) { + dac_ll_dma_reset(hal->dev, hal->dma_chan); + dac_ll_dma_fifo_reset(hal->dev); + dac_ll_dma_start(hal->dev, hal->dma_chan, desc); +} + +void dac_hal_digi_controller_configure(const dac_hal_ctrl_config_t *cfg) +{ + dac_ll_digi_clk_inv(true); dac_ll_digi_set_convert_mode(cfg->mode); dac_ll_digi_set_trigger_interval(cfg->interval); adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a); @@ -46,3 +76,24 @@ void dac_hal_digi_stop(void) dac_ll_digi_trigger_output(false); dac_ll_digi_enable_dma(false); } + +void __attribute__((deprecated)) dac_hal_digi_deinit(void) +{ + dac_ll_digi_trigger_output(false); + dac_ll_digi_enable_dma(false); + dac_ll_digi_fifo_reset(); + dac_ll_digi_reset(); +} + +void __attribute__((deprecated)) dac_hal_digi_controller_config(const dac_digi_config_t *cfg) +{ + dac_ll_digi_set_convert_mode(cfg->mode); + dac_ll_digi_set_trigger_interval(cfg->interval); + adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a); + adc_ll_digi_controller_clk_enable(cfg->dig_clk.use_apll); +} + +void __attribute__((deprecated)) dac_hal_digi_init(void) +{ + dac_ll_digi_clk_inv(true); +} diff --git a/components/hal/esp32s2/include/hal/dac_hal.h b/components/hal/esp32s2/include/hal/dac_hal.h index a7f4abce4c..947b563a12 100644 --- a/components/hal/esp32s2/include/hal/dac_hal.h +++ b/components/hal/esp32s2/include/hal/dac_hal.h @@ -1,16 +1,8 @@ -// Copyright 2019 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. +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -24,6 +16,8 @@ #include "hal/dac_ll.h" #include "hal/dac_types.h" +#include "hal/spi_ll.h" +#include "soc/lldesc.h" #include_next "hal/dac_hal.h" @@ -31,6 +25,19 @@ extern "C" { #endif +#define DAC_DMA_HAL_INTR (SPI_LL_INTR_OUT_TOTAL_EOF) + +typedef struct { + void *dev; + uint32_t dma_chan; +} dac_hal_context_t; + +typedef struct { + dac_digi_convert_mode_t mode; + uint32_t interval; +} dac_hal_ctrl_config_t; + + /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ @@ -49,7 +56,7 @@ void dac_hal_digi_deinit(void); * * @param cfg Pointer to digital controller paramter. */ -void dac_hal_digi_controller_config(const dac_digi_config_t *cfg); +void dac_hal_digi_controller_configure(const dac_hal_ctrl_config_t *ctrl_cfg); /** * DAC digital controller start output voltage. @@ -71,6 +78,51 @@ void dac_hal_digi_stop(void); */ #define dac_hal_digi_reset() dac_ll_digi_reset() +/******************************************************* + * DAC-DMA hal layer functions. + * On ESP32-S2, DAC shares the DMA with SPI3. +*******************************************************/ + +/** + * DAC DMA HAL initialization + * + * @param hal Context of the HAL layer + */ +void dac_dma_hal_init(dac_hal_context_t *hal); + +/** + * DAC DMA HAL interrupt clear. + * + * @param hal Context of the HAL layer + */ +void dac_dma_hal_clr_intr(dac_hal_context_t *hal); + +/** + * DAC DMA HAL transaction start. + * + * @param hal Context of the HAL layer + */ +void dac_dma_hal_trans_start(dac_hal_context_t *hal, lldesc_t *desc); + +/** + * Get if interrupt is triggered or not. + * + * @param hal Context of the HAL layer + * + * @return if the intr is triggered. 1: triggered, 0: not triggered. + */ +bool dac_dma_hal_get_intr_status(dac_hal_context_t *hal); + +/** + * DAC DMA HAL deinitialization + * + * @param hal Context of the HAL layer + */ +void dac_dma_hal_deinit(dac_hal_context_t *hal); + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +void __attribute__((deprecated)) dac_hal_digi_controller_config(const dac_digi_config_t *cfg); + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 13b862b5fd..65084c8d23 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -1290,11 +1290,6 @@ static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw) return hw->dma_int_raw.outfifo_empty_err; } -static inline uint32_t spi_ll_read_intr_status(spi_dev_t *hw) -{ - return hw->dma_int_st.val; -} - #undef SPI_LL_RST_MASK #undef SPI_LL_UNUSED_INT_MASK diff --git a/components/hal/include/hal/dac_hal.h b/components/hal/include/hal/dac_hal.h index ec2e8014b0..e0c4d9a23f 100644 --- a/components/hal/include/hal/dac_hal.h +++ b/components/hal/include/hal/dac_hal.h @@ -13,12 +13,6 @@ #pragma once #include "hal/dac_ll.h" -#if CONFIG_IDF_TARGET_ESP32S2 -#include "soc/spi_struct.h" -#include "hal/spi_ll.h" -#include "soc/spi_reg.h" -#include "soc/spi_periph.h" -#endif /** * Power on dac module and start output voltage. @@ -74,51 +68,3 @@ void dac_hal_cw_generator_config(dac_cw_config_t *cw); * Enable/disable DAC output data from DMA. */ #define dac_hal_digi_enable_dma(enable) dac_ll_digi_enable_dma(enable) - -#if CONFIG_IDF_TARGET_ESP32S2 -/******************************************************* - * DAC-DMA hal layer functions. - * On ESP32-S2, DAC shares the DMA with SPI3. -*******************************************************/ - -/** - * Read the interrupt status. - */ -#define dac_hal_digi_read_intr_status() spi_ll_read_intr_status(&GPSPI3) - -/** - * Clear the interrupt bit. - * @param mask spi-dma interrupt bit mask. - */ -#define dac_hal_digi_clear_intr(mask) spi_ll_clear_intr(&GPSPI3, mask) - -/** - * Enable interrupt - * @param mask spi-dma interrupt bit mask. - */ -#define dac_hal_digi_enable_intr(mask) spi_ll_enable_intr(&GPSPI3, mask) - -/** - * Disable dac dma - */ -#define dac_hal_dma_disable() spi_dma_ll_tx_disable(&GPSPI3) - -/** - * Reset dac dma - * @param chan the dma channel. - */ -#define dac_hal_dma_reset(chan) spi_dma_ll_tx_reset(&GPSPI3, chan) - -/** - * Start dac dma - * @param chan the dma channel. - * @param desc the pointer to the dma link. - */ -#define dac_hal_dma_start(chan, desc) spi_dma_ll_tx_start(&GPSPI3, chan, desc) - -/** - * Reset the dma fifo - */ -#define dac_hal_dma_fifo_reset() spi_ll_dma_tx_fifo_reset(&GPSPI3) - -#endif //CONFIG_IDF_TARGET_ESP32S2 diff --git a/components/hal/include/hal/dac_types.h b/components/hal/include/hal/dac_types.h index 587ea9e4ec..d52c72ed7c 100644 --- a/components/hal/include/hal/dac_types.h +++ b/components/hal/include/hal/dac_types.h @@ -70,9 +70,6 @@ typedef struct { Note: The sampling rate of each channel is also related to the conversion mode (See ``dac_digi_convert_mode_t``) and pattern table settings. */ adc_digi_clk_t dig_clk; /*!` and the :doc:`LED Control module `. Both these modules produce high frequency PDM/PWM output, which can be hardware low-pass filtered in order to generate a lower frequency analog output. @@ -40,35 +40,6 @@ Setting DAC channel 1 ({IDF_TARGET_DAC_CH_1}) voltage to approx 0.78 of VDD_A vo dac_output_voltage(DAC_CHANNEL_1, 200); -.. only:: esp32s2 - -For {IDF_TARGET_NAME}, DAC support to use DMA to send digital data to convert. Here is the example: - -.. code-block:: c - - #include - - const dac_digi_config_t cfg = { - .mode = mode, - .interval = 100, - .dig_clk.use_apll = false, // APB clk - .dig_clk.div_num = 79, // See comments `adc_digi_clk_t` - .dig_clk.div_b = 1, - .dig_clk.div_a = 0, - .dac_dma_cnt = 1, // The dac dma link number for your project - .dac_dma_length = 512, // The dac dam link length for your project. Should fit the buffer you prepared with dac_dma_cnt. - .dac_dma_link_type = DAC_DMA_LINK_RECURSIVE, //The link type. - }; - - dac_digi_initialize(&cfg); - dac_output_enable(DAC_CHANNEL_X); - dac_digi_start(); - dac_digi_write_bytes((uint8_t*)buffer_you_prepared); - dac_digi_stop(); - dac_digi_deinitialize(); - - - API Reference ------------- diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index fb6cabc244..bfefd9b15e 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -717,7 +717,7 @@ components/hal/esp32h2/include/hal/uhci_ll.h components/hal/esp32h2/include/hal/uhci_types.h components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h components/hal/esp32s2/include/hal/crypto_dma_ll.h -components/hal/esp32s2/include/hal/dac_hal.h +components/hal/esp32s2/include/hal/dac_ll.h components/hal/esp32s2/include/hal/dedic_gpio_ll.h components/hal/esp32s2/include/hal/mpu_ll.h components/hal/esp32s2/include/hal/sha_ll.h