feat(adc): support ADC oneshot and continuous mode on ESP32-H21

This commit is contained in:
gaoxu
2026-06-01 19:04:35 +08:00
parent 302b820782
commit 13b4430716
17 changed files with 1306 additions and 31 deletions
@@ -11,6 +11,10 @@ if(CONFIG_SOC_PMU_SUPPORTED)
)
endif()
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "sar_periph_ctrl.c")
endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
@@ -0,0 +1,132 @@
/*
* SPDX-FileCopyrightText: 2026 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 <sys/lock.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "esp_private/sar_periph_ctrl.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp_private/esp_modem_clock.h"
#include "esp_private/critical_section.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "hal/sar_ctrl_ll.h"
#include "hal/adc_ll.h"
ESP_LOG_ATTR_TAG(TAG, "sar_periph_ctrl");
extern portMUX_TYPE rtc_spinlock;
static _lock_t adc_reset_lock;
void sar_periph_ctrl_init(void)
{
sar_ctrl_ll_force_power_ctrl_from_pwdet(true);
}
void sar_periph_ctrl_power_enable(void)
{
esp_os_enter_critical_safe(&rtc_spinlock);
sar_ctrl_ll_force_power_ctrl_from_pwdet(true);
esp_os_exit_critical_safe(&rtc_spinlock);
}
void sar_periph_ctrl_power_disable(void)
{
esp_os_enter_critical_safe(&rtc_spinlock);
sar_ctrl_ll_force_power_ctrl_from_pwdet(false);
esp_os_exit_critical_safe(&rtc_spinlock);
}
/**
* This gets incremented when s_sar_power_acquire() is called,
* and decremented when s_sar_power_release() is called.
* PWDET and REG_I2C are 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)
{
modem_clock_module_enable(PERIPH_MODEM_ADC_COMMON_FE_MODULE);
regi2c_saradc_enable();
esp_os_enter_critical_safe(&rtc_spinlock);
s_sar_power_on_cnt++;
if (s_sar_power_on_cnt == 1) {
sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_ON);
}
esp_os_exit_critical_safe(&rtc_spinlock);
}
static void s_sar_power_release(void)
{
esp_os_enter_critical_safe(&rtc_spinlock);
s_sar_power_on_cnt--;
if (s_sar_power_on_cnt < 0) {
esp_os_exit_critical_safe(&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_from_pwdet(SAR_CTRL_LL_POWER_FSM);
}
esp_os_exit_critical_safe(&rtc_spinlock);
regi2c_saradc_disable();
modem_clock_module_disable(PERIPH_MODEM_ADC_COMMON_FE_MODULE);
}
void sar_periph_ctrl_pwdet_power_acquire(void)
{
s_sar_power_acquire();
}
void sar_periph_ctrl_pwdet_power_release(void)
{
s_sar_power_release();
}
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();
}
void sar_periph_ctrl_adc_reset(void)
{
adc_reset_lock_acquire();
adc_ll_reset_register();
adc_reset_lock_release();
}
void adc_reset_lock_acquire(void)
{
_lock_acquire(&adc_reset_lock);
}
void adc_reset_lock_release(void)
{
_lock_release(&adc_reset_lock);
}