Skip to content

Commit

Permalink
Merge branch 'feat/lp_core_lp_adc_support' into 'master'
Browse files Browse the repository at this point in the history
feat(lp_adc): Addded support for LP ADC for the LP core on esp32p4

Closes IDF-6875 and IDF-10205

See merge request espressif/esp-idf!33117
  • Loading branch information
sudeep-mohanty committed Sep 11, 2024
2 parents eab9876 + 0b75e75 commit 1b6a829
Show file tree
Hide file tree
Showing 24 changed files with 848 additions and 17 deletions.
16 changes: 12 additions & 4 deletions components/esp_adc/adc_oneshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,24 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a
unit->unit_id = init_config->unit_id;
unit->ulp_mode = init_config->ulp_mode;

adc_oneshot_clk_src_t clk_src = ADC_DIGI_CLK_SRC_DEFAULT;
if (init_config->clk_src) {
clk_src = init_config->clk_src;
adc_oneshot_clk_src_t clk_src;
#if SOC_LP_ADC_SUPPORTED
if (init_config->ulp_mode != ADC_ULP_MODE_DISABLE) {
clk_src = LP_ADC_CLK_SRC_LP_DYN_FAST;
} else
#endif /* CONFIG_SOC_LP_ADC_SUPPORTED */
{
clk_src = ADC_DIGI_CLK_SRC_DEFAULT;
if (init_config->clk_src) {
clk_src = init_config->clk_src;
}
}
uint32_t clk_src_freq_hz = 0;
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz), err, TAG, "clock source not supported");

adc_oneshot_hal_cfg_t config = {
.unit = init_config->unit_id,
.work_mode = (init_config->ulp_mode == ADC_ULP_MODE_FSM) ? ADC_HAL_ULP_FSM_MODE : ADC_HAL_SINGLE_READ_MODE,
.work_mode = (init_config->ulp_mode != ADC_ULP_MODE_DISABLE) ? ADC_HAL_LP_MODE : ADC_HAL_SINGLE_READ_MODE,
.clk_src = clk_src,
.clk_src_freq_hz = clk_src_freq_hz,
};
Expand Down
8 changes: 4 additions & 4 deletions components/hal/adc_hal_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ static adc_ll_controller_t get_controller(adc_unit_t unit, adc_hal_work_mode_t w
{
if (unit == ADC_UNIT_1) {
switch (work_mode) {
#if SOC_ULP_HAS_ADC
case ADC_HAL_ULP_FSM_MODE:
#if SOC_ULP_HAS_ADC || SOC_LP_CORE_SUPPORT_LP_ADC
case ADC_HAL_LP_MODE:
return ADC_LL_CTRL_ULP;
#endif
case ADC_HAL_SINGLE_READ_MODE:
Expand All @@ -35,8 +35,8 @@ static adc_ll_controller_t get_controller(adc_unit_t unit, adc_hal_work_mode_t w
}
} else {
switch (work_mode) {
#if SOC_ULP_HAS_ADC
case ADC_HAL_ULP_FSM_MODE:
#if SOC_ULP_HAS_ADC || SOC_LP_CORE_SUPPORT_LP_ADC
case ADC_HAL_LP_MODE:
return ADC_LL_CTRL_ULP;
#endif
#if !SOC_ADC_ARBITER_SUPPORTED //No ADC2 arbiter on ESP32
Expand Down
10 changes: 9 additions & 1 deletion components/hal/adc_oneshot_hal.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -62,8 +62,16 @@ void adc_oneshot_hal_setup(adc_oneshot_hal_ctx_t *hal, adc_channel_t chan)
adc_ll_digi_clk_sel(hal->clk_src);
adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT);
adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT);
#else
#if SOC_LP_ADC_SUPPORTED
if (hal->work_mode == ADC_HAL_LP_MODE) {
adc_ll_set_sar_clk_div(unit, LP_ADC_LL_SAR_CLK_DIV_DEFAULT(unit));
} else {
adc_ll_set_sar_clk_div(unit, ADC_LL_SAR_CLK_DIV_DEFAULT(unit));
}
#else
adc_ll_set_sar_clk_div(unit, ADC_LL_SAR_CLK_DIV_DEFAULT(unit));
#endif //SOC_LP_ADC_SUPPORTED
if (unit == ADC_UNIT_2) {
adc_ll_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
}
Expand Down
9 changes: 5 additions & 4 deletions components/hal/esp32p4/include/hal/adc_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C" {
---------------------------------------------------------------*/
#define ADC_LL_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (1)
#define LP_ADC_LL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (2)
#define ADC_LL_DELAY_CYCLE_AFTER_DONE_SIGNAL (0)

/*---------------------------------------------------------------
Expand Down Expand Up @@ -616,8 +617,8 @@ static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t c
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;
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_DIG:
LP_ADC.meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
Expand All @@ -636,8 +637,8 @@ static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t c
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;
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_DIG:
LP_ADC.meas2_mux.sar2_rtc_force = 0; // 1: Select digital control; 0: Select RTC control.
Expand Down
4 changes: 2 additions & 2 deletions components/hal/include/hal/adc_hal_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ typedef enum adc_hal_work_mode_t {
ADC_HAL_SINGLE_READ_MODE,
ADC_HAL_CONTINUOUS_READ_MODE,
ADC_HAL_PWDET_MODE,
ADC_HAL_ULP_FSM_MODE,
ADC_HAL_LP_MODE,
} adc_hal_work_mode_t;

/**
Expand Down Expand Up @@ -61,7 +61,7 @@ void adc_hal_arbiter_config(adc_arbiter_t *config);
/**
* @brief Initialize default parameter for the calibration block.
*
* @param adc_n ADC index numer
* @param adc_n ADC index number
*/
void adc_hal_calibration_init(adc_unit_t adc_n);

Expand Down
3 changes: 3 additions & 0 deletions components/hal/include/hal/adc_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ typedef enum {
ADC_ULP_MODE_DISABLE = 0, ///< ADC ULP mode is disabled
ADC_ULP_MODE_FSM = 1, ///< ADC is controlled by ULP FSM
ADC_ULP_MODE_RISCV = 2, ///< ADC is controlled by ULP RISCV
#if SOC_LP_ADC_SUPPORTED
ADC_ULP_MODE_LP_CORE = 3, ///< ADC is controlled by LP Core
#endif // SOC_LP_ADC_SUPPORTED
} adc_ulp_mode_t;

/**
Expand Down
8 changes: 8 additions & 0 deletions components/soc/esp32p4/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ config SOC_LP_SPI_SUPPORTED
bool
default y

config SOC_LP_ADC_SUPPORTED
bool
default y

config SOC_SPIRAM_SUPPORTED
bool
default y
Expand Down Expand Up @@ -1926,3 +1930,7 @@ config SOC_LCDCAM_CAM_DATA_WIDTH_MAX
config SOC_LP_CORE_SUPPORT_ETM
bool
default y

config SOC_LP_CORE_SUPPORT_LP_ADC
bool
default y
14 changes: 14 additions & 0 deletions components/soc/esp32p4/include/soc/clk_tree_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,20 @@ typedef enum {
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;

///////////////////////////////////////////////LP_ADC///////////////////////////////////////////////////////////////////

/**
* @brief Array initializer for all supported clock sources of LP_ADC
*/
#define SOC_LP_ADC_CLKS {SOC_MOD_CLK_LP_DYN_FAST}

/**
* @brief LP ADC controller clock source
*/
typedef enum {
LP_ADC_CLK_SRC_LP_DYN_FAST = SOC_MOD_CLK_LP_DYN_FAST, /*!< Select LP_DYN_FAST as the source clock */
} soc_periph_lp_adc_clk_src_t;

//////////////////////////////////////////////////MWDT/////////////////////////////////////////////////////////////////

/**
Expand Down
3 changes: 2 additions & 1 deletion components/soc/esp32p4/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
#define SOC_LP_I2C_SUPPORTED 1
#define SOC_LP_I2S_SUPPORTED 1
#define SOC_LP_SPI_SUPPORTED 1
#define SOC_LP_ADC_SUPPORTED 1
#define SOC_SPIRAM_SUPPORTED 1
#define SOC_PSRAM_DMA_CAPABLE 1
// #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534
#define SOC_SDMMC_HOST_SUPPORTED 1
#define SOC_CLK_TREE_SUPPORTED 1
#define SOC_ASSIST_DEBUG_SUPPORTED 1
Expand Down Expand Up @@ -738,3 +738,4 @@

/*------------------------------------- ULP CAPS -------------------------------------*/
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
#define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */
4 changes: 4 additions & 0 deletions components/ulp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
if(CONFIG_SOC_LP_CORE_SUPPORT_ETM)
list(APPEND srcs "lp_core/lp_core_etm.c")
endif()

if(CONFIG_SOC_LP_ADC_SUPPORTED)
list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_adc_shared.c")
endif()
endif()

idf_component_register(SRCS ${srcs}
Expand Down
3 changes: 2 additions & 1 deletion components/ulp/cmake/IDFULPProject.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ function(ulp_apply_default_sources ulp_app_name)
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_interrupt.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_i2c.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c")
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c")

set(target_folder ${IDF_TARGET})

Expand Down
113 changes: 113 additions & 0 deletions components/ulp/lp_core/shared/include/ulp_lp_core_lp_adc_shared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "esp_err.h"
#include "hal/adc_types.h"
#include "esp_adc/adc_oneshot.h"

/**
* @brief LP ADC channel configurations
*/
typedef adc_oneshot_chan_cfg_t lp_core_lp_adc_chan_cfg_t;

/**
* @brief Initialize the LP ADC
*
* @note We only support LP ADC1 and not LP ADC2 due to a HW issue.
*
* @param unit_id LP ADC unit to initialize
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG if the unit_id is invalid
* ESP_ERR_NOT_SUPPORTED if the API is not supported on the LP Core
* ESP_FAIL if the ADC unit failed to initialize
*/
esp_err_t lp_core_lp_adc_init(adc_unit_t unit_id);

/**
* @brief Deinitialize the LP ADC
*
* @param unit_id LP ADC unit to deinitialize
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG if the unit_id is invalid
* ESP_ERR_NOT_SUPPORTED if the API is not supported on the LP Core
* ESP_FAIL if the ADC unit failed to deinitialize
*/
esp_err_t lp_core_lp_adc_deinit(adc_unit_t unit_id);

/**
* @brief Configure an LP ADC channel
*
* @param unit_id ADC unit to configure the channel for
* @param channel ADC channel to configure
* @param chan_config Configuration for the channel
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG if the unit_id is invalid
* ESP_ERR_NOT_SUPPORTED if the API is not supported on the LP Core
* ESP_FAIL if the channel configuration fails
*/
esp_err_t lp_core_lp_adc_config_channel(adc_unit_t unit_id, adc_channel_t channel, const lp_core_lp_adc_chan_cfg_t *chan_config);

/**
* @brief Read the raw ADC value from a channel
*
* @note The raw value is the 12-bit value read from the ADC.
* The value is between 0 and 4095. To convert this value
* to a voltage, use the formula:
* voltage = (raw_value * (1.1v / 4095)) * attenuation
*
* Alternatively, use lp_core_lp_adc_read_channel_converted()
* to get the converted value.
*
* @param[in] unit_id ADC unit to configure the channel for
* @param[in] channel ADC channel to configure
* @param[in] adc_raw Pointer to store the raw 12-bit ADC value
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG if the unit_id is invalid
* ESP_FAIL if the read fails
*/
esp_err_t lp_core_lp_adc_read_channel_raw(adc_unit_t unit_id, adc_channel_t channel, int *adc_raw);

/**
* @brief Read the converted ADC value in millivolts from a channel
*
* @note The API converts the measured voltage based on the
* internal reference voltage of 1.1v and the the attenuation
* factors. It uses the formula:
* voltage = (raw_value * (1.1v / 4095)) * attenuation
*
* To avoid complex floating-point operations at runtime,
* the API converts the raw data to millivolts. Also, the
* conversion approximates the calculation when scaling
* the voltage by using pre-computed attenuation factors.
*
* @note The conversion approximates the measured voltage based on the
* internal reference voltage of 1.1v and the approximations of
* the attenuation factors.
*
* @param[in] unit_id ADC unit to configure the channel for
* @param[in] channel ADC channel to configure
* @param[out] voltage_mv Pointer to store the converted ADC value in millivolts
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG if the unit_id is invalid or voltage_mv is NULL
* ESP_FAIL if the read fails
*/
esp_err_t lp_core_lp_adc_read_channel_converted(adc_unit_t unit_id, adc_channel_t channel, int *voltage_mv);

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 1b6a829

Please sign in to comment.