esp_adc: move adc common hw related code into esp_hw_support

This commit is contained in:
Armando 2022-07-21 11:47:09 +08:00 committed by Armando (Dou Yiwen)
parent 9a7a1fe61f
commit 5e6a16380a
25 changed files with 431 additions and 371 deletions

View File

@ -20,10 +20,11 @@
#include "freertos/ringbuf.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_lock.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/dma_types.h"
#include "hal/adc_hal_common.h"
#include "driver/gpio.h"
#include "driver/adc_types_legacy.h"
@ -588,3 +589,23 @@ static void check_adc_continuous_driver_conflict(void)
}
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_continuous.h`");
}
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
static __attribute__((constructor)) void adc_hw_calibration(void)
{
//Calculate all ICode
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
adc_hal_calibration_init(i);
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
/**
* This may get wrong when attenuations are NOT consecutive on some chips,
* update this when bringing up the calibration on that chip
*/
adc_calc_hw_calibration_code(i, j);
}
}
}
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED

View File

@ -19,12 +19,13 @@
#include "sys/lock.h"
#include "driver/gpio.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "adc1_private.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/adc_hal_common.h"
#include "hal/adc_hal_conf.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/adc_lock.h"
#include "driver/adc_types_legacy.h"
#if SOC_DAC_SUPPORTED
@ -904,8 +905,6 @@ static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, int *out_raw)
return ESP_OK;
}
#if !CONFIG_IDF_TARGET_ESP32
//wrapper should be removed after I2S deprecation
/**
* @brief This function will be called during start up, to check that adc_oneshot driver is not running along with the legacy adc oneshot driver
*/
@ -921,4 +920,23 @@ static void check_adc_oneshot_driver_conflict(void)
}
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_oneshot.h`");
}
#endif
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
static __attribute__((constructor)) void adc_hw_calibration(void)
{
//Calculate all ICode
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
adc_hal_calibration_init(i);
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
/**
* This may get wrong when attenuations are NOT consecutive on some chips,
* update this when bringing up the calibration on that chip
*/
adc_calc_hw_calibration_code(i, j);
}
}
}
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED

View File

@ -27,7 +27,7 @@
#include "hal/i2s_hal.h"
#if SOC_I2S_SUPPORTS_DAC
#include "driver/dac.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "adc1_private.h"
#include "driver/adc_i2s_legacy.h"
#include "driver/adc_types_legacy.h"

View File

@ -6,18 +6,12 @@ set(srcs "adc_cali.c"
"adc_cali_curve_fitting.c"
"adc_oneshot.c"
"adc_common.c"
"adc_lock.c"
"deprecated/esp_adc_cal_common_legacy.c")
if(CONFIG_SOC_ADC_DMA_SUPPORTED)
list(APPEND srcs "adc_continuous.c")
endif()
# init constructor for wifi
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/adc2_init_cal.c")
list(APPEND srcs "${target}/adc2_init_cal.c")
endif()
# line fitting scheme
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/adc_cali_line_fitting.c")
list(APPEND srcs "${target}/adc_cali_line_fitting.c")

View File

@ -11,18 +11,13 @@
#include "freertos/FreeRTOS.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "driver/gpio.h"
#include "hal/adc_hal.h"
#include "hal/adc_hal_common.h"
#include "hal/adc_hal_conf.h"
#include "soc/adc_periph.h"
//For calibration
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp_efuse_rtc_table.h"
#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
#include "esp_efuse_rtc_calib.h"
#endif
static const char *TAG = "adc_common";
static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
@ -62,54 +57,6 @@ void adc_apb_periph_free(void)
portEXIT_CRITICAL(&s_spinlock);
}
/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
// This gets incremented when adc_power_acquire() is called, and decremented when
// adc_power_release() is called. ADC is powered down when the value reaches zero.
// Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
static int s_adc_power_on_cnt;
static void adc_power_on_internal(void)
{
/* Set the power always on to increase precision. */
adc_hal_set_power_manage(ADC_POWER_SW_ON);
}
void adc_power_acquire(void)
{
portENTER_CRITICAL(&rtc_spinlock);
s_adc_power_on_cnt++;
if (s_adc_power_on_cnt == 1) {
adc_power_on_internal();
}
portEXIT_CRITICAL(&rtc_spinlock);
}
static void adc_power_off_internal(void)
{
#if CONFIG_IDF_TARGET_ESP32
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
#else
adc_hal_set_power_manage(ADC_POWER_BY_FSM);
#endif
}
void adc_power_release(void)
{
portENTER_CRITICAL(&rtc_spinlock);
s_adc_power_on_cnt--;
/* Sanity check */
if (s_adc_power_on_cnt < 0) {
portEXIT_CRITICAL(&rtc_spinlock);
ESP_LOGE(TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
abort();
} else if (s_adc_power_on_cnt == 0) {
adc_power_off_internal();
}
portEXIT_CRITICAL(&rtc_spinlock);
}
/*---------------------------------------------------------------
ADC IOs
---------------------------------------------------------------*/
@ -145,52 +92,6 @@ esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_n
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
#if CONFIG_IDF_TARGET_ESP32S2
#define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version()
static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
{
int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
}
#endif
static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
if (s_adc_cali_param[adc_n][atten]) {
ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n + 1, atten, s_adc_cali_param[adc_n][atten]);
return ;
}
// check if we can fetch the values from eFuse.
int version = esp_efuse_rtc_calib_get_ver();
uint32_t init_code = 0;
if (version == ESP_EFUSE_ADC_CALIB_VER) {
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
} else {
ESP_EARLY_LOGD(TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
adc_power_acquire();
portENTER_CRITICAL(&rtc_spinlock);
adc_ll_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
const bool internal_gnd = true;
init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
portEXIT_CRITICAL(&rtc_spinlock);
adc_power_release();
}
s_adc_cali_param[adc_n][atten] = init_code;
ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n + 1, atten, init_code);
}
void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
}
static __attribute__((constructor)) void adc_hw_calibration(void)
{
//Calculate all ICode

View File

@ -20,7 +20,7 @@
#include "freertos/ringbuf.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_lock.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "driver/gpio.h"
#include "esp_adc/adc_continuous.h"
#include "hal/adc_types.h"

View File

@ -1,87 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include "sdkconfig.h"
#include "sys/lock.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "hal/adc_types.h"
#include "esp_private/adc_lock.h"
#include "esp_private/adc2_wifi.h"
static const char *TAG = "adc_lock";
static _lock_t adc1_lock;
static _lock_t adc2_lock;
esp_err_t adc_lock_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
_lock_acquire(&adc1_lock);
}
if (adc_unit == ADC_UNIT_2) {
_lock_acquire(&adc2_lock);
}
return ESP_OK;
}
esp_err_t adc_lock_release(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_2) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc2_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc2 lock release without acquiring");
_lock_release(&adc2_lock);
}
if (adc_unit == ADC_UNIT_1) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc1_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc1 lock release without acquiring");
_lock_release(&adc1_lock);
}
return ESP_OK;
}
esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
if (_lock_try_acquire(&adc1_lock) == -1) {
return ESP_ERR_TIMEOUT;
}
}
if (adc_unit == ADC_UNIT_2) {
if (_lock_try_acquire(&adc2_lock) == -1) {
return ESP_ERR_TIMEOUT;
}
}
return ESP_OK;
}
esp_err_t adc2_wifi_acquire(void)
{
#if CONFIG_IDF_TARGET_ESP32
/* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
adc_lock_acquire(ADC_UNIT_2);
ESP_LOGD(TAG, "Wi-Fi takes adc2 lock.");
#endif
return ESP_OK;
}
esp_err_t adc2_wifi_release(void)
{
#if CONFIG_IDF_TARGET_ESP32
return adc_lock_release(ADC_UNIT_2);
#endif
return ESP_OK;
}

View File

@ -16,7 +16,7 @@
#include "driver/rtc_io.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_lock.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "hal/adc_types.h"
#include "hal/adc_oneshot_hal.h"
#include "hal/adc_ll.h"

View File

@ -1,59 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief For WIFI module to claim the usage of ADC2.
*
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
* The WIFI module may have to wait for a short time for the current conversion (if exist) to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc2_wifi_acquire(void);
/**
* @brief For WIFI module to let other tasks use the ADC2 when WIFI is not work.
*
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
* Call this function to release the occupation of ADC2 by WIFI.
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
*/
esp_err_t adc2_wifi_release(void);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
/**
* @brief This API help ADC2 calibration constructor be linked.
*
* @note This is a private function, Don't call `adc2_cal_include` in user code.
*/
void adc2_cal_include(void);
#else
/**
* @brief There's no calibration involved on this chip.
*
* @note This is a private function, Don't call `adc2_cal_include` in user code.
*/
#define adc2_cal_include()
#endif //CONFIG_IDF_TARGET_*
#ifdef __cplusplus
}
#endif

View File

@ -1,60 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "hal/adc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Acquire ADC lock by unit
*
* The lock acquiring sequence will be: ADC1, ADC2, ...
*
* @note If any of the locks are taken, this API will wait until the lock is successfully acquired.
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
*/
esp_err_t adc_lock_acquire(adc_unit_t adc_unit);
/**
* @brief Release ADC lock by unit
*
* The lock releasing sequence will be: ..., ADC2, ADC1
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
*/
esp_err_t adc_lock_release(adc_unit_t adc_unit);
/**
* @brief Try to acquire ADC lock by unit
*
* The lock acquiring sequence will be: ADC1, ADC2, ...
*
* @note If any of the locks are taken, this API will return immediately with an error `ESP_ERR_TIMEOUT`
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
* - ESP_ERR_TIMEOUT: Lock(s) is taken already
*/
esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit);
#ifdef __cplusplus
}
#endif

View File

@ -34,20 +34,6 @@ void adc_apb_periph_claim(void);
void adc_apb_periph_free(void);
/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
/**
* @brief Acquire the ADC Power
*/
void adc_power_acquire(void);
/**
* @brief Release the ADC Power
*/
void adc_power_release(void);
/*---------------------------------------------------------------
ADC IOs
---------------------------------------------------------------*/
@ -79,27 +65,6 @@ esp_err_t adc_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *chan
esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
/**
* @brief Calculate the ADC HW calibration code. (Based on the pre-stored efuse or actual calibration)
*
* @param adc_n ADC unit to calibrate
* @param atten Attenuation to use
*/
void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
/**
* @brief Set the ADC HW calibration code.
*
* @param adc_n ADC unit to calibrate
* @param atten Attenuation to use
*/
void adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Oneshot Read API ISR Version
---------------------------------------------------------------*/

View File

@ -15,7 +15,8 @@ if(NOT BOOTLOADER_BUILD)
"sleep_modes.c"
"sleep_gpio.c"
"sleep_mac_bb.c"
"regi2c_ctrl.c")
"regi2c_ctrl.c"
"adc_share_hw_ctrl.c")
if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2)
list(APPEND srcs "sleep_retention.c")

View File

@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* ADC is shared by multiple components, including:
* - esp_phy
* - esp_wifi
* - driver
*
* However, usages of above components are different.
* Therefore, we put the common used parts into `esp_hw_support`, including:
* - adc power maintainance
* - adc hw calibration settings
* - adc locks, to prevent concurrently using adc hw
*/
#include <esp_types.h>
#include "sdkconfig.h"
#include "sys/lock.h"
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/adc_hal_common.h"
#include "hal/adc_hal_conf.h"
#include "esp_private/adc_share_hw_ctrl.h"
//For calibration
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp_efuse_rtc_table.h"
#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
#include "esp_efuse_rtc_calib.h"
#endif
static const char *TAG = "adc_share_hw_ctrl";
extern portMUX_TYPE rtc_spinlock;
/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
// This gets incremented when adc_power_acquire() is called, and decremented when
// adc_power_release() is called. ADC is powered down when the value reaches zero.
// Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
static int s_adc_power_on_cnt;
static void adc_power_on_internal(void)
{
/* Set the power always on to increase precision. */
adc_hal_set_power_manage(ADC_POWER_SW_ON);
}
void adc_power_acquire(void)
{
portENTER_CRITICAL(&rtc_spinlock);
s_adc_power_on_cnt++;
if (s_adc_power_on_cnt == 1) {
adc_power_on_internal();
}
portEXIT_CRITICAL(&rtc_spinlock);
}
static void adc_power_off_internal(void)
{
#if CONFIG_IDF_TARGET_ESP32
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
#else
adc_hal_set_power_manage(ADC_POWER_BY_FSM);
#endif
}
void adc_power_release(void)
{
portENTER_CRITICAL(&rtc_spinlock);
s_adc_power_on_cnt--;
/* Sanity check */
if (s_adc_power_on_cnt < 0) {
portEXIT_CRITICAL(&rtc_spinlock);
ESP_LOGE(TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
abort();
} else if (s_adc_power_on_cnt == 0) {
adc_power_off_internal();
}
portEXIT_CRITICAL(&rtc_spinlock);
}
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
#if CONFIG_IDF_TARGET_ESP32S2
#define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version()
static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
{
int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
}
#endif
static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
if (s_adc_cali_param[adc_n][atten]) {
ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n + 1, atten, s_adc_cali_param[adc_n][atten]);
return ;
}
// check if we can fetch the values from eFuse.
int version = esp_efuse_rtc_calib_get_ver();
uint32_t init_code = 0;
if (version == ESP_EFUSE_ADC_CALIB_VER) {
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
} else {
ESP_EARLY_LOGD(TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
adc_power_acquire();
portENTER_CRITICAL(&rtc_spinlock);
adc_ll_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
const bool internal_gnd = true;
init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
portEXIT_CRITICAL(&rtc_spinlock);
adc_power_release();
}
s_adc_cali_param[adc_n][atten] = init_code;
ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n + 1, atten, init_code);
}
void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
}
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Locks
---------------------------------------------------------------*/
static _lock_t adc1_lock;
static _lock_t adc2_lock;
esp_err_t adc_lock_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
_lock_acquire(&adc1_lock);
}
if (adc_unit == ADC_UNIT_2) {
_lock_acquire(&adc2_lock);
}
return ESP_OK;
}
esp_err_t adc_lock_release(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_2) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc2_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc2 lock release without acquiring");
_lock_release(&adc2_lock);
}
if (adc_unit == ADC_UNIT_1) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc1_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc1 lock release without acquiring");
_lock_release(&adc1_lock);
}
return ESP_OK;
}
esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
if (_lock_try_acquire(&adc1_lock) == -1) {
return ESP_ERR_TIMEOUT;
}
}
if (adc_unit == ADC_UNIT_2) {
if (_lock_try_acquire(&adc2_lock) == -1) {
return ESP_ERR_TIMEOUT;
}
}
return ESP_OK;
}
esp_err_t adc2_wifi_acquire(void)
{
#if CONFIG_IDF_TARGET_ESP32
/* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
adc_lock_acquire(ADC_UNIT_2);
ESP_LOGD(TAG, "Wi-Fi takes adc2 lock.");
#endif
return ESP_OK;
}
esp_err_t adc2_wifi_release(void)
{
#if CONFIG_IDF_TARGET_ESP32
return adc_lock_release(ADC_UNIT_2);
#endif
return ESP_OK;
}

View File

@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* ADC is shared by multiple components, including:
* - esp_phy
* - esp_wifi
* - driver
*
* However, usages of above components are different.
* Therefore, we put the common used parts into `esp_hw_support`, including:
* - adc power maintainance
* - adc hw calibration settings
* - adc locks, to prevent concurrently using adc hw
*/
#pragma once
#include "esp_err.h"
#include "hal/adc_types.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
/**
* @brief Acquire the ADC Power
*/
void adc_power_acquire(void);
/**
* @brief Release the ADC Power
*/
void adc_power_release(void);
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Hardware Calibration
---------------------------------------------------------------*/
/**
* @brief Calculate the ADC HW calibration code. (Based on the pre-stored efuse or actual calibration)
*
* @param adc_n ADC unit to calibrate
* @param atten Attenuation to use
*/
void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
/**
* @brief Set the ADC HW calibration code.
*
* @param adc_n ADC unit to calibrate
* @param atten Attenuation to use
*/
void adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Cross Peripheral Locks
---------------------------------------------------------------*/
/**
* @brief Acquire ADC lock by unit
*
* The lock acquiring sequence will be: ADC1, ADC2, ...
*
* @note If any of the locks are taken, this API will wait until the lock is successfully acquired.
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
*/
esp_err_t adc_lock_acquire(adc_unit_t adc_unit);
/**
* @brief Release ADC lock by unit
*
* The lock releasing sequence will be: ..., ADC2, ADC1
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
*/
esp_err_t adc_lock_release(adc_unit_t adc_unit);
/**
* @brief Try to acquire ADC lock by unit
*
* The lock acquiring sequence will be: ADC1, ADC2, ...
*
* @note If any of the locks are taken, this API will return immediately with an error `ESP_ERR_TIMEOUT`
*
* @param[in] adc_unit ADC unit ID
*
* @return
* - ESP_OK: On success
* - ESP_ERR_TIMEOUT: Lock(s) is taken already
*/
esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit);
/**
* @brief For WIFI module to claim the usage of ADC2.
*
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
* The WIFI module may have to wait for a short time for the current conversion (if exist) to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc2_wifi_acquire(void);
/**
* @brief For WIFI module to let other tasks use the ADC2 when WIFI is not work.
*
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
* Call this function to release the occupation of ADC2 by WIFI.
*
* @return
* - ESP_OK: On success
* - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
*/
esp_err_t adc2_wifi_release(void);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
/**
* @brief This API help ADC2 calibration constructor be linked.
*
* @note This is a private function, Don't call `adc2_cal_include` in user code.
*/
void adc2_cal_include(void);
#else
/**
* @brief There's no calibration involved on this chip.
*
* @note This is a private function, Don't call `adc2_cal_include` in user code.
*/
#define adc2_cal_include()
#endif //CONFIG_IDF_TARGET_*
#ifdef __cplusplus
}
#endif

View File

@ -12,6 +12,9 @@ if(NOT BOOTLOADER_BUILD)
"esp_crypto_lock.c"
"esp_ds.c")
# init constructor for wifi
list(APPEND srcs "adc2_init_cal.c")
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
endif()

View File

@ -11,8 +11,7 @@ Don't put any other code into this file. */
#include "freertos/FreeRTOS.h"
#include "hal/adc_types.h"
#include "hal/adc_hal_common.h"
#include "esp_private/adc2_wifi.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
extern portMUX_TYPE rtc_spinlock;

View File

@ -17,6 +17,9 @@ if(NOT BOOTLOADER_BUILD)
"esp_crypto_lock.c"
"esp_ds.c")
# init constructor for wifi
list(APPEND srcs "adc2_init_cal.c")
endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

View File

@ -11,8 +11,7 @@ Don't put any other code into this file. */
#include "freertos/FreeRTOS.h"
#include "hal/adc_types.h"
#include "hal/adc_hal_common.h"
#include "esp_private/adc2_wifi.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
extern portMUX_TYPE rtc_spinlock;

View File

@ -31,7 +31,7 @@ endif()
# [refactor-todo]: requires "driver" component for periph_ctrl header file
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include" "${idf_target}/include"
PRIV_REQUIRES nvs_flash driver efuse esp_timer esp_adc esp_wifi
PRIV_REQUIRES nvs_flash driver efuse esp_timer esp_wifi
LDFRAGMENTS "${ldfragments}"
EMBED_FILES ${embed_files}
)

View File

@ -7,7 +7,7 @@
#include <stdbool.h>
#include "esp_attr.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp_private/adc_private.h"
#include "esp_private/adc_share_hw_ctrl.h"
/*
* This file is used to override the hooks provided by the PHY lib for some system features.

View File

@ -31,7 +31,7 @@ endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include"
REQUIRES esp_event esp_phy esp_netif
PRIV_REQUIRES driver esptool_py esp_pm esp_timer nvs_flash esp_adc
PRIV_REQUIRES driver esptool_py esp_pm esp_timer nvs_flash
wpa_supplicant hal lwip ${extra_priv_requires}
LDFRAGMENTS "${ldfragments}")

View File

@ -8,14 +8,13 @@
#include <esp_wifi.h>
#include "esp_log.h"
#include "esp_private/wifi.h"
#include "esp_private/adc2_wifi.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "esp_pm.h"
#include "esp_sleep.h"
#include "esp_private/pm_impl.h"
#include "esp_private/esp_clk.h"
#include "esp_wpa.h"
#include "esp_netif.h"
#include "esp_private/adc_private.h"
#include "esp_coexist_internal.h"
#include "esp_phy_init.h"
#include "phy.h"

View File

@ -8,10 +8,10 @@
#include "esp_err.h"
#include "esp_check.h"
#include "esp_log.h"
#include "esp_private/adc_private.h"
#include "esp_adc/adc_oneshot.h"
#include "hal/adc_hal_common.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/adc_share_hw_ctrl.h"
static const char *TAG = "ulp_riscv_adc";

View File

@ -19,8 +19,8 @@ ADC
- ADC oneshot mode driver has been redesigned. New driver is in ``esp_adc`` component and the include path is ``esp_adc/adc_oneshot.h``. Legacy driver is still available in the previous include path ``driver/adc.h``. However, by default, including ``driver/adc.h`` will bring a build warning like `legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively`. The warning can be suppressed by the Kconfig option :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN`.
- ADC continuous mode driver has been moved from ``driver`` component to ``esp_adc`` component. Include path has been changed from ``driver/adc.h`` to ``esp_adc/adc_continuous.h``. Legacy driver is still available in the previous include path ``driver/adc.h``. Similarly, including it will bring a build warning, and it can be suppressed by the Kconfig option :ref:`CONFIG_ADC_SUPPRESS_DEPRECATE_WARN`.
- ADC calibration driver has been redesigned. New driver is in ``esp_adc`` component and the include path is ``esp_adc/adc_cali.h`` and ``esp_adc/adc_cali_scheme.h``. Legacy driver is still available by including ``esp_adc_cal.h``. However, by default, including ``esp_adc_cal.h`` will bring a build warning like `legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h`. The warning can be suppressed by the Kconfig option :ref:`CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN`.
- API ``adc_power_acquire`` and ``adc_power_release`` have been deprecated. These two are used by other drivers to maintain ADC power due to hardware limitation. After this change, ADC power will still be handled by the drivers. However, for users who are interested in this, the include path has been changed from ``driver/adc.h`` to ``esp_private/adc_private.h``.
- Previous ``driver/adc2_wifi_private.h`` has been moved to ``esp_private/adc2_wifi.h``.
- API ``adc_power_acquire`` and ``adc_power_release`` have been deprecated. These two are used by other drivers to maintain ADC power due to hardware limitation. After this change, ADC power will still be handled by the drivers. However, for users who are interested in this, the include path has been changed from ``driver/adc.h`` to ``esp_private/adc_share_hw_ctrl.h``.
- Previous ``driver/adc2_wifi_private.h`` has been moved to ``esp_private/adc_share_hw_ctrl.h``.
- Enums ``ADC_UNIT_BOTH``, ``ADC_UNIT_ALTER`` and ``ADC_UNIT_MAX`` in ``adc_unit_t`` have been removed.
- Enum ``ADC_CHANNEL_MAX`` in ``adc_channel_t`` has been removed. Some channels are not supported on some chips, driver will give a dynamic error if an unsupported channels are used.
- Enum ``ADC_ATTEN_MAX`` has been removed. Some attenuations are not supported on some chips, driver will give a dynamic error if an unsupported attenuation is used.

View File

@ -40,10 +40,8 @@ set(extra_components_which_shouldnt_be_included
# Figure out if these components can exist without a dependency on efuse.
# If not, see if esp_hw_support can provide minimal efuse component replacement in G1 build.
efuse
# [refactor-todo]: esp_adc is a dependency of driver, esp_phy and esp_wii.
# [refactor-todo]: esp_adc is a dependency of driver.
# Driver dependency only exists in legacy drivers. After removing deprecated drivers, this dependency can be fixed
# esp_phy requires esp_adc to maintain the ADC power for PWDET usage
# esp_wifi requires esp_adc to do the initial calibration for PWDET usage
esp_adc
# esp_pm is pulled in by freertos, can be made a weak dependency
# conditional on related Kconfig option. It is also used by esp_wifi, driver, mbedtls,