Merge branch 'esp32p4/add_adc_support_v5.3' into 'release/v5.3'

feat(adc): support ADC oneshot/continuous mode on ESP32P4(v5.3)

See merge request espressif/esp-idf!31367
This commit is contained in:
morris
2024-06-13 11:00:59 +08:00
52 changed files with 1604 additions and 192 deletions

View File

@ -9,7 +9,7 @@
#include "soc/pmu_reg.h"
#include "soc/regi2c_saradc.h"
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/rtcadc_reg.h"
#include "soc/lp_adc_reg.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp_rom_regi2c.h"

View File

@ -57,7 +57,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
#define INTERNAL_BUF_NUM 5
#if SOC_AHB_GDMA_VERSION == 1
#if SOC_AHB_GDMA_SUPPORTED
#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
@ -434,7 +434,10 @@ esp_err_t adc_digi_start(void)
return ESP_ERR_INVALID_STATE;
}
//reset ADC digital part to reset ADC sampling EOF counter
periph_module_reset(PERIPH_SARADC_MODULE);
ADC_BUS_CLK_ATOMIC() {
adc_ll_reset_register();
}
sar_periph_ctrl_adc_continuous_power_acquire();
//reset flags
s_adc_digi_ctx->ringbuf_overflow_flag = 0;

View File

@ -70,7 +70,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
#define FSM_ENTER() RTC_ENTER_CRITICAL()
#define FSM_EXIT() RTC_EXIT_CRITICAL()
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
//prevent ADC1 being used by I2S dma and other tasks at the same time.
static _lock_t adc1_dma_lock;
#define SARADC1_ACQUIRE() _lock_acquire( &adc1_dma_lock )
@ -172,7 +172,7 @@ static void adc_rtc_chan_init(adc_unit_t adc_unit)
esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
{
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(adc_unit), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
#if ADC_LL_RTC_GPIO_SUPPORTED
gpio_num_t gpio_num = 0;
//If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run
if (adc_unit == ADC_UNIT_1) {
@ -188,7 +188,7 @@ esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
ESP_RETURN_ON_ERROR(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED), ADC_TAG, "rtc_gpio_set_direction fail");
ESP_RETURN_ON_ERROR(rtc_gpio_pulldown_dis(gpio_num), ADC_TAG, "rtc_gpio_pulldown_dis fail");
ESP_RETURN_ON_ERROR(rtc_gpio_pullup_dis(gpio_num), ADC_TAG, "rtc_gpio_pullup_dis fail");
#endif
return ESP_OK;
}
@ -571,7 +571,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
#endif
adc_oneshot_ll_set_output_bits(ADC_UNIT_2, bitwidth);
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32P4
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_RTC);// set controller
#else
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_ARB);// set controller

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -81,6 +81,18 @@ typedef enum {
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO6 */
ADC1_CHANNEL_MAX,
} adc1_channel_t;
#elif CONFIG_IDF_TARGET_ESP32P4
typedef enum {
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO16 */
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO17 */
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO18 */
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO19 */
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO20 */
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO21 */
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO22 */
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO23 */
ADC1_CHANNEL_MAX,
} adc1_channel_t;
#endif // CONFIG_IDF_TARGET_*
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
@ -103,6 +115,17 @@ typedef enum {
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
ADC2_CHANNEL_MAX,
} adc2_channel_t;
#elif CONFIG_IDF_TARGET_ESP32P4
typedef enum {
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO49 */
ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO50 */
ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO51 */
ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO52 */
ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO53 */
ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO54 */
ADC2_CHANNEL_MAX,
} adc2_channel_t;
#endif
#if SOC_ADC_DMA_SUPPORTED

View File

@ -17,6 +17,10 @@ components/driver/test_apps/i2s_test_apps/legacy_i2s_driver:
components/driver/test_apps/legacy_adc_driver:
disable:
- if: SOC_ADC_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners, TODO IDF-9573
depends_components:
- efuse
- esp_driver_i2s

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -67,6 +67,13 @@
#define ADC_TEST_HIGH_VAL 3390
#define ADC_TEST_HIGH_THRESH 200
#elif CONFIG_IDF_TARGET_ESP32P4
#define ADC_TEST_LOW_VAL 3100
#define ADC_TEST_LOW_THRESH 200
#define ADC_TEST_HIGH_VAL 4095
#define ADC_TEST_HIGH_THRESH 200
#endif
//ADC Channels

View File

@ -1,6 +1,5 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut

View File

@ -53,5 +53,5 @@ endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
PRIV_REQUIRES driver esp_driver_gpio efuse esp_pm esp_ringbuf
PRIV_REQUIRES driver esp_driver_gpio efuse esp_pm esp_ringbuf esp_mm
LDFRAGMENTS linker.lf)

View File

@ -37,6 +37,11 @@
#include "adc_continuous_internal.h"
#include "esp_private/adc_dma.h"
#include "adc_dma_internal.h"
#include "esp_dma_utils.h"
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "esp_cache.h"
#include "esp_private/esp_cache_private.h"
#endif
static const char *ADC_TAG = "adc_continuous";
@ -66,6 +71,12 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx)
if (status != ADC_HAL_DMA_DESC_VALID) {
break;
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
else {
esp_err_t msync_ret = esp_cache_msync((void *)finished_buffer, finished_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(msync_ret == ESP_OK);
}
#endif
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
need_yield |= (taskAwoken == pdTRUE);
@ -108,7 +119,10 @@ static IRAM_ATTR bool adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx)
}
}
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_err_t msync_ret = esp_cache_msync((void *)(adc_digi_ctx->hal.rx_desc), adc_digi_ctx->adc_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(msync_ret == ESP_OK);
#endif
return need_yield;
}
@ -178,7 +192,11 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi
}
//malloc internal buffer used by DMA
adc_ctx->rx_dma_buf = heap_caps_calloc(1, hdl_config->conv_frame_size * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
esp_dma_mem_info_t dma_mem_info = {
.extra_heap_caps = (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA),
.dma_alignment_bytes = 4,
};
esp_dma_capable_calloc(1, hdl_config->conv_frame_size * INTERNAL_BUF_NUM, &dma_mem_info, (void **)&adc_ctx->rx_dma_buf, NULL);
if (!adc_ctx->rx_dma_buf) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
@ -187,7 +205,7 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi
//malloc dma descriptor
uint32_t dma_desc_num_per_frame = (hdl_config->conv_frame_size + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
uint32_t dma_desc_max_num = dma_desc_num_per_frame * INTERNAL_BUF_NUM;
adc_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * dma_desc_max_num, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
esp_dma_capable_calloc(1, (sizeof(dma_descriptor_t)) * dma_desc_max_num, &dma_mem_info, (void **)&adc_ctx->hal.rx_desc, &adc_ctx->adc_desc_size);
if (!adc_ctx->hal.rx_desc) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
@ -245,7 +263,9 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "ADC continuous mode isn't in the init state, it's started already");
//reset ADC digital part to reset ADC sampling EOF counter
periph_module_reset(PERIPH_SARADC_MODULE);
ADC_BUS_CLK_ATOMIC() {
adc_ll_reset_register();
}
if (handle->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(handle->pm_lock), ADC_TAG, "acquire pm_lock failed");
@ -295,6 +315,10 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
adc_dma_reset(handle->adc_dma);
adc_hal_digi_reset();
adc_hal_digi_dma_link(&handle->hal, handle->rx_dma_buf);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_err_t ret = esp_cache_msync(handle->hal.rx_desc, handle->adc_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
adc_dma_start(handle->adc_dma, handle->hal.rx_desc);
adc_hal_digi_connect(true);

View File

@ -99,6 +99,7 @@ struct adc_continuous_ctx_t {
#if SOC_ADC_MONITOR_SUPPORTED
adc_monitor_t *adc_monitor[SOC_ADC_DIGI_MONITOR_NUM]; // adc monitor context
#endif
size_t adc_desc_size;
adc_dma_t adc_dma;
adc_dma_intr_func_t adc_intr_func;
};

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -115,7 +115,6 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
};
adc_oneshot_hal_init(&(unit->hal), &config);
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
//To enable the APB_SARADC periph if needed
_lock_acquire(&s_ctx.mutex);
s_ctx.apb_periph_ref_cnts++;
@ -123,12 +122,13 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
adc_apb_periph_claim();
}
_lock_release(&s_ctx.mutex);
#endif
if (init_config->ulp_mode == ADC_ULP_MODE_DISABLE) {
sar_periph_ctrl_adc_oneshot_power_acquire();
} else {
#if !CONFIG_IDF_TARGET_ESP32P4 // # TODO: IDF-7528, IDF-7529
esp_sleep_enable_adc_tsens_monitor(true);
#endif
}
ESP_LOGD(TAG, "new adc unit%"PRId32" is created", unit->unit_id);
@ -229,7 +229,9 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle)
if (ulp_mode == ADC_ULP_MODE_DISABLE) {
sar_periph_ctrl_adc_oneshot_power_release();
} else {
#if !CONFIG_IDF_TARGET_ESP32P4 // # TODO: IDF-7528, IDF-7529
esp_sleep_enable_adc_tsens_monitor(false);
#endif
}
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
@ -262,7 +264,7 @@ static esp_err_t s_adc_io_init(adc_unit_t unit, adc_channel_t channel)
{
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(unit), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
#if !ADC_LL_RTC_GPIO_SUPPORTED
uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
gpio_config_t cfg = {

View File

@ -4,6 +4,10 @@ components/esp_adc/test_apps/adc:
disable:
- if: SOC_ADC_SUPPORTED != 1
- if: CONFIG_NAME == "gdma_iram_safe" and IDF_TARGET in ["esp32", "esp32s2", "esp32c2"]
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: not runners for ESP32P4 ADC # TODO: IDF-9573
depends_components:
- esp_adc
- esp_driver_gpio

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -13,6 +13,7 @@
#include "driver/rtc_io.h"
#include "soc/adc_periph.h"
#include "test_common_adc.h"
#include "hal/adc_ll.h"
__attribute__((unused)) static const char *TAG = "TEST_ADC";
@ -98,7 +99,7 @@ void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level)
{
TEST_ASSERT(channel < SOC_ADC_CHANNEL_NUM(unit) && "invalid channel");
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
#if !ADC_LL_RTC_GPIO_SUPPORTED
uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY : GPIO_PULLDOWN_ONLY)));
#else

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -86,6 +86,14 @@ extern "C" {
#define ADC_TEST_HIGH_VAL 3390
#define ADC_TEST_HIGH_VAL_DMA 4081
#define ADC_TEST_HIGH_THRESH 200
#elif CONFIG_IDF_TARGET_ESP32P4
#define ADC_TEST_LOW_VAL 3100
#define ADC_TEST_LOW_THRESH 200
#define ADC_TEST_HIGH_VAL 4095
#define ADC_TEST_HIGH_VAL_DMA 4095
#define ADC_TEST_HIGH_THRESH 200
#endif
/*---------------------------------------------------------------

View File

@ -12,7 +12,7 @@
*
* However, usages of above components are different.
* Therefore, we put the common used parts into `esp_hw_support`, including:
* - adc power maintainance
* - adc power maintenance
* - adc hw calibration settings
* - adc locks, to prevent concurrently using adc hw
*/
@ -205,10 +205,10 @@ void adc_apb_periph_claim(void)
portENTER_CRITICAL(&s_spinlock);
s_adc_digi_ctrlr_cnt++;
if (s_adc_digi_ctrlr_cnt == 1) {
//enable ADC digital part
periph_module_enable(PERIPH_SARADC_MODULE);
//reset ADC digital part
periph_module_reset(PERIPH_SARADC_MODULE);
ADC_BUS_CLK_ATOMIC() {
adc_ll_enable_bus_clock(true);
adc_ll_reset_register();
}
}
portEXIT_CRITICAL(&s_spinlock);
@ -219,7 +219,9 @@ void adc_apb_periph_free(void)
portENTER_CRITICAL(&s_spinlock);
s_adc_digi_ctrlr_cnt--;
if (s_adc_digi_ctrlr_cnt == 0) {
periph_module_disable(PERIPH_SARADC_MODULE);
ADC_BUS_CLK_ATOMIC() {
adc_ll_enable_bus_clock(false);
}
} else if (s_adc_digi_ctrlr_cnt < 0) {
portEXIT_CRITICAL(&s_spinlock);
ESP_LOGE(TAG, "%s called, but `s_adc_digi_ctrlr_cnt == 0`", __func__);

View File

@ -12,7 +12,7 @@
*
* However, usages of above components are different.
* Therefore, we put the common used parts into `esp_hw_support`, including:
* - adc power maintainance
* - adc power maintenance
* - adc hw calibration settings
* - adc locks, to prevent concurrently using adc hw
*/
@ -26,6 +26,12 @@
extern "C" {
#endif
#if SOC_RCC_IS_INDEPENDENT || CONFIG_IDF_TARGET_ESP32
#define ADC_BUS_CLK_ATOMIC()
#else
#define ADC_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC()
#endif
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration

View File

@ -10,7 +10,8 @@ set(srcs "rtc_clk_init.c"
)
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_crypto_lock.c")
list(APPEND srcs "sar_periph_ctrl.c"
"esp_crypto_lock.c")
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi_timing_config.c")

View File

@ -0,0 +1,116 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* SAR related peripherals are interdependent. This file
* provides a united control to these registers, as multiple
* components require these controls.
*
* Related peripherals are:
* - ADC
* - PWDET
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "esp_private/sar_periph_ctrl.h"
#include "esp_private/esp_modem_clock.h"
#include "hal/sar_ctrl_ll.h"
static const char *TAG = "sar_periph_ctrl";
extern portMUX_TYPE rtc_spinlock;
void sar_periph_ctrl_init(void)
{
//Put SAR control mux to FSM state
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_FSM);
}
void sar_periph_ctrl_power_enable(void)
{
portENTER_CRITICAL_SAFE(&rtc_spinlock);
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_FSM);
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
}
void sar_periph_ctrl_power_disable(void)
{
portENTER_CRITICAL_SAFE(&rtc_spinlock);
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_OFF);
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
}
/**
* This gets incremented when s_sar_power_acquire() is called,
* and decremented when s_sar_power_release() is called.
* PWDET is powered down when the value reaches zero.
* Should be modified within critical section.
*/
static int s_sar_power_on_cnt;
static void s_sar_power_acquire(void)
{
portENTER_CRITICAL_SAFE(&rtc_spinlock);
s_sar_power_on_cnt++;
if (s_sar_power_on_cnt == 1) {
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_ON);
}
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
}
static void s_sar_power_release(void)
{
portENTER_CRITICAL_SAFE(&rtc_spinlock);
s_sar_power_on_cnt--;
if (s_sar_power_on_cnt < 0) {
portEXIT_CRITICAL(&rtc_spinlock);
ESP_LOGE(TAG, "%s called, but s_sar_power_on_cnt == 0", __func__);
abort();
} else if (s_sar_power_on_cnt == 0) {
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_FSM);
}
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
}
/*------------------------------------------------------------------------------
* PWDET Power
*----------------------------------------------------------------------------*/
void sar_periph_ctrl_pwdet_power_acquire(void)
{
s_sar_power_acquire();
}
void sar_periph_ctrl_pwdet_power_release(void)
{
s_sar_power_release();
}
/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
void sar_periph_ctrl_adc_oneshot_power_acquire(void)
{
s_sar_power_acquire();
}
void sar_periph_ctrl_adc_oneshot_power_release(void)
{
s_sar_power_release();
}
void sar_periph_ctrl_adc_continuous_power_acquire(void)
{
s_sar_power_acquire();
}
void sar_periph_ctrl_adc_continuous_power_release(void)
{
s_sar_power_release();
}

View File

@ -663,7 +663,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(bool deep_sleep)
#endif
}
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-6496
#if !CONFIG_IDF_TARGET_ESP32P4
// TODO: IDF-7370
if (!(deep_sleep && s_adc_tsen_enabled)){
sar_periph_ctrl_power_disable();
@ -679,11 +679,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(void)
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
sleep_console_usj_pad_restore();
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-6496
sar_periph_ctrl_power_enable();
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
sleep_disable_cpu_retention();
#endif

View File

@ -74,6 +74,10 @@ void adc_hal_digi_init(adc_hal_dma_ctx_t *hal)
void adc_hal_digi_deinit()
{
#if ADC_LL_POWER_MANAGE_SUPPORTED
adc_ll_set_power_manage(ADC_UNIT_1, ADC_LL_POWER_SW_OFF);
adc_ll_set_power_manage(ADC_UNIT_2, ADC_LL_POWER_SW_OFF);
#endif
adc_ll_digi_trigger_disable();
adc_ll_digi_dma_disable();
adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
@ -144,6 +148,9 @@ void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_c
for (int i = 0; i < cfg->adc_pattern_len; i++) {
adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]);
}
#if ADC_LL_POWER_MANAGE_SUPPORTED
adc_ll_set_power_manage(0, ADC_LL_POWER_SW_ON);
#endif
#elif (SOC_ADC_DIGI_CONTROLLER_NUM >= 2)
uint32_t adc1_pattern_idx = 0;
@ -154,9 +161,15 @@ void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_c
for (int i = 0; i < cfg->adc_pattern_len; i++) {
if (cfg->adc_pattern[i].unit == ADC_UNIT_1) {
#if ADC_LL_POWER_MANAGE_SUPPORTED
adc_ll_set_power_manage(ADC_UNIT_1, ADC_LL_POWER_SW_ON);
#endif
adc_ll_digi_set_pattern_table(ADC_UNIT_1, adc1_pattern_idx, cfg->adc_pattern[i]);
adc1_pattern_idx++;
} else if (cfg->adc_pattern[i].unit == ADC_UNIT_2) {
#if ADC_LL_POWER_MANAGE_SUPPORTED
adc_ll_set_power_manage(ADC_UNIT_2, ADC_LL_POWER_SW_ON);
#endif
adc_ll_digi_set_pattern_table(ADC_UNIT_2, adc2_pattern_idx, cfg->adc_pattern[i]);
adc2_pattern_idx++;
} else {

View File

@ -142,7 +142,7 @@ bool adc_oneshot_hal_convert(adc_oneshot_hal_ctx_t *hal, int *out_raw)
}
esp_rom_delay_us(read_delay_us);
*out_raw = adc_oneshot_ll_get_raw_result(hal->unit);
#if (SOC_ADC_PERIPH_NUM == 2)
#if SOC_ADC_ARBITER_SUPPORTED
if (hal->unit == ADC_UNIT_2) {
valid = adc_oneshot_ll_raw_check_valid(ADC_UNIT_2, *out_raw);
if (!valid) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -31,6 +31,7 @@ extern "C" {
#define ADC_LL_DATA_INVERT_DEFAULT(PERIPH_NUM) (1)
#define ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (1)
#define ADC_LL_DELAY_CYCLE_AFTER_DONE_SIGNAL (0)
#define ADC_LL_RTC_GPIO_SUPPORTED (1)
/*---------------------------------------------------------------
DMA
@ -229,7 +230,7 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t
}
/**
* Set pattern table lenth for digital controller.
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself.
@ -564,6 +565,25 @@ static inline void adc_oneshot_ll_disable_all_unit(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
(void)enable;
//For compatibility
}
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
//For compatibility
}
/**
* Set ADC module controller.
* There are five SAR ADC controllers:

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,6 +15,7 @@
#include "soc/rtc_cntl_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/system_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/adc_types.h"
@ -286,6 +287,29 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
SYSTEM.perip_clk_en0.apb_saradc_clk_en = enable;
}
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
SYSTEM.perip_rst_en0.apb_saradc_rst = 1;
SYSTEM.perip_rst_en0.apb_saradc_rst = 0;
}
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_reset_register(__VA_ARGS__)
/**
* Set ADC module power management.
*

View File

@ -15,6 +15,7 @@
#include "soc/rtc_cntl_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/system_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/adc_types.h"
@ -560,6 +561,29 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
SYSTEM.perip_clk_en0.reg_apb_saradc_clk_en = enable;
}
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
SYSTEM.perip_rst_en0.reg_apb_saradc_rst = 1;
SYSTEM.perip_rst_en0.reg_apb_saradc_rst = 0;
}
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_reset_register(__VA_ARGS__)
/**
* Set ADC module power management.
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -59,6 +59,7 @@ extern "C" {
#define ADC_LL_DEFAULT_CONV_LIMIT_EN 0
#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10
#define ADC_LL_POWER_MANAGE_SUPPORTED 1 //ESP32C6 supported to manage power mode
/*---------------------------------------------------------------
PWDET (Power Detect)
---------------------------------------------------------------*/
@ -554,13 +555,33 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
PCR.saradc_conf.saradc_reg_clk_en = enable;
}
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
PCR.saradc_conf.saradc_reg_rst_en = 1;
PCR.saradc_conf.saradc_reg_rst_en = 0;
}
/**
* Set ADC module power management.
*
* @param manage Set ADC power status.
*/
static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
static inline void adc_ll_set_power_manage(adc_unit_t adc_n, adc_ll_power_t manage)
{
(void) adc_n;
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {

View File

@ -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
*/
@ -60,6 +60,7 @@ extern "C" {
#define ADC_LL_DEFAULT_CONV_LIMIT_EN 0
#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10
#define ADC_LL_POWER_MANAGE_SUPPORTED 1 //ESP32H2 supported to manage power mode
/*---------------------------------------------------------------
PWDET (Power Detect)
---------------------------------------------------------------*/
@ -555,13 +556,32 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
PCR.saradc_conf.saradc_reg_clk_en = enable;
}
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
PCR.saradc_conf.saradc_reg_rst_en = 1;
PCR.saradc_conf.saradc_reg_rst_en = 0;
}
/**
* Set ADC module power management.
*
* @param manage Set ADC power status.
*/
static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
static inline void adc_ll_set_power_manage(adc_unit_t adc_n, adc_ll_power_t manage)
{
(void) adc_n;
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {

View File

@ -0,0 +1,913 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "soc/adc_periph.h"
#include "soc/adc_struct.h"
#include "soc/clk_tree_defs.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/lpperi_struct.h"
#include "soc/regi2c_saradc.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/adc_types.h"
#include "hal/adc_types_private.h"
#include "hal/regi2c_ctrl.h"
#include "hal/sar_ctrl_ll.h"
#include "soc/lp_adc_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ADC_LL_EVENT_ADC1_ONESHOT_DONE BIT(31)
#define ADC_LL_EVENT_ADC2_ONESHOT_DONE BIT(30)
#define LP_ADC_FORCE_XPD_SAR_FSM 0 // Use FSM to control power down
#define LP_ADC_FORCE_XPD_SAR_PD 2 // Force power down
#define LP_ADC_FORCE_XPD_SAR_PU 3 // Force power up
/*---------------------------------------------------------------
Oneshot
---------------------------------------------------------------*/
#define ADC_LL_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (1)
#define ADC_LL_DELAY_CYCLE_AFTER_DONE_SIGNAL (0)
/*---------------------------------------------------------------
DMA
---------------------------------------------------------------*/
#define ADC_LL_DIGI_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define ADC_LL_FSM_RSTB_WAIT_DEFAULT (8)
#define ADC_LL_FSM_START_WAIT_DEFAULT (5)
#define ADC_LL_FSM_STANDBY_WAIT_DEFAULT (100)
#define ADC_LL_SAMPLE_CYCLE_DEFAULT (2)
#define ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT (1)
#define ADC_LL_CLKM_DIV_NUM_DEFAULT 15
#define ADC_LL_CLKM_DIV_B_DEFAULT 1
#define ADC_LL_CLKM_DIV_A_DEFAULT 0
#define ADC_LL_DEFAULT_CONV_LIMIT_EN 0
#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10
#define ADC_LL_POWER_MANAGE_SUPPORTED 1 //ESP32P4 supported to manage power mode
/*---------------------------------------------------------------
PWDET (Power Detect)
---------------------------------------------------------------*/
#define ADC_LL_PWDET_CCT_DEFAULT (4)
typedef enum {
ADC_LL_CTRL_RTC = 0, ///< For ADC1 and ADC2. Select RTC controller.
ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller.
ADC_LL_CTRL_DIG = 2, ///< For ADC1 and ADC2. Select DIG controller.
ADC_LL_CTRL_PWDET = 3, ///< For ADC2. Select PWDET controller.
} adc_ll_controller_t;
typedef enum {
ADC_LL_POWER_BY_FSM = SAR_CTRL_LL_POWER_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */
ADC_LL_POWER_SW_ON = SAR_CTRL_LL_POWER_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */
ADC_LL_POWER_SW_OFF = SAR_CTRL_LL_POWER_OFF, /*!< ADC XPD controlled by SW. power off. */
} adc_ll_power_t;
/**
* @brief ADC digital controller (DMA mode) work mode.
*
* @note The conversion mode affects the sampling frequency:
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
*/
typedef enum {
ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion
ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion
ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously
ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 .....
} adc_ll_digi_convert_mode_t;
typedef struct {
union {
struct {
uint8_t atten: 2;
uint8_t channel: 3;
uint8_t unit: 1;
uint8_t reserved: 2;
};
uint8_t val;
};
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* Set adc fsm interval parameter for digital controller. These values are fixed for same platforms.
*
* @param rst_wait cycles between DIG ADC controller reset ADC sensor and start ADC sensor.
* @param start_wait Delay time after open xpd.
* @param standby_wait Delay time to close xpd.
*/
static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait)
{
// Internal FSM reset wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.fsm_wait, rstb_wait, rst_wait);
// Internal FSM start wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.fsm_wait, xpd_wait, start_wait);
// Internal FSM standby wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.fsm_wait, standby_wait, standby_wait);
}
/**
* Set adc sample cycle for digital controller.
*
* @note Normally, please use default value.
* @param sample_cycle Cycles between DIG ADC controller start ADC sensor and beginning to receive data from sensor.
* Range: 2 ~ 0xFF.
*/
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{
/* Peripheral reg i2c has powered up in rtc_init, write directly */
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle);
}
/**
* Set SAR ADC module clock division factor.
* SAR ADC clock divided from digital controller clock.
*
* @param div Division factor.
*/
static inline void adc_ll_digi_set_clk_div(uint32_t div)
{
/* ADC clock divided from digital controller clock clk */
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.ctrl_reg, sar_clk_div, div);
}
/**
* Set adc max conversion number for digital controller.
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
*
* @param meas_num Max conversion number. Range: 0 ~ 255.
*/
static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.ctrl2, max_meas_num, meas_num);
}
/**
* Enable max conversion number detection for digital controller.
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
*
* @param enable true: enable; false: disable
*/
static inline void adc_ll_digi_convert_limit_enable(bool enable)
{
ADC.ctrl2.meas_num_limit = enable;
}
/**
* Set adc conversion mode for digital controller.
*
* @param mode Conversion mode select.
*/
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
{
if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) {
ADC.ctrl_reg.work_mode = 0;
ADC.ctrl_reg.sar_sel = 0;
} else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) {
ADC.ctrl_reg.work_mode = 0;
ADC.ctrl_reg.sar_sel = 1;
} else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) {
ADC.ctrl_reg.work_mode = 1;
} else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) {
ADC.ctrl_reg.work_mode = 2;
}
ADC.ctrl_reg.data_sar_sel = 1;
}
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
*
* @param div_num Division factor. Range: 0 ~ 255.
* @param div_b Division factor. Range: 1 ~ 63.
* @param div_a Division factor. Range: 0 ~ 63.
*/
static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl23, reg_adc_clk_div_num, div_num);
HP_SYS_CLKRST.peri_clk_ctrl23.reg_adc_clk_div_numerator = div_a;
HP_SYS_CLKRST.peri_clk_ctrl23.reg_adc_clk_div_denominator = div_b;
}
/**
* Enable clock and select clock source for ADC digital controller.
*
* @param clk_src clock source for ADC digital controller.
*/
static inline void adc_ll_digi_clk_sel(adc_continuous_clk_src_t clk_src)
{
switch (clk_src) {
case ADC_DIGI_CLK_SRC_XTAL:
HP_SYS_CLKRST.peri_clk_ctrl22.reg_adc_clk_src_sel = 0;
break;
case ADC_DIGI_CLK_SRC_RC_FAST:
HP_SYS_CLKRST.peri_clk_ctrl22.reg_adc_clk_src_sel = 1;
break;
case ADC_DIGI_CLK_SRC_PLL_F80M:
HP_SYS_CLKRST.peri_clk_ctrl22.reg_adc_clk_src_sel = 2;
break;
default:
HAL_ASSERT(false && "unsupported clock");
}
// Enable ADC_CTRL_CLK (i.e. digital domain clock)
ADC.ctrl_reg.sar_clk_gated = 1;
}
/**
* Disable clock for ADC digital controller.
*/
static inline void adc_ll_digi_controller_clk_disable(void)
{
ADC.ctrl_reg.sar_clk_gated = 0;
}
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)adc_n;
ADC.filter_ctrl0.filter_reset = 1;
ADC.filter_ctrl0.filter_reset = 0;
}
/**
* Set adc digital controller filter coeff.
*
* @param idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
static inline void adc_ll_digi_filter_set_factor(adc_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
ADC.filter_ctrl0.filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
ADC.filter_ctrl1.filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
ADC.filter_ctrl0.filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
ADC.filter_ctrl1.filter_factor1 = factor_reg_val;
}
}
/**
* Enable adc digital controller filter.
* Filtering the ADC data to obtain smooth data at higher sampling rates.
*
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
ADC.filter_ctrl0.filter_channel0 = 0xF;
ADC.filter_ctrl1.filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
ADC.filter_ctrl0.filter_channel1 = 0xF;
ADC.filter_ctrl1.filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself.
*
* @param adc_n ADC unit.
* @param patt_len Items range: 1 ~ 16.
*/
static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t patt_len)
{
if (adc_n == ADC_UNIT_1) {
ADC.ctrl_reg.sar1_patt_len = patt_len - 1;
} else { // adc_n == ADC_UNIT_2
ADC.ctrl_reg.sar2_patt_len = patt_len - 1;
}
}
/**
* Set pattern table for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 12 items, in which channel selection,
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 12 different rules before repeating itself.
*
* @param adc_n ADC unit.
* @param pattern_index Items index. Range: 0 ~ 11.
* @param pattern Stored conversion rules.
*/
static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table)
{
uint32_t tab;
uint8_t index = pattern_index / 4;
uint8_t offset = (pattern_index % 4) * 6;
adc_ll_digi_pattern_table_t pattern = {0};
pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 2);
if (table.unit == ADC_UNIT_1){
tab = ADC.sar1_patt_tab[index].sar1_patt_tab; //Read old register value
tab &= (~(0xFC0000 >> offset)); //Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data
ADC.sar1_patt_tab[index].sar1_patt_tab = tab; //Write back
} else {
tab = ADC.sar2_patt_tab[index].sar2_patt_tab; //Read old register value
tab &= (~(0xFC0000 >> offset)); //clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data
ADC.sar2_patt_tab[index].sar2_patt_tab = tab; //Write back
}
}
/**
* Reset the pattern table pointer, then take the measurement rule from table header in next measurement.
*
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_clear_pattern_table(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
ADC.ctrl_reg.sar1_patt_p_clear = 1;
ADC.ctrl_reg.sar1_patt_p_clear = 0;
} else { // adc_n == ADC_UNIT_2
ADC.ctrl_reg.sar2_patt_p_clear = 1;
ADC.ctrl_reg.sar2_patt_p_clear = 0;
}
}
/**
* ADC Digital controller output data invert or not.
*
* @param adc_n ADC unit.
* @param inv_en data invert or not.
*/
static inline void adc_ll_digi_output_invert(adc_unit_t adc_n, bool inv_en)
{
if (adc_n == ADC_UNIT_1) {
ADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_UNIT_2
ADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert
}
}
/**
* Set the interval clock cycle for the digital controller to trigger the measurement.
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval.
*
* @note The trigger interval should not be smaller than the sampling time of the SAR ADC.
* @param cycle The clock cycle (trigger interval) of the measurement. Range: 30 ~ 4095.
*/
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
{
ADC.ctrl2.timer_target = cycle;
}
/**
* Set DMA eof num of adc digital controller.
* If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated.
*
* @param num eof num of DMA.
*/
static inline void adc_ll_digi_dma_set_eof_num(uint32_t num)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(ADC.dma_conf, apb_adc_eof_num, num);
}
/**
* Enable output data to DMA from adc digital controller.
*/
static inline void adc_ll_digi_dma_enable(void)
{
ADC.dma_conf.apb_adc_trans = 1;
}
/**
* Disable output data to DMA from adc digital controller.
*/
static inline void adc_ll_digi_dma_disable(void)
{
ADC.dma_conf.apb_adc_trans = 0;
}
/**
* Reset adc digital controller.
*/
static inline void adc_ll_digi_reset(void)
{
ADC.dma_conf.apb_adc_reset_fsm = 1;
ADC.dma_conf.apb_adc_reset_fsm = 0;
}
/**
* Enable digital controller timer to trigger the measurement.
*/
static inline void adc_ll_digi_trigger_enable(void)
{
ADC.ctrl2.timer_sel = 1;
ADC.ctrl2.timer_en = 1;
}
/**
* Disable digital controller timer to trigger the measurement.
*/
static inline void adc_ll_digi_trigger_disable(void)
{
ADC.ctrl2.timer_en = 0;
}
/*---------------------------------------------------------------
PWDET(Power detect) controller setting
---------------------------------------------------------------*/
/**
* Set adc cct for PWDET controller.
*
* @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY.
* @param cct Range: 0 ~ 7.
*/
static inline void adc_ll_pwdet_set_cct(uint32_t cct)
{
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
LP_ADC.meas2_mux.sar2_pwdet_cct = cct;
}
/**
* Get adc cct for PWDET controller.
*
* @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY.
* @return cct Range: 0 ~ 7.
*/
static inline uint32_t adc_ll_pwdet_get_cct(void)
{
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
return LP_ADC.meas2_mux.sar2_pwdet_cct;
}
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
HP_SYS_CLKRST.soc_clk_ctrl2.reg_adc_apb_clk_en = enable;
HP_SYS_CLKRST.peri_clk_ctrl23.reg_adc_clk_en = enable;
}
// HP_SYS_CLKRST.soc_clk_ctrl2 are shared registers, so this function must be used in an atomic way
#define adc_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_adc = 1;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_adc = 0;
}
// HP_SYS_CLKRST.hp_rst_en2 is a shared register, so this function must be used in an atomic way
#define adc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_reset_register(__VA_ARGS__)
/**
* Set ADC digital controller power management.
*
* @param adc_n ADC unit.
* @param manage Set ADC power status.
*/
static inline void adc_ll_digi_set_power_manage(adc_unit_t adc_n, adc_ll_power_t manage)
{
if (adc_n == ADC_UNIT_1) {
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {
ADC.ctrl_reg.sar_clk_gated = 1;
ADC.ctrl_reg.xpd_sar1_force = LP_ADC_FORCE_XPD_SAR_PU;
} else if (manage == ADC_LL_POWER_BY_FSM) {
ADC.ctrl_reg.sar_clk_gated = 1;
ADC.ctrl_reg.xpd_sar1_force = LP_ADC_FORCE_XPD_SAR_FSM;
} else if (manage == ADC_LL_POWER_SW_OFF) {
ADC.ctrl_reg.sar_clk_gated = 0;
ADC.ctrl_reg.xpd_sar1_force = LP_ADC_FORCE_XPD_SAR_PD;
}
} else {
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {
ADC.ctrl_reg.sar_clk_gated = 1;
ADC.ctrl_reg.xpd_sar2_force = LP_ADC_FORCE_XPD_SAR_PU;
} else if (manage == ADC_LL_POWER_BY_FSM) {
ADC.ctrl_reg.sar_clk_gated = 1;
ADC.ctrl_reg.xpd_sar2_force = LP_ADC_FORCE_XPD_SAR_FSM;
} else if (manage == ADC_LL_POWER_SW_OFF) {
ADC.ctrl_reg.sar_clk_gated = 0;
ADC.ctrl_reg.xpd_sar2_force = LP_ADC_FORCE_XPD_SAR_PD;
}
}
}
/**
* Set ADC module power management.
*
* @param adc_n ADC unit.
* @param manage Set ADC power status.
*/
static inline void adc_ll_set_power_manage(adc_unit_t adc_n, adc_ll_power_t manage)
{
adc_ll_digi_set_power_manage(adc_n, manage);
if (adc_n == ADC_UNIT_1) {
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {
LPPERI.clk_en.ck_en_lp_adc = 1;
LP_ADC.force_wpd_sar.force_xpd_sar1 = LP_ADC_FORCE_XPD_SAR_PU;
} else if (manage == ADC_LL_POWER_BY_FSM) {
LPPERI.clk_en.ck_en_lp_adc = 1;
LP_ADC.force_wpd_sar.force_xpd_sar1 = LP_ADC_FORCE_XPD_SAR_FSM;
} else if (manage == ADC_LL_POWER_SW_OFF) {
LP_ADC.force_wpd_sar.force_xpd_sar1 = LP_ADC_FORCE_XPD_SAR_PD;
LPPERI.clk_en.ck_en_lp_adc = 0;
}
} else {
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_LL_POWER_SW_ON) {
LPPERI.clk_en.ck_en_lp_adc = 1;
LP_ADC.force_wpd_sar.force_xpd_sar2 = LP_ADC_FORCE_XPD_SAR_PU;
} else if (manage == ADC_LL_POWER_BY_FSM) {
LPPERI.clk_en.ck_en_lp_adc = 1;
LP_ADC.force_wpd_sar.force_xpd_sar2 = LP_ADC_FORCE_XPD_SAR_FSM;
} else if (manage == ADC_LL_POWER_SW_OFF) {
LP_ADC.force_wpd_sar.force_xpd_sar2 = LP_ADC_FORCE_XPD_SAR_PD;
LPPERI.clk_en.ck_en_lp_adc = 0;
}
}
}
/**
* Set ADC module controller.
* There are five SAR ADC controllers:
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
*
* @param adc_n ADC unit.
* @param ctrl ADC controller.
*/
__attribute__((always_inline))
static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t ctrl)
{
if (adc_n == ADC_UNIT_1) {
switch (ctrl) {
case ADC_LL_CTRL_RTC:
LP_ADC.meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_ULP:
LP_ADC.meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_DIG:
LP_ADC.meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
default:
break;
}
} else { // adc_n == ADC_UNIT_2
switch (ctrl) {
case ADC_LL_CTRL_RTC:
LP_ADC.meas2_mux.sar2_rtc_force = 1; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_ULP:
LP_ADC.meas2_mux.sar2_rtc_force = 0; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_DIG:
LP_ADC.meas2_mux.sar2_rtc_force = 0; // 1: Select digital control; 0: Select RTC control.
LP_ADC.meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
LP_ADC.meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
default:
break;
}
}
}
/*---------------------------------------------------------------
Oneshot Read
---------------------------------------------------------------*/
static inline void adc_ll_vref_output(adc_unit_t adc, adc_channel_t channel, bool en)
{
abort();
}
/**
* Set adc output data format for RTC controller.
*
* @note ESP32P4 RTC controller only support 12bit.
* @param adc_n ADC unit.
* @param bits Output data bits width option.
*/
static inline void adc_oneshot_ll_set_output_bits(adc_unit_t adc_n, adc_bitwidth_t bits)
{
//ESP32P4 only supports 12bit, leave here for compatibility
HAL_ASSERT(bits == ADC_BITWIDTH_12 || bits == ADC_BITWIDTH_DEFAULT);
}
/**
* Enable adc channel to start convert.
*
* @note Only one channel can be selected for once measurement.
*
* @param adc_n ADC unit.
* @param channel ADC channel number for each ADCn.
*/
static inline void adc_oneshot_ll_set_channel(adc_unit_t adc_n, adc_channel_t channel)
{
if (adc_n == ADC_UNIT_1) {
LP_ADC.meas1_ctrl2.sar1_en_pad = (1 << channel); //only one channel is selected.
} else { // adc_n == ADC_UNIT_2
LP_ADC.meas2_ctrl2.sar2_en_pad = (1 << ((channel + 2))); //only one channel is selected.
}
}
/**
* Disable adc channel to start convert.
*
* @note Only one channel can be selected in once measurement.
*
* @param adc_n ADC unit.
* @param channel ADC channel number for each ADCn.
*/
static inline void adc_oneshot_ll_disable_channel(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
LP_ADC.meas1_ctrl2.sar1_en_pad = 0; //only one channel is selected.
} else { // adc_n == ADC_UNIT_2
LP_ADC.meas2_ctrl2.sar2_en_pad = 0; //only one channel is selected.
}
}
/**
* Start conversion once by software for RTC controller.
*
* @note It may be block to wait conversion idle for ADC1.
*
* @param adc_n ADC unit.
*/
static inline void adc_oneshot_ll_start(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
LP_ADC.meas1_ctrl2.meas1_start_sar = 0;
LP_ADC.meas1_ctrl2.meas1_start_sar = 1;
} else { // adc_n == ADC_UNIT_2
LP_ADC.meas2_ctrl2.meas2_start_sar = 0;
LP_ADC.meas2_ctrl2.meas2_start_sar = 1;
}
}
/**
* Clear the event for each ADCn for Oneshot mode
*
* @param event ADC event
*/
static inline void adc_oneshot_ll_clear_event(uint32_t event_mask)
{
// ADC.int_clr.val |= event_mask;
}
/**
* Check the event for each ADCn for Oneshot mode
*
* @param event ADC event
*
* @return
* -true : The conversion process is finish.
* -false : The conversion process is not finish.
*/
static inline bool adc_oneshot_ll_get_event(uint32_t event)
{
bool ret = true;
if (event == ADC_LL_EVENT_ADC1_ONESHOT_DONE) {
ret = (bool)LP_ADC.meas1_ctrl2.meas1_done_sar;
} else if (event == ADC_LL_EVENT_ADC2_ONESHOT_DONE) {
ret = (bool)LP_ADC.meas2_ctrl2.meas2_done_sar;
} else {
HAL_ASSERT(false);
}
return ret;
}
/**
* Get the converted value for each ADCn for RTC controller.
*
* @param adc_n ADC unit.
* @return
* - Converted value.
*/
static inline uint32_t adc_oneshot_ll_get_raw_result(adc_unit_t adc_n)
{
uint32_t ret_val = 0;
if (adc_n == ADC_UNIT_1) {
ret_val = HAL_FORCE_READ_U32_REG_FIELD(LP_ADC.meas1_ctrl2, meas1_data_sar);
} else { // adc_n == ADC_UNIT_2
ret_val = HAL_FORCE_READ_U32_REG_FIELD(LP_ADC.meas2_ctrl2, meas2_data_sar);
}
return ret_val;
}
/**
* Analyze whether the obtained raw data is correct.
*
* @param adc_n ADC unit.
* @param raw ADC raw data input (convert value).
* @return
* - true: raw data is valid
*/
static inline bool adc_oneshot_ll_raw_check_valid(adc_unit_t adc_n, uint32_t raw)
{
/* No arbiter, don't need check data */
return true;
}
/**
* ADC module RTC output data invert or not.
*
* @param adc_n ADC unit.
* @param inv_en data invert or not.
*/
static inline void adc_oneshot_ll_output_invert(adc_unit_t adc_n, bool inv_en)
{
if (adc_n == ADC_UNIT_1) {
LP_ADC.reader1_ctrl.sar1_data_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_UNIT_2
LP_ADC.reader2_ctrl.sar2_data_inv = inv_en; // Enable / Disable ADC data invert
}
}
/**
* Enable oneshot conversion trigger
*
* @param adc_n ADC unit
*/
static inline void adc_oneshot_ll_enable(adc_unit_t adc_n)
{
(void)adc_n;
//For compatibility
}
/**
* Disable oneshot conversion trigger for all the ADC units
*/
static inline void adc_oneshot_ll_disable_all_unit(void)
{
//For compatibility
}
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/**
* ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`.
*
* @param div Division factor.
*/
static inline void adc_ll_set_sar_clk_div(adc_unit_t adc_n, uint32_t div)
{
if (adc_n == ADC_UNIT_1) {
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_ADC.reader1_ctrl, sar1_clk_div, div);
} else { // adc_n == ADC_UNIT_2
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_ADC.reader2_ctrl, sar2_clk_div, div);
}
}
/**
* Reset RTC controller FSM.
*/
static inline void adc_ll_rtc_reset(void)
{
LPPERI.reset_en.rst_en_lp_adc = 1;
LPPERI.reset_en.rst_en_lp_adc = 0;
}
/**
* Set the attenuation of a particular channel on ADCn.
*
* @note For any given channel, this function must be called before the first time conversion.
*
* The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
*
* When VDD_A is 3.3V:
*
* - 0dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
* - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V
* - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V
* - 11dB attenuation (ADC_ATTEN_DB_12) gives full-scale voltage 3.9V (see note below)
*
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured
* bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
*
* @note At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
*
* Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges:
*
* - 0dB attenuation (ADC_ATTEN_DB_0) between 100 and 950mV
* - 2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV
* - 6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV
* - 11dB attenuation (ADC_ATTEN_DB_12) between 150 to 2450mV
*
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
*
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @param atten The attenuation option.
*/
static inline void adc_oneshot_ll_set_atten(adc_unit_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
if (adc_n == ADC_UNIT_1) {
LP_ADC.atten1.sar1_atten = ( LP_ADC.atten1.sar1_atten & ~(0x3 << (channel * 2)) ) | ((atten & 0x3) << (channel * 2));
} else { // adc_n == ADC_UNIT_2
LP_ADC.atten2.sar2_atten = ( LP_ADC.atten2.sar2_atten & ~(0x3 << ((channel + 2) * 2)) ) | ((atten & 0x3) << ((channel + 2) * 2));
}
}
/**
* Get the attenuation of a particular channel on ADCn.
*
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @return atten The attenuation option.
*/
__attribute__((always_inline))
static inline adc_atten_t adc_ll_get_atten(adc_unit_t adc_n, adc_channel_t channel)
{
if (adc_n == ADC_UNIT_1) {
return (adc_atten_t)((LP_ADC.atten1.sar1_atten >> (channel * 2)) & 0x3);
} else {
return (adc_atten_t)((LP_ADC.atten2.sar2_atten >> ((channel + 2) * 2)) & 0x3);
}
}
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,6 +20,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/lp_adc_struct.h"
#ifdef __cplusplus
extern "C" {
@ -39,6 +40,27 @@ typedef enum {
/*---------------------------------------------------------------
SAR power control
---------------------------------------------------------------*/
/**
* Set SAR power mode
*
* @param mode See `sar_ctrl_ll_power_t`
*/
__attribute__((always_inline))
static inline void sar_ctrl_ll_set_power_mode(sar_ctrl_ll_power_t mode)
{
if (mode == SAR_CTRL_LL_POWER_FSM) {
LP_ADC.force_wpd_sar.force_xpd_sar1 = 0x0;
LP_ADC.force_wpd_sar.force_xpd_sar2 = 0x0;
} else if (mode == SAR_CTRL_LL_POWER_ON) {
LP_ADC.force_wpd_sar.force_xpd_sar1 = 0x3;
LP_ADC.force_wpd_sar.force_xpd_sar2 = 0x3;
} else {
LP_ADC.force_wpd_sar.force_xpd_sar1 = 0x2;
LP_ADC.force_wpd_sar.force_xpd_sar2 = 0x2;
}
}
/**
* @brief Set SAR power mode when controlled by PWDET
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -22,6 +22,8 @@
#include "soc/clk_tree_defs.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h"
#include "soc/system_reg.h"
#include "soc/dport_reg.h"
#ifdef __cplusplus
extern "C" {
@ -40,6 +42,7 @@ extern "C" {
#define ADC_LL_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (1)
#define ADC_LL_DELAY_CYCLE_AFTER_DONE_SIGNAL (0)
#define ADC_LL_RTC_GPIO_SUPPORTED (1)
/*---------------------------------------------------------------
DMA
@ -917,6 +920,32 @@ static inline void adc_oneshot_ll_disable_all_unit(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG);
reg_val = reg_val & (~DPORT_APB_SARADC_CLK_EN);
reg_val = reg_val | (enable << DPORT_APB_SARADC_CLK_EN_S);
WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val);
}
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_APB_SARADC_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_APB_SARADC_RST);
}
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_reset_register(__VA_ARGS__)
/**
* Set ADC module power management.
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,6 +20,7 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/regi2c_defs.h"
#include "soc/clk_tree_defs.h"
#include "soc/system_struct.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h"
@ -43,6 +44,7 @@ extern "C" {
#define ADC_LL_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (1)
#define ADC_LL_DELAY_CYCLE_AFTER_DONE_SIGNAL (0)
#define ADC_LL_RTC_GPIO_SUPPORTED (1)
/*---------------------------------------------------------------
DMA
@ -611,6 +613,29 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Enable the ADC clock
* @param enable true to enable, false to disable
*/
static inline void adc_ll_enable_bus_clock(bool enable)
{
SYSTEM.perip_clk_en0.apb_saradc_clk_en = enable;
}
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset ADC module
*/
static inline void adc_ll_reset_register(void)
{
SYSTEM.perip_rst_en0.apb_saradc_rst = 1;
SYSTEM.perip_rst_en0.apb_saradc_rst = 0;
}
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
#define adc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; adc_ll_reset_register(__VA_ARGS__)
/**
* Set ADC module power management.
*

View File

@ -19,6 +19,7 @@
#include "soc/io_mux_reg.h"
#include "soc/usb_serial_jtag_reg.h"
#include "soc/usb_serial_jtag_struct.h"
#include "soc/sens_struct.h"
#ifdef __cplusplus
extern "C" {
@ -27,7 +28,7 @@ extern "C" {
#define RTCIO_LL_PIN_FUNC 0
typedef enum {
RTCIO_LL_FUNC_RTC = 0x0, /*!< The pin controled by RTC module. */
RTCIO_LL_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */
RTCIO_LL_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */
} rtcio_ll_func_t;

View File

@ -191,7 +191,7 @@ typedef struct {
};
} adc_digi_output_data_t;
#elif CONFIG_IDF_TARGET_ESP32S3
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.

View File

@ -10,3 +10,11 @@
/* Solicited yields (portYIELD() or taskYIELD()) take longer on esp32p4. TODO: IDF-2809 */
#define IDF_PERFORMANCE_MAX_SCHEDULING_TIME 3200
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 10
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 10

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -7,4 +7,15 @@
#include "soc/adc_periph.h"
/* Store IO number corresponding to the ADC channel number. */
const int adc_channel_io_map[SOC_ADC_PERIPH_NUM][SOC_ADC_MAX_CHANNEL_NUM] = {};
const int adc_channel_io_map[SOC_ADC_PERIPH_NUM][SOC_ADC_MAX_CHANNEL_NUM] = {
/* ADC1 */
{
ADC1_CHANNEL_0_GPIO_NUM, ADC1_CHANNEL_1_GPIO_NUM, ADC1_CHANNEL_2_GPIO_NUM, ADC1_CHANNEL_3_GPIO_NUM,
ADC1_CHANNEL_4_GPIO_NUM, ADC1_CHANNEL_5_GPIO_NUM, ADC1_CHANNEL_6_GPIO_NUM, ADC1_CHANNEL_7_GPIO_NUM
},
/* ADC2 */
{
ADC2_CHANNEL_0_GPIO_NUM, ADC2_CHANNEL_1_GPIO_NUM, ADC2_CHANNEL_2_GPIO_NUM,
ADC2_CHANNEL_3_GPIO_NUM, ADC2_CHANNEL_4_GPIO_NUM, ADC2_CHANNEL_5_GPIO_NUM
}
};

View File

@ -3,6 +3,10 @@
# using gen_soc_caps_kconfig.py, do not edit manually
#####################################################
config SOC_ADC_SUPPORTED
bool
default y
config SOC_ANA_CMPR_SUPPORTED
bool
default y
@ -307,13 +311,25 @@ config SOC_AES_SUPPORT_AES_256
bool
default y
config SOC_ADC_RTC_CTRL_SUPPORTED
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_DMA_SUPPORTED
bool
default y
config SOC_ADC_PERIPH_NUM
int
default 1
default 2
config SOC_ADC_MAX_CHANNEL_NUM
int
default 7
default 8
config SOC_ADC_ATTEN_NUM
int
@ -321,11 +337,11 @@ config SOC_ADC_ATTEN_NUM
config SOC_ADC_DIGI_CONTROLLER_NUM
int
default 1
default 2
config SOC_ADC_PATT_LEN_MAX
int
default 8
default 16
config SOC_ADC_DIGI_MAX_BITWIDTH
int
@ -371,6 +387,10 @@ config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool
default n
config SOC_ADC_SHARED_POWER
bool
default y
config SOC_APB_BACKUP_DMA
bool
default n

View File

@ -1,7 +1,49 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#define ADC1_GPIO16_CHANNEL 0
#define ADC1_CHANNEL_0_GPIO_NUM 16
#define ADC1_GPIO17_CHANNEL 1
#define ADC1_CHANNEL_1_GPIO_NUM 17
#define ADC1_GPIO18_CHANNEL 2
#define ADC1_CHANNEL_2_GPIO_NUM 18
#define ADC1_GPIO19_CHANNEL 3
#define ADC1_CHANNEL_3_GPIO_NUM 19
#define ADC1_GPIO20_CHANNEL 4
#define ADC1_CHANNEL_4_GPIO_NUM 20
#define ADC1_GPIO21_CHANNEL 5
#define ADC1_CHANNEL_5_GPIO_NUM 21
#define ADC1_GPIO22_CHANNEL 6
#define ADC1_CHANNEL_6_GPIO_NUM 22
#define ADC1_GPIO23_CHANNEL 7
#define ADC1_CHANNEL_7_GPIO_NUM 23
#define ADC2_GPIO49_CHANNEL 0
#define ADC2_CHANNEL_0_GPIO_NUM 49
#define ADC2_GPIO50_CHANNEL 1
#define ADC2_CHANNEL_1_GPIO_NUM 50
#define ADC2_GPIO51_CHANNEL 2
#define ADC2_CHANNEL_2_GPIO_NUM 51
#define ADC2_GPIO52_CHANNEL 3
#define ADC2_CHANNEL_3_GPIO_NUM 52
#define ADC2_GPIO53_CHANNEL 4
#define ADC2_CHANNEL_4_GPIO_NUM 53
#define ADC2_GPIO54_CHANNEL 5
#define ADC2_CHANNEL_5_GPIO_NUM 54

View File

@ -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
*/
@ -195,6 +195,26 @@ extern "C" {
#define ADC_FILTER_FACTOR0_V 0x00000007U
#define ADC_FILTER_FACTOR0_S 29
#define ADC_FSM_WAIT_REG (DR_REG_ADC_BASE + 0xC)
/* ADC_STANDBY_WAIT : R/W ;bitpos:[23:16] ;default: 8'd255 ; */
/*description: need_des.*/
#define ADC_STANDBY_WAIT 0x000000FF
#define ADC_STANDBY_WAIT_M ((ADC_STANDBY_WAIT_V)<<(ADC_STANDBY_WAIT_S))
#define ADC_STANDBY_WAIT_V 0xFF
#define ADC_STANDBY_WAIT_S 16
/* ADC_RSTB_WAIT : R/W ;bitpos:[15:8] ;default: 8'd8 ; */
/*description: need_des.*/
#define ADC_RSTB_WAIT 0x000000FF
#define ADC_RSTB_WAIT_M ((ADC_RSTB_WAIT_V)<<(ADC_RSTB_WAIT_S))
#define ADC_RSTB_WAIT_V 0xFF
#define ADC_RSTB_WAIT_S 8
/* ADC_XPD_WAIT : R/W ;bitpos:[7:0] ;default: 8'd8 ; */
/*description: need_des.*/
#define ADC_XPD_WAIT 0x000000FF
#define ADC_XPD_WAIT_M ((ADC_XPD_WAIT_V)<<(ADC_XPD_WAIT_S))
#define ADC_XPD_WAIT_V 0xFF
#define ADC_XPD_WAIT_S 0
/** ADC_SAR1_PATT_TAB1_REG register
* Register
*/

View File

@ -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
*/
@ -137,117 +137,46 @@ typedef union {
uint32_t val;
} adc_filter_ctrl1_reg_t;
/** Type of sar1_patt_tab1 register
/** Type of filter_ctrl1 register
* Register
*/
typedef union {
struct {
/** sar1_patt_tab1 : R/W; bitpos: [23:0]; default: 0;
uint32_t xpd_wait:8;
uint32_t rstb_wait:8;
uint32_t standby_wait:8;
uint32_t reserved24:8;
};
uint32_t val;
} adc_fsm_wait_reg_t;
/** Type of sar1_patt_tab register
* Register
*/
typedef union {
struct {
/** sar1_patt_tab : R/W; bitpos: [23:0]; default: 0;
* item 0 ~ 3 for pattern table 1 (each item one byte)
*/
uint32_t sar1_patt_tab1:24;
uint32_t sar1_patt_tab:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar1_patt_tab1_reg_t;
/** Type of sar1_patt_tab2 register
* Register
*/
typedef union {
struct {
/** sar1_patt_tab2 : R/W; bitpos: [23:0]; default: 0;
* Item 4 ~ 7 for pattern table 1 (each item one byte)
*/
uint32_t sar1_patt_tab2:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar1_patt_tab2_reg_t;
/** Type of sar1_patt_tab3 register
* Register
*/
typedef union {
struct {
/** sar1_patt_tab3 : R/W; bitpos: [23:0]; default: 0;
* Item 8 ~ 11 for pattern table 1 (each item one byte)
*/
uint32_t sar1_patt_tab3:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar1_patt_tab3_reg_t;
/** Type of sar1_patt_tab4 register
* Register
*/
typedef union {
struct {
/** sar1_patt_tab4 : R/W; bitpos: [23:0]; default: 0;
* Item 12 ~ 15 for pattern table 1 (each item one byte)
*/
uint32_t sar1_patt_tab4:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar1_patt_tab4_reg_t;
} adc_sar1_patt_tab_reg_t;
/** Type of sar2_patt_tab1 register
* Register
*/
typedef union {
struct {
/** sar2_patt_tab1 : R/W; bitpos: [23:0]; default: 0;
/** sar2_patt_tab : R/W; bitpos: [23:0]; default: 0;
* item 0 ~ 3 for pattern table 2 (each item one byte)
*/
uint32_t sar2_patt_tab1:24;
uint32_t sar2_patt_tab:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar2_patt_tab1_reg_t;
/** Type of sar2_patt_tab2 register
* Register
*/
typedef union {
struct {
/** sar2_patt_tab2 : R/W; bitpos: [23:0]; default: 0;
* Item 4 ~ 7 for pattern table 2 (each item one byte)
*/
uint32_t sar2_patt_tab2:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar2_patt_tab2_reg_t;
/** Type of sar2_patt_tab3 register
* Register
*/
typedef union {
struct {
/** sar2_patt_tab3 : R/W; bitpos: [23:0]; default: 0;
* Item 8 ~ 11 for pattern table 2 (each item one byte)
*/
uint32_t sar2_patt_tab3:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar2_patt_tab3_reg_t;
/** Type of sar2_patt_tab4 register
* Register
*/
typedef union {
struct {
/** sar2_patt_tab4 : R/W; bitpos: [23:0]; default: 0;
* Item 12 ~ 15 for pattern table 2 (each item one byte)
*/
uint32_t sar2_patt_tab4:24;
uint32_t reserved_24:8;
};
uint32_t val;
} adc_sar2_patt_tab4_reg_t;
} adc_sar2_patt_tab_reg_t;
/** Type of arb_ctrl register
* Register
@ -655,15 +584,10 @@ typedef struct {
volatile adc_ctrl_reg_reg_t ctrl_reg;
volatile adc_ctrl2_reg_t ctrl2;
volatile adc_filter_ctrl1_reg_t filter_ctrl1;
uint32_t reserved_00c[3];
volatile adc_sar1_patt_tab1_reg_t sar1_patt_tab1;
volatile adc_sar1_patt_tab2_reg_t sar1_patt_tab2;
volatile adc_sar1_patt_tab3_reg_t sar1_patt_tab3;
volatile adc_sar1_patt_tab4_reg_t sar1_patt_tab4;
volatile adc_sar2_patt_tab1_reg_t sar2_patt_tab1;
volatile adc_sar2_patt_tab2_reg_t sar2_patt_tab2;
volatile adc_sar2_patt_tab3_reg_t sar2_patt_tab3;
volatile adc_sar2_patt_tab4_reg_t sar2_patt_tab4;
volatile adc_fsm_wait_reg_t fsm_wait;
uint32_t reserved_00c[2];
volatile adc_sar1_patt_tab_reg_t sar1_patt_tab[4];
volatile adc_sar2_patt_tab_reg_t sar2_patt_tab[4];
volatile adc_arb_ctrl_reg_t arb_ctrl;
volatile adc_filter_ctrl0_reg_t filter_ctrl0;
volatile adc_sar1_data_status_reg_t sar1_data_status;
@ -684,6 +608,7 @@ typedef struct {
volatile adc_ctrl_date_reg_t ctrl_date;
} adc_dev_t;
extern adc_dev_t ADC;
#ifndef __cplusplus
_Static_assert(sizeof(adc_dev_t) == 0x400, "Invalid size of adc_dev_t structure");

View File

@ -589,6 +589,34 @@ typedef enum {
//////////////////////////////////////////////////ADC///////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of ADC digital controller
*/
#define SOC_ADC_DIGI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_RC_FAST}
/**
* @brief ADC digital controller clock source
*/
typedef enum {
ADC_DIGI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
ADC_DIGI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
ADC_DIGI_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */
ADC_DIGI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default clock choice */
} soc_periph_adc_digi_clk_src_t;
/**
* @brief Array initializer for all supported clock sources of ADC RTC controller
*/
#define SOC_ADC_RTC_CLKS {SOC_MOD_CLK_RC_FAST}
/**
* @brief ADC RTC controller clock source
*/
typedef enum {
ADC_RTC_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
ADC_RTC_CLK_SRC_DEFAULT = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the default clock choice */
} soc_periph_adc_rtc_clk_src_t;
//////////////////////////////////////////////////MWDT/////////////////////////////////////////////////////////////////
/**

View File

@ -259,11 +259,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_raw:1;
/** cocpu_saradc1_error_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
* An errro occurs from ADC1, int raw.
* An error occurs from ADC1, int raw.
*/
uint32_t cocpu_saradc1_error_int_raw:1;
/** cocpu_saradc2_error_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
* An errro occurs from ADC2, int raw.
* An error occurs from ADC2, int raw.
*/
uint32_t cocpu_saradc2_error_int_raw:1;
/** cocpu_saradc1_wake_int_raw : R/WTC/SS; bitpos: [4]; default: 0;
@ -293,11 +293,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_ena:1;
/** cocpu_saradc1_error_int_ena : R/WTC; bitpos: [2]; default: 0;
* An errro occurs from ADC1, int enable.
* An error occurs from ADC1, int enable.
*/
uint32_t cocpu_saradc1_error_int_ena:1;
/** cocpu_saradc2_error_int_ena : R/WTC; bitpos: [3]; default: 0;
* An errro occurs from ADC2, int enable.
* An error occurs from ADC2, int enable.
*/
uint32_t cocpu_saradc2_error_int_ena:1;
/** cocpu_saradc1_wake_int_ena : R/WTC; bitpos: [4]; default: 0;
@ -327,11 +327,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_st:1;
/** cocpu_saradc1_error_int_st : RO; bitpos: [2]; default: 0;
* An errro occurs from ADC1, int status.
* An error occurs from ADC1, int status.
*/
uint32_t cocpu_saradc1_error_int_st:1;
/** cocpu_saradc2_error_int_st : RO; bitpos: [3]; default: 0;
* An errro occurs from ADC2, int status.
* An error occurs from ADC2, int status.
*/
uint32_t cocpu_saradc2_error_int_st:1;
/** cocpu_saradc1_wake_int_st : RO; bitpos: [4]; default: 0;
@ -361,11 +361,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_clr:1;
/** cocpu_saradc1_error_int_clr : WT; bitpos: [2]; default: 0;
* An errro occurs from ADC1, int clear.
* An error occurs from ADC1, int clear.
*/
uint32_t cocpu_saradc1_error_int_clr:1;
/** cocpu_saradc2_error_int_clr : WT; bitpos: [3]; default: 0;
* An errro occurs from ADC2, int clear.
* An error occurs from ADC2, int clear.
*/
uint32_t cocpu_saradc2_error_int_clr:1;
/** cocpu_saradc1_wake_int_clr : WT; bitpos: [4]; default: 0;
@ -395,11 +395,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_ena_w1ts:1;
/** cocpu_saradc1_error_int_ena_w1ts : WT; bitpos: [2]; default: 0;
* An errro occurs from ADC1, write 1 to assert int enable.
* An error occurs from ADC1, write 1 to assert int enable.
*/
uint32_t cocpu_saradc1_error_int_ena_w1ts:1;
/** cocpu_saradc2_error_int_ena_w1ts : WT; bitpos: [3]; default: 0;
* An errro occurs from ADC2, write 1 to assert int enable.
* An error occurs from ADC2, write 1 to assert int enable.
*/
uint32_t cocpu_saradc2_error_int_ena_w1ts:1;
/** cocpu_saradc1_wake_int_ena_w1ts : WT; bitpos: [4]; default: 0;
@ -429,11 +429,11 @@ typedef union {
*/
uint32_t cocpu_saradc2_int_ena_w1tc:1;
/** cocpu_saradc1_error_int_ena_w1tc : WT; bitpos: [2]; default: 0;
* An errro occurs from ADC1, write 1 to deassert int enable.
* An error occurs from ADC1, write 1 to deassert int enable.
*/
uint32_t cocpu_saradc1_error_int_ena_w1tc:1;
/** cocpu_saradc2_error_int_ena_w1tc : WT; bitpos: [3]; default: 0;
* An errro occurs from ADC2, write 1 to deassert int enable.
* An error occurs from ADC2, write 1 to deassert int enable.
*/
uint32_t cocpu_saradc2_error_int_ena_w1tc:1;
/** cocpu_saradc1_wake_int_ena_w1tc : WT; bitpos: [4]; default: 0;
@ -592,6 +592,7 @@ typedef struct {
volatile rtcadc_sar2_hw_wakeup_reg_t sar2_hw_wakeup;
} rtcadc_dev_t;
extern rtcadc_dev_t LP_ADC;
#ifndef __cplusplus
_Static_assert(sizeof(rtcadc_dev_t) == 0x74, "Invalid size of rtcadc_dev_t structure");

View File

@ -43,7 +43,7 @@
#define DR_REG_REGDMA_BASE (DR_REG_HPPERIPH0_BASE + 0x82000)
#define DR_REG_SDMMC_BASE (DR_REG_HPPERIPH0_BASE + 0x83000)
#define DR_REG_H264_CORE_BASE (DR_REG_HPPERIPH0_BASE + 0x84000)
#define DR_REG_AHB_PDMA_BASE (DR_REG_HPPERIPH0_BASE + 0x85000)
#define DR_REG_AHB_DMA_BASE (DR_REG_HPPERIPH0_BASE + 0x85000)
#define DR_REG_JPEG_BASE (DR_REG_HPPERIPH0_BASE + 0x86000)
#define DR_REG_PPA_BASE (DR_REG_HPPERIPH0_BASE + 0x87000)
#define DR_REG_DMA2D_BASE (DR_REG_HPPERIPH0_BASE + 0x88000)

View File

@ -37,3 +37,44 @@
#define I2C_SAR_ADC_DTEST_VDD_GRP1 9
#define I2C_SAR_ADC_DTEST_VDD_GRP1_MSB 3
#define I2C_SAR_ADC_DTEST_VDD_GRP1_LSB 0
#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
#define ADC_SAR1_DREF_ADDR 0x2
#define ADC_SAR1_DREF_ADDR_MSB 0x6
#define ADC_SAR1_DREF_ADDR_LSB 0x4
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define ADC_SAR2_SAMPLE_CYCLE_ADDR 0x5
#define ADC_SAR2_SAMPLE_CYCLE_ADDR_MSB 0x2
#define ADC_SAR2_SAMPLE_CYCLE_ADDR_LSB 0x0
#define ADC_SAR2_DREF_ADDR 0x5
#define ADC_SAR2_DREF_ADDR_MSB 0x6
#define ADC_SAR2_DREF_ADDR_LSB 0x4
#define ADC_SAR1_ENCAL_REF_ADDR 0x7
#define ADC_SAR1_ENCAL_REF_ADDR_MSB 4
#define ADC_SAR1_ENCAL_REF_ADDR_LSB 4
#define ADC_SAR1_ENCAL_GND_ADDR 0x7
#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5
#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5
#define ADC_SAR2_ENCAL_REF_ADDR 0x7
#define ADC_SAR2_ENCAL_REF_ADDR_MSB 6
#define ADC_SAR2_ENCAL_REF_ADDR_LSB 6
#define ADC_SAR2_ENCAL_GND_ADDR 0x7
#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7
#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7

View File

@ -17,7 +17,7 @@
#pragma once
/*-------------------------- COMMON CAPS ---------------------------------------*/
// #define SOC_ADC_SUPPORTED 1 //TODO: IDF-6496
#define SOC_ADC_SUPPORTED 1
#define SOC_ANA_CMPR_SUPPORTED 1
#define SOC_DEDICATED_GPIO_SUPPORTED 1
#define SOC_UART_SUPPORTED 1
@ -108,19 +108,20 @@
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
// #define SOC_ADC_DIG_CTRL_SUPPORTED 1 //TODO: IDF-6496, TODO: IDF-6497
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
// #define SOC_ADC_DIG_IIR_FILTER_SUPPORTED 1
// #define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit
// #define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (1U)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (7)
#define SOC_ADC_MAX_CHANNEL_NUM (7)
#define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 6: 8)
#define SOC_ADC_MAX_CHANNEL_NUM (8)
#define SOC_ADC_ATTEN_NUM (4)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
#define SOC_ADC_PATT_LEN_MAX (8) /*!< Two pattern tables, each contains 4 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_CONTROLLER_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16) /*!< Four pattern tables, each contains 4 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_MIN_BITWIDTH (12)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
@ -138,6 +139,9 @@
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (0) /*!< support HW offset calibration version 1*/
/*!< ADC power control is shared by PWDET, TempSensor */
#define SOC_ADC_SHARED_POWER 1
// ESP32P4-TODO: Copy from esp32c6, need check
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (0)

View File

@ -82,6 +82,7 @@ PROVIDE ( LP_I2C = 0x50122000 );
PROVIDE ( LP_SPI = 0x50123000 );
PROVIDE ( LP_WDT = 0x50116000 );
PROVIDE ( LP_I2S = 0x50125000 );
PROVIDE ( LP_ADC = 0x50127000 );
PROVIDE ( LP_TOUCH = 0x50128000 );
PROVIDE ( LP_GPIO = 0x5012A000 );
PROVIDE ( LP_PERI_PMS = 0x5012E000 );

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,11 +13,6 @@
#if SOC_RTCIO_PIN_COUNT > 0
#include "soc/rtc_io_channel.h"
#endif
#if SOC_ADC_RTC_CTRL_SUPPORTED
#include "soc/sens_struct.h"
#endif
#include "soc/io_mux_reg.h"
#ifdef __cplusplus

View File

@ -10,11 +10,19 @@
examples/peripherals/adc/continuous_read:
disable:
- if: SOC_ADC_DMA_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners, TODO IDF-9573
<<: *adc_dependencies
examples/peripherals/adc/oneshot_read:
disable:
- if: SOC_ADC_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runner, TODO IDF-9573
<<: *adc_dependencies
examples/peripherals/analog_comparator:

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# ADC DMA Example

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# ADC Single Read Example

View File

@ -1,6 +1,5 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded.dut import Dut