diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index b93c9b3a4ff..cdf18b5eb7b 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -6,7 +6,8 @@ set(includes "") if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) list(APPEND srcs - "ulp_common/ulp_common.c") + "ulp_common/ulp_common.c" + "ulp_common/ulp_adc.c") list(APPEND includes ulp_common/include @@ -25,7 +26,6 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) list(APPEND srcs "ulp_riscv/ulp_riscv.c" "ulp_riscv/ulp_riscv_lock.c" - "ulp_riscv/ulp_riscv_adc.c" "ulp_riscv/ulp_riscv_i2c.c") list(APPEND includes diff --git a/components/ulp/ulp_common/include/ulp_adc.h b/components/ulp/ulp_common/include/ulp_adc.h new file mode 100644 index 00000000000..5f1b93967b2 --- /dev/null +++ b/components/ulp/ulp_common/include/ulp_adc.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/adc_types.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + adc_unit_t adc_n; // ADC Unit + adc_channel_t channel; // ADC channel + adc_atten_t atten; // ADC channel attenuation + adc_bitwidth_t width; // ADC bit width, only used for ADC unit 1 + adc_ulp_mode_t ulp_mode; // ADC ULP Mode +} ulp_adc_cfg_t; // ULP FSM ADC configuration parameters + +/** + * @brief Initialize and calibrate the ADC for use by ULP FSM + * + * @param cfg Configuration parameters + * @return esp_err_t ESP_OK for successful. + */ +esp_err_t ulp_adc_init(const ulp_adc_cfg_t *cfg); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/ulp_riscv/ulp_riscv_adc.c b/components/ulp/ulp_common/ulp_adc.c similarity index 72% rename from components/ulp/ulp_riscv/ulp_riscv_adc.c rename to components/ulp/ulp_common/ulp_adc.c index 9241dd9c6a8..a46f928eb73 100644 --- a/components/ulp/ulp_riscv/ulp_riscv_adc.c +++ b/components/ulp/ulp_common/ulp_adc.c @@ -4,7 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ulp_riscv_adc.h" +#include "sdkconfig.h" +#include "ulp_adc.h" #include "esp_err.h" #include "esp_check.h" #include "esp_log.h" @@ -13,9 +14,9 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/adc_share_hw_ctrl.h" -static const char *TAG = "ulp_riscv_adc"; +static const char *TAG = "ulp_adc"; -esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg) +esp_err_t ulp_adc_init(const ulp_adc_cfg_t *cfg) { esp_err_t ret = ESP_OK; @@ -24,10 +25,19 @@ esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg) //-------------ADC1 Init---------------// adc_oneshot_unit_handle_t adc1_handle; + adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = cfg->adc_n, - .ulp_mode = ADC_ULP_MODE_RISCV, + .ulp_mode = cfg->ulp_mode, }; + + if (init_config1.ulp_mode == ADC_ULP_MODE_DISABLE) { + /* Default to RISCV for backward compatibility */ + ESP_LOGI(TAG, "No ulp mode specified in cfg struct, default to riscv"); + init_config1.ulp_mode = ADC_ULP_MODE_RISCV; + } + + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); //-------------ADC1 Config---------------// @@ -38,7 +48,10 @@ esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg) ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, cfg->channel, &config)); //Calibrate the ADC +#if SOC_ADC_CALIBRATION_V1_SUPPORTED adc_set_hw_calibration_code(cfg->adc_n, cfg->atten); +#endif + esp_sleep_enable_adc_tsens_monitor(true); err: diff --git a/components/ulp/ulp_riscv/include/ulp_riscv_adc.h b/components/ulp/ulp_riscv/include/ulp_riscv_adc.h index 05b03264c94..098b7af5135 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv_adc.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv_adc.h @@ -9,24 +9,15 @@ #include "hal/adc_types.h" #include "esp_err.h" +#include "ulp_adc.h" + #ifdef __cplusplus extern "C" { #endif -typedef struct { - adc_unit_t adc_n; // ADC Unit - adc_channel_t channel; // ADC channel - adc_atten_t atten; // ADC channel attenuation - adc_bitwidth_t width; // ADC bit width, only used for ADC unit 1 -} ulp_riscv_adc_cfg_t; // ULP Riscv ADC configuration parameters - -/** - * @brief Initialize and calibrate the ADC for use by ULP RISCV - * - * @param cfg Configuration parameters - * @return esp_err_t ESP_OK for successful. - */ -esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg); +/* Kept for backwards compatibilty */ +#define ulp_riscv_adc_cfg_t ulp_adc_cfg_t +#define ulp_riscv_adc_init ulp_adc_init #ifdef __cplusplus } diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index f2efe5d5f30..29ea59a3bf9 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -160,7 +160,7 @@ examples/system/ulp_fsm/ulp: examples/system/ulp_fsm/ulp_adc: enable: - - if: IDF_TARGET == "esp32" + - if: IDF_TARGET in ["esp32", "esp32s3"] temporary: true reason: the other targets are not tested yet diff --git a/examples/system/ulp_fsm/ulp_adc/README.md b/examples/system/ulp_fsm/ulp_adc/README.md index b27ef2772d1..21dc77038fb 100644 --- a/examples/system/ulp_fsm/ulp_adc/README.md +++ b/examples/system/ulp_fsm/ulp_adc/README.md @@ -1,11 +1,11 @@ -| Supported Targets | ESP32 | -| ----------------- | ----- | +| Supported Targets | ESP32 | ESP32-S3 | +| ----------------- | ----- | -------- | # ULP ADC Example This example demonstrates how to use the ULP coprocessor to poll ADC in deep sleep. -ULP program periodically measures the input voltage on GPIO34. The voltage is compared to two thresholds. If the voltage is less than the low threshold, or higher than the high threshold, ULP wakes up the system. +ULP program periodically measures the input voltage on ADC_CHANNEL_6 (GPIO34 on ESP32, GPIO7 on ESP32-S3). The voltage is compared to two thresholds. If the voltage is less than the low threshold, or higher than the high threshold, ULP wakes up the system. By default, thresholds are set to 1.35V and 1.75V, approximately. diff --git a/examples/system/ulp_fsm/ulp_adc/main/ulp/adc.S b/examples/system/ulp_fsm/ulp_adc/main/ulp/adc.S index 1b59ccee73a..b96f51c3b07 100644 --- a/examples/system/ulp_fsm/ulp_adc/main/ulp/adc.S +++ b/examples/system/ulp_fsm/ulp_adc/main/ulp/adc.S @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /* ULP Example: using ADC in deep sleep This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -22,9 +27,9 @@ */ #include "soc/rtc_cntl_reg.h" #include "soc/soc_ulp.h" +#include "example_config.h" - /* ADC1 channel 6, GPIO34 */ - .set adc_channel, 6 + .set adc_channel, EXAMPLE_ADC_CHANNEL /* Configure the number of ADC samples to average on each measurement. For convenience, make it a power of 2. */ diff --git a/examples/system/ulp_fsm/ulp_adc/main/ulp/example_config.h b/examples/system/ulp_fsm/ulp_adc/main/ulp/example_config.h new file mode 100644 index 00000000000..baa86dd842d --- /dev/null +++ b/examples/system/ulp_fsm/ulp_adc/main/ulp/example_config.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +/* Ints are used here to be able to include the file in assembly as well */ +#define EXAMPLE_ADC_CHANNEL 6 // ADC_CHANNEL_6, GPIO34 on ESP32, GPIO7 on ESP32-S3 +#define EXAMPLE_ADC_UNIT 0 // ADC_UNIT_1 +#define EXAMPLE_ADC_ATTEN 3 // ADC_ATTEN_DB_11 +#define EXAMPLE_ADC_WIDTH 0 // ADC_BITWIDTH_DEFAULT + +/* Set low and high thresholds, approx. 1.35V - 1.75V*/ +#define EXAMPLE_ADC_LOW_TRESHOLD 1500 +#define EXAMPLE_ADC_HIGH_TRESHOLD 2000 diff --git a/examples/system/ulp_fsm/ulp_adc/main/ulp_adc_example_main.c b/examples/system/ulp_fsm/ulp_adc/main/ulp_adc_example_main.c index 6b3ff56485f..a8d431c7559 100644 --- a/examples/system/ulp_fsm/ulp_adc/main/ulp_adc_example_main.c +++ b/examples/system/ulp_fsm/ulp_adc/main/ulp_adc_example_main.c @@ -10,16 +10,18 @@ #include #include #include "esp_sleep.h" -#include "nvs.h" -#include "nvs_flash.h" #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "driver/gpio.h" #include "driver/rtc_io.h" -#include "driver/dac.h" -#include "esp32/ulp.h" +#include "ulp.h" #include "ulp_main.h" #include "esp_adc/adc_oneshot.h" +#include "ulp/example_config.h" +#include "ulp_adc.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); @@ -51,6 +53,12 @@ void app_main(void) printf("Entering deep sleep\n\n"); start_ulp_program(); ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() ); + +#if !CONFIG_IDF_TARGET_ESP32 + /* RTC peripheral power domain needs to be kept on to keep SAR ADC related configs during sleep */ + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); +#endif + esp_deep_sleep_start(); } @@ -60,35 +68,31 @@ static void init_ulp_program(void) (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t)); ESP_ERROR_CHECK(err); - //-------------ADC1 Init---------------// - adc_oneshot_unit_handle_t adc1_handle; - adc_oneshot_unit_init_cfg_t init_config1 = { - .unit_id = ADC_UNIT_1, + ulp_adc_cfg_t cfg = { + .adc_n = EXAMPLE_ADC_UNIT, + .channel = EXAMPLE_ADC_CHANNEL, + .width = EXAMPLE_ADC_WIDTH, + .atten = EXAMPLE_ADC_ATTEN, .ulp_mode = ADC_ULP_MODE_FSM, }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); - //-------------ADC1 Channel Config---------------// - // Note: when changing channel here, also change 'adc_channel' constant in adc.S - adc_oneshot_chan_cfg_t config = { - .bitwidth = ADC_BITWIDTH_DEFAULT, - .atten = ADC_ATTEN_DB_11, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_6, &config)); + ESP_ERROR_CHECK(ulp_adc_init(&cfg)); - /* Set low and high thresholds, approx. 1.35V - 1.75V*/ - ulp_low_thr = 1500; - ulp_high_thr = 2000; + ulp_low_thr = EXAMPLE_ADC_LOW_TRESHOLD; + ulp_high_thr = EXAMPLE_ADC_HIGH_TRESHOLD; /* Set ULP wake up period to 20ms */ ulp_set_wakeup_period(0, 20000); +#if CONFIG_IDF_TARGET_ESP32 /* Disconnect GPIO12 and GPIO15 to remove current drain through - * pullup/pulldown resistors. + * pullup/pulldown resistors on modules which have these (e.g. ESP32-WROVER) * GPIO12 may be pulled high to select flash voltage. */ rtc_gpio_isolate(GPIO_NUM_12); rtc_gpio_isolate(GPIO_NUM_15); +#endif // CONFIG_IDF_TARGET_ESP32 + esp_deep_sleep_disable_rom_logging(); // suppress boot messages } diff --git a/examples/system/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py b/examples/system/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py index 0908d8c931b..b5c9d9974ca 100644 --- a/examples/system/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py +++ b/examples/system/ulp_fsm/ulp_adc/pytest_ulp_fsm_adc.py @@ -8,6 +8,7 @@ @pytest.mark.esp32 +@pytest.mark.esp32s3 @pytest.mark.generic def test_ulp_fsm_adc(dut: Dut) -> None: diff --git a/examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c b/examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c index b18951b6d43..c1806f6d02a 100644 --- a/examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c +++ b/examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c @@ -15,7 +15,7 @@ #include #include "esp_sleep.h" #include "ulp_riscv.h" -#include "ulp_riscv_adc.h" +#include "ulp_adc.h" #include "ulp_main.h" #include "ulp/example_config.h" @@ -56,14 +56,15 @@ void app_main(void) static void init_ulp_program(void) { - ulp_riscv_adc_cfg_t cfg = { - .adc_n = EXAMPLE_ADC_UNIT, - .channel = EXAMPLE_ADC_CHANNEL, - .width = EXAMPLE_ADC_WIDTH, - .atten = EXAMPLE_ADC_ATTEN, + ulp_adc_cfg_t cfg = { + .adc_n = EXAMPLE_ADC_UNIT, + .channel = EXAMPLE_ADC_CHANNEL, + .width = EXAMPLE_ADC_WIDTH, + .atten = EXAMPLE_ADC_ATTEN, + .ulp_mode = ADC_ULP_MODE_RISCV, }; - ESP_ERROR_CHECK(ulp_riscv_adc_init(&cfg)); + ESP_ERROR_CHECK(ulp_adc_init(&cfg)); esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)); ESP_ERROR_CHECK(err);