Merge branch 'refactor/dac_common_lock_and_log' into 'master'

refactor(dac): split spinlock, update logging and memory management

See merge request espressif/esp-idf!51826
This commit is contained in:
morris
2026-08-18 22:11:22 +08:00
8 changed files with 96 additions and 105 deletions

View File

@@ -27,6 +27,7 @@ endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "./include"
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES ${priv_req}
REQUIRES esp_hal_ana_conv
LDFRAGMENTS "linker.lf"

View File

@@ -6,14 +6,24 @@
#include <stdint.h>
#include <string.h>
#include "stdatomic.h"
#include <stdatomic.h>
#include "dac_priv_common.h"
#include "freertos/FreeRTOS.h"
#include "hal/dac_periph.h"
#include "hal/dac_types.h"
#include "hal/dac_ll.h"
#include "esp_private/gpio.h"
#include "esp_check.h"
#include "dac_priv_common.h"
#include "esp_log.h"
#if ! (SOC_IS(ESP32) || SOC_IS(ESP32S2))
portMUX_TYPE dac_priv_spinlock = portMUX_INITIALIZER_UNLOCKED;
#endif // ! (SOC_IS(ESP32) || SOC_IS(ESP32S2))
/*---------------------------------------------------------------
Channel (analog pad) management
---------------------------------------------------------------*/
typedef enum {
DAC_CHAN_FSM_IDLE,
@@ -26,8 +36,6 @@ static _Atomic dac_channel_fsm_t s_dac_chan_fsm[SOC_DAC_CHAN_NUM] = {
[0 ... SOC_DAC_CHAN_NUM - 1] = DAC_CHAN_FSM_IDLE,
};
static const char *TAG = "dac_common";
esp_err_t dac_priv_register_channel(dac_channel_t chan_id)
{
ESP_RETURN_ON_FALSE(IS_VALID_DAC_CHANNEL(chan_id), ESP_ERR_INVALID_ARG, TAG, "channel id is invalid");
@@ -62,10 +70,10 @@ esp_err_t dac_priv_enable_channel(dac_channel_t chan_id)
if (atomic_compare_exchange_strong(&s_dac_chan_fsm[chan_id], &expected_fsm, DAC_CHAN_FSM_WAIT)) {
gpio_num_t gpio_num = (gpio_num_t)dac_periph_signal.dac_channel_io_num[chan_id];
gpio_config_as_analog(gpio_num);
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_power_on(chan_id);
dac_ll_rtc_sync_by_adc(false);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
atomic_store(&s_dac_chan_fsm[chan_id], DAC_CHAN_FSM_ENABLED);
return ESP_OK;
} else {
@@ -80,9 +88,9 @@ esp_err_t dac_priv_disable_channel(dac_channel_t chan_id)
dac_channel_fsm_t expected_fsm = DAC_CHAN_FSM_ENABLED;
if (atomic_compare_exchange_strong(&s_dac_chan_fsm[chan_id], &expected_fsm, DAC_CHAN_FSM_WAIT)) {
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_power_down(chan_id);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
atomic_store(&s_dac_chan_fsm[chan_id], DAC_CHAN_FSM_REGISTERED);
return ESP_OK;
} else {
@@ -90,3 +98,11 @@ esp_err_t dac_priv_disable_channel(dac_channel_t chan_id)
return ESP_ERR_INVALID_STATE;
}
}
#if CONFIG_DAC_ENABLE_DEBUG_LOG
__attribute__((constructor))
static void dac_override_default_log_level(void)
{
esp_log_level_set(TAG, ESP_LOG_DEBUG);
}
#endif

View File

@@ -4,27 +4,22 @@
* SPDX-License-Identifier: Apache-2.0
*/
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include <assert.h>
#include <stdatomic.h>
#include <string.h>
#include "dac_priv_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/idf_additions.h"
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "hal/dac_ll.h"
#include "driver/dac_continuous.h"
#include "esp_private/gdma_link.h"
#include "esp_check.h"
#include "dac_priv_common.h"
#include "esp_log.h"
#include "dac_priv_dma.h"
#if CONFIG_PM_ENABLE
@@ -33,12 +28,6 @@
#define DAC_DMA_MAX_BUF_SIZE 4092 // Max DMA buffer size is 4095 but better to align with 4 bytes, so set 4092 here
#if CONFIG_DAC_ISR_IRAM_SAFE || CONFIG_DAC_CTRL_FUNC_IN_IRAM
#define DAC_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define DAC_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
#if CONFIG_DAC_ISR_IRAM_SAFE
#define DAC_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
#else
@@ -84,8 +73,6 @@ typedef enum {
static _Atomic dac_continuous_fsm_t s_dac_cont_fsm = DAC_CONT_FSM_IDLE;
static const char *TAG = "dac_continuous";
static esp_err_t s_dac_continuous_stop_sync(dac_continuous_handle_t handle);
static void s_dac_free_dma_desc(dac_continuous_handle_t handle)
@@ -212,9 +199,6 @@ static void IRAM_ATTR s_dac_default_intr_handler(void *arg)
esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, dac_continuous_handle_t *ret_handle)
{
#if CONFIG_DAC_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
/* Parameters validation */
DAC_NULL_POINTER_CHECK(cont_cfg);
DAC_NULL_POINTER_CHECK(ret_handle);
@@ -276,9 +260,9 @@ esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, d
err1, TAG, "Failed to register DAC DMA interrupt");
/* Connect DAC module to the DMA peripheral */
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_digi_enable_dma(true);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
/* FSM: WAIT -> REGISTERED */
atomic_store(&s_dac_cont_fsm, DAC_CONT_FSM_REGISTERED);
@@ -334,9 +318,9 @@ esp_err_t dac_continuous_del_channels(dac_continuous_handle_t handle)
ESP_RETURN_ON_ERROR(dac_dma_periph_deinit(), TAG, "Failed to deinitialize DAC DMA peripheral");
/* Disconnect DAC module from the DMA peripheral */
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_digi_enable_dma(false);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
/* Free allocated resources */
s_dac_free_dma_desc(handle);
@@ -416,9 +400,9 @@ esp_err_t dac_continuous_enable(dac_continuous_handle_t handle)
dac_dma_periph_enable();
esp_intr_enable(handle->intr_handle);
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_digi_enable_dma(true);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
/* FSM: WAIT -> ENABLED */
atomic_store(&s_dac_cont_fsm, DAC_CONT_FSM_ENABLED);
@@ -448,9 +432,9 @@ esp_err_t dac_continuous_disable(dac_continuous_handle_t handle)
dac_dma_periph_disable();
esp_intr_disable(handle->intr_handle);
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
dac_ll_digi_enable_dma(false);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
DAC_CHANNEL_MASK_FOREACH(chan, handle->cfg.chan_mask) {
dac_priv_disable_channel(chan);

View File

@@ -5,28 +5,19 @@
*/
#include <string.h>
#include "dac_priv_common.h"
#include "driver/dac_cosine.h"
#include "hal/clk_tree_ll.h"
#include "dac_priv_common.h"
#include "hal/dac_ll.h"
#include "esp_clk_tree.h"
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "esp_check.h"
#if CONFIG_PM_ENABLE
#include "esp_pm.h"
#endif
#include "esp_log.h"
struct dac_cosine_s {
dac_cosine_config_t cfg; /*!< Cosine mode configurations */
bool is_started; /*!< Flag: is the channel started(not cosine wave generator) */
};
static const char *TAG = "dac_cosine";
/* Cosine wave generator reference count
* The cosine wave generator is shared by dac channels */
static uint32_t s_cwg_refer_cnt = 0;
@@ -36,9 +27,6 @@ static uint32_t s_cwg_freq = 0;
esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_handle_t *ret_handle)
{
#if CONFIG_DAC_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
/* Parameters validation */
DAC_NULL_POINTER_CHECK(cos_cfg);
DAC_NULL_POINTER_CHECK(ret_handle);
@@ -49,7 +37,7 @@ esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_
esp_err_t ret = ESP_OK;
/* Allocate cosine handle */
dac_cosine_handle_t handle = heap_caps_calloc(1, sizeof(struct dac_cosine_s), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
dac_cosine_handle_t handle = heap_caps_calloc(1, sizeof(struct dac_cosine_s), DAC_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(handle, ESP_ERR_NO_MEM, TAG, "no memory for the dac cosine handle");
/* Assign configurations */
handle->cfg = *cos_cfg;
@@ -64,7 +52,7 @@ esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_
ESP_LOGW(TAG, "RTC clock calibration failed, using the approximate value as default");
rtc_clk_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
}
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
/* Set coefficients for cosine wave generator */
if ((!s_cwg_freq) || cos_cfg->flags.force_set_freq) {
dac_ll_cw_set_freq(cos_cfg->freq_hz, rtc_clk_freq);
@@ -73,7 +61,7 @@ esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_
dac_ll_cw_set_atten(cos_cfg->chan_id, cos_cfg->atten);
dac_ll_cw_set_phase(cos_cfg->chan_id, cos_cfg->phase);
dac_ll_cw_set_dc_offset(cos_cfg->chan_id, cos_cfg->offset);
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
*ret_handle = handle;
return ret;
@@ -112,7 +100,7 @@ esp_err_t dac_cosine_start(dac_cosine_handle_t handle)
ESP_GOTO_ON_ERROR(dac_priv_enable_channel(handle->cfg.chan_id), err, TAG,
"enable dac channel %d failed", handle->cfg.chan_id);
/* Enabled the cosine wave generator if no channel using it before */
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
if (s_cwg_refer_cnt == 0) {
dac_ll_cw_generator_enable();
}
@@ -120,7 +108,7 @@ esp_err_t dac_cosine_start(dac_cosine_handle_t handle)
dac_ll_cw_enable_channel(handle->cfg.chan_id, true);
s_cwg_refer_cnt++;
handle->is_started = true;
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
return ESP_OK;
@@ -138,7 +126,7 @@ esp_err_t dac_cosine_stop(dac_cosine_handle_t handle)
/* Enabled DAC channel */
ESP_RETURN_ON_ERROR(dac_priv_disable_channel(handle->cfg.chan_id), TAG,
"disable dac channel %d failed", handle->cfg.chan_id);
DAC_RTC_ENTER_CRITICAL();
DAC_ENTER_CRITICAL();
/* Disconnect the DAC channel from the cosine wave generator */
dac_ll_cw_enable_channel(handle->cfg.chan_id, false);
s_cwg_refer_cnt--;
@@ -147,7 +135,7 @@ esp_err_t dac_cosine_stop(dac_cosine_handle_t handle)
dac_ll_cw_generator_disable();
}
handle->is_started = false;
DAC_RTC_EXIT_CRITICAL();
DAC_EXIT_CRITICAL();
/* Release the RTC clock */
ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, false), TAG, "RC_FAST clock disable failed");

View File

@@ -7,28 +7,16 @@
#include <string.h>
#include "dac_priv_common.h"
#include "driver/dac_oneshot.h"
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "hal/dac_ll.h"
#include "esp_check.h"
#if CONFIG_PM_ENABLE
#include "esp_pm.h"
#endif
#include "esp_log.h"
struct dac_oneshot_s {
dac_oneshot_config_t cfg; /*!< Oneshot mode configurations */
};
static const char *TAG = "dac_oneshot";
esp_err_t dac_oneshot_new_channel(const dac_oneshot_config_t *oneshot_cfg, dac_oneshot_handle_t *ret_handle)
{
#if CONFIG_DAC_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
/* Parameters validation */
DAC_NULL_POINTER_CHECK(oneshot_cfg);
DAC_NULL_POINTER_CHECK(ret_handle);
@@ -36,7 +24,7 @@ esp_err_t dac_oneshot_new_channel(const dac_oneshot_config_t *oneshot_cfg, dac_o
esp_err_t ret = ESP_OK;
/* Resources allocation */
dac_oneshot_handle_t handle = heap_caps_calloc(1, sizeof(struct dac_oneshot_s), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
dac_oneshot_handle_t handle = heap_caps_calloc(1, sizeof(struct dac_oneshot_s), DAC_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(handle, ESP_ERR_NO_MEM, TAG, "no memory for the dac oneshot handle");
handle->cfg = *oneshot_cfg;
@@ -75,9 +63,9 @@ esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_v
}
/* Set the voltage by the digital value */
DAC_RTC_ENTER_CRITICAL_SAFE();
DAC_ENTER_CRITICAL_SAFE();
dac_ll_update_output_value(handle->cfg.chan_id, digi_value);
DAC_RTC_EXIT_CRITICAL_SAFE();
DAC_EXIT_CRITICAL_SAFE();
return ESP_OK;
}

View File

@@ -6,26 +6,56 @@
#pragma once
#include "sdkconfig.h"
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for DAC driver
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "freertos/FreeRTOS.h"
#include "hal/dac_types.h"
#include "hal/dac_ll.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_err.h"
#include "esp_heap_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
extern portMUX_TYPE rtc_spinlock; /*!< Extern global rtc spinlock */
ESP_LOG_ATTR_TAG(TAG, "dac");
#define DAC_RTC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define DAC_RTC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
/**
* DAC driver spinlock
*
* - ESP32 / ESP32-S2: use the global rtc_spinlock
* - ESP32-S31: dedicated DAC register block, use dac_priv_spinlock
*/
#if SOC_IS(ESP32) || SOC_IS(ESP32S2)
extern portMUX_TYPE rtc_spinlock;
#define DAC_RTC_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&rtc_spinlock)
#define DAC_RTC_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&rtc_spinlock)
#define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
#define DAC_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&rtc_spinlock)
#define DAC_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&rtc_spinlock)
#else
extern portMUX_TYPE dac_priv_spinlock;
#define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&dac_priv_spinlock)
#define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&dac_priv_spinlock)
#define DAC_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&dac_priv_spinlock)
#define DAC_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&dac_priv_spinlock)
#endif // SOC_IS(ESP32) || SOC_IS(ESP32S2)
#define DAC_NULL_POINTER_CHECK(p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, TAG, "input parameter '"#p"' is NULL")
#define DAC_NULL_POINTER_CHECK_ISR(p) ESP_RETURN_ON_FALSE_ISR((p), ESP_ERR_INVALID_ARG, TAG, "input parameter '"#p"' is NULL")
#if CONFIG_DAC_ISR_IRAM_SAFE || CONFIG_DAC_CTRL_FUNC_IN_IRAM
#define DAC_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define DAC_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
/**
* @brief Register dac channel in the driver, in case a same channel is reused by different modes
*

View File

@@ -12,6 +12,7 @@
* DAC digital controller clock source: I2S ws signal (root clock: D2PLL or APLL)
*/
#include "dac_priv_common.h"
#include "freertos/FreeRTOS.h"
#include "sdkconfig.h"
#include "hal/adc_ll.h"
@@ -19,15 +20,11 @@
#include "hal/i2s_types.h"
#include "hal/clk_tree_ll.h"
#include "hal/i2s_periph.h"
#include "../dac_priv_dma.h"
#include "dac_priv_dma.h"
#include "esp_private/i2s_platform.h"
#include "esp_private/esp_clk.h"
#include "esp_clk_tree.h"
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "esp_log.h"
#include "esp_check.h"
#include "esp_attr.h"
@@ -42,8 +39,6 @@ typedef struct {
static dac_dma_periph_i2s_t *s_ddp = NULL; // Static DAC DMA peripheral structure pointer
static const char *TAG = "DAC_DMA";
static uint32_t s_dac_set_apll_freq(uint32_t mclk)
{
/* Calculate the expected APLL */
@@ -108,14 +103,11 @@ static esp_err_t s_dac_dma_periph_set_clock(uint32_t freq_hz, bool is_apll)
esp_err_t dac_dma_periph_init(uint32_t freq_hz, bool is_alternate, bool is_apll)
{
#if CONFIG_DAC_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
/* Acquire DMA peripheral */
ESP_RETURN_ON_ERROR(i2s_platform_acquire_occupation(I2S_CTLR_HP, DAC_DMA_PERIPH_I2S_NUM, "dac_dma"), TAG, "Failed to acquire DAC DMA peripheral");
/* Allocate DAC DMA peripheral object */
s_ddp = (dac_dma_periph_i2s_t *)heap_caps_calloc(1, sizeof(dac_dma_periph_i2s_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
s_ddp = (dac_dma_periph_i2s_t *)heap_caps_calloc(1, sizeof(dac_dma_periph_i2s_t), DAC_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(s_ddp, ESP_ERR_NO_MEM, err, TAG, "No memory for DAC DMA object");
s_ddp->periph_dev = (void *)I2S_LL_GET_HW(DAC_DMA_PERIPH_I2S_NUM);

View File

@@ -12,6 +12,7 @@
* DAC digital controller clock source: DIG_SARADC_CLK (root clock: APB or APLL)
*/
#include "dac_priv_common.h"
#include "sdkconfig.h"
#include "esp_private/spi_common_internal.h"
#include "esp_private/periph_ctrl.h"
@@ -24,13 +25,9 @@
#include "soc/lldesc.h"
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "../dac_priv_dma.h"
#include "dac_priv_dma.h"
#include "esp_clk_tree.h"
#if CONFIG_DAC_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "esp_log.h"
#include "esp_check.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
@@ -46,8 +43,6 @@ typedef struct {
static dac_dma_periph_spi_t *s_ddp = NULL; // Static DAC DMA peripheral structure pointer
static const char *TAG = "DAC_DMA";
static uint32_t s_dac_set_apll_freq(uint32_t expt_freq)
{
/* Set APLL coefficients to the given frequency */
@@ -125,15 +120,12 @@ static esp_err_t s_dac_dma_periph_set_clock(uint32_t freq_hz, bool is_apll)
esp_err_t dac_dma_periph_init(uint32_t freq_hz, bool is_alternate, bool is_apll)
{
#if CONFIG_DAC_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
/* Acquire DMA peripheral */
ESP_RETURN_ON_FALSE(spicommon_periph_claim(DAC_DMA_PERIPH_SPI_HOST, "dac_dma"), ESP_ERR_NOT_FOUND, TAG, "Failed to acquire DAC DMA peripheral");
adc_apb_periph_claim();
/* Allocate DAC DMA peripheral object */
s_ddp = (dac_dma_periph_spi_t *)heap_caps_calloc(1, sizeof(dac_dma_periph_spi_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
s_ddp = (dac_dma_periph_spi_t *)heap_caps_calloc(1, sizeof(dac_dma_periph_spi_t), DAC_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(s_ddp, ESP_ERR_NO_MEM, err, TAG, "No memory for DAC DMA object");
s_ddp->periph_dev = (void *)SPI_LL_GET_HW(DAC_DMA_PERIPH_SPI_HOST);