diff --git a/components/bootloader_support/src/bootloader_random_esp32s3.c b/components/bootloader_support/src/bootloader_random_esp32s3.c index ef9f630694..65eafa46ed 100644 --- a/components/bootloader_support/src/bootloader_random_esp32s3.c +++ b/components/bootloader_support/src/bootloader_random_esp32s3.c @@ -83,8 +83,6 @@ void bootloader_random_disable(void) REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); - //Stop SAR ADC clock - CLEAR_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_SARADC_CLK_EN); //Power off SAR ADC REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0); //return to ADC RTC controller diff --git a/components/driver/adc_single.c b/components/driver/adc_single.c index 9673dc2758..14a79fc490 100644 --- a/components/driver/adc_single.c +++ b/components/driver/adc_single.c @@ -225,7 +225,7 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num) #if SOC_ADC_RTC_CTRL_SUPPORTED #if SOC_ADC_CALIBRATION_V1_SUPPORTED -static uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan) +uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan) { adc_atten_t atten = adc_ll_get_atten(adc_n, chan); extern uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten); diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h new file mode 100644 index 0000000000..ee0b72953f --- /dev/null +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode + * + * @note This state is kept in RTC memory and will keep its value after a deep sleep wakeup + * + */ +void esp_sleep_enable_adc_tsens_monitor(bool enable); + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index fa478f5703..d40572a170 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -182,7 +182,7 @@ static bool s_light_sleep_wakeup = false; static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED; static const char *TAG = "sleep"; -static bool s_adc_tsen_enabled = false; +static RTC_FAST_ATTR bool s_adc_tsen_enabled = false; //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. static bool s_ultra_low_enabled = false; @@ -1386,7 +1386,7 @@ void esp_deep_sleep_disable_rom_logging(void) rtc_suppress_rom_log(); } -void rtc_sleep_enable_adc_tesn_monitor(bool enable) +void esp_sleep_enable_adc_tsens_monitor(bool enable) { s_adc_tsen_enabled = enable; } diff --git a/components/esp_system/test_apps/rtc_power_modes/README.md b/components/esp_system/test_apps/rtc_power_modes/README.md index 5c923a3eee..e485773505 100644 --- a/components/esp_system/test_apps/rtc_power_modes/README.md +++ b/components/esp_system/test_apps/rtc_power_modes/README.md @@ -8,12 +8,12 @@ This test app is to enter 7 different sub power modes we have, so that the power Currently there are 6 sub power modes, 3 for deepsleep and 3 for lightsleep. Show as below (priority from high to low). ## Deepsleep -1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `rtc_sleep_enable_adc_tesn_monitor`. +1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `esp_sleep_enable_adc_tsens_monitor`. 2. Default mode. 3. Ultra low power mode. To enable this mode, call `rtc_sleep_enable_ultra_low`. Note if mode 1 has higher priority than this. ## Lightsleep 1. Mode for using 40 MHz XTAL in lightsleep. To enable this mode, call `esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON)`. 2. Mode for using 8M clock by digital system (peripherals). To enable this mode, initialize LEDC with 8M clock source. -3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `rtc_sleep_enable_adc_tesn_monitor`. +3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `esp_sleep_enable_adc_tsens_monitor`. 4. Default mode. diff --git a/components/esp_system/test_apps/rtc_power_modes/main/test_rtc_power.c b/components/esp_system/test_apps/rtc_power_modes/main/test_rtc_power.c index b59a828f4f..d0ed9b2b3c 100644 --- a/components/esp_system/test_apps/rtc_power_modes/main/test_rtc_power.c +++ b/components/esp_system/test_apps/rtc_power_modes/main/test_rtc_power.c @@ -16,6 +16,7 @@ #include "soc/soc_caps.h" #include "driver/ledc.h" #include "soc/rtc.h" +#include "esp_private/esp_sleep_internal.h" static const char TAG[] = "rtc_power"; @@ -30,8 +31,7 @@ TEST_CASE("Power Test: Deepsleep (with ADC/TSEN in monitor)", "[pm]") { rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source - extern void rtc_sleep_enable_adc_tesn_monitor(bool); - rtc_sleep_enable_adc_tesn_monitor(true); + esp_sleep_enable_adc_tsens_monitor(true); test_deepsleep(); } @@ -108,8 +108,8 @@ TEST_CASE("Power Test: Lightsleep (with ADC/TSEN in monitor)", "[pm]") { rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source - extern void rtc_sleep_enable_adc_tesn_monitor(bool); - rtc_sleep_enable_adc_tesn_monitor(true); + extern void esp_sleep_enable_adc_tsens_monitor(bool); + esp_sleep_enable_adc_tsens_monitor(true); test_lightsleep(); } diff --git a/components/hal/platform_port/include/hal/assert.h b/components/hal/platform_port/include/hal/assert.h index 3423ed96e6..19847d9936 100644 --- a/components/hal/platform_port/include/hal/assert.h +++ b/components/hal/platform_port/include/hal/assert.h @@ -31,7 +31,9 @@ extern void abort(void); #endif #endif -#if CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent +#if IS_ULP_COCPU +#define HAL_ASSERT(__e) ((void)(__e)) +#elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent #define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : abort()) #elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 2 // full assertion #define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func(__FILE__, __LINE__, __ASSERT_FUNC, #__e)) diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index c38c122c56..971abfebfa 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -23,7 +23,8 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) elseif(CONFIG_ULP_COPROC_TYPE_RISCV) list(APPEND srcs - "ulp_riscv/ulp_riscv.c") + "ulp_riscv/ulp_riscv.c" + "ulp_riscv/ulp_riscv_adc.c") list(APPEND includes ulp_riscv/include) @@ -31,4 +32,5 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) endif() idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ${includes}) + INCLUDE_DIRS ${includes} + REQUIRES driver) diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 5b98d008cf..7209f06e1d 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -71,8 +71,9 @@ add_custom_target(${ULP_APP_NAME}_ld_script if(ULP_COCPU_IS_RISCV) #risc-v ulp uses extra files for building: list(APPEND ULP_S_SOURCES - "${IDF_PATH}/components/ulp/ulp_riscv/start.S" - "${IDF_PATH}/components/ulp/ulp_riscv/ulp_riscv_utils.c") + "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/start.S" + "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c" + "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c") #dummy loop to force pre-processed linker file generation: foreach(ulp_s_source ${ULP_S_SOURCES}) @@ -95,7 +96,9 @@ if(ULP_COCPU_IS_RISCV) list(APPEND EXTRA_LINKER_ARGS "-Wl,--gc-sections") list(APPEND EXTRA_LINKER_ARGS "-Wl,-Map=\"${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}.map\"") #Makes the csr utillies for riscv visible: - target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/include") + target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/include") + target_link_libraries(${ULP_APP_NAME} "-T \"${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.periperals.ld\"") + target_compile_definitions(${ULP_APP_NAME} PRIVATE IS_ULP_COCPU) else() diff --git a/components/ulp/ld/esp32s2.periperals.ld b/components/ulp/ld/esp32s2.periperals.ld new file mode 100644 index 0000000000..391b20c1c1 --- /dev/null +++ b/components/ulp/ld/esp32s2.periperals.ld @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +PROVIDE ( RTCCNTL = 0x8000 ); +PROVIDE ( RTCIO = 0xA400 ); +PROVIDE ( SENS = 0xC800 ); diff --git a/components/ulp/ld/esp32s3.periperals.ld b/components/ulp/ld/esp32s3.periperals.ld new file mode 100644 index 0000000000..391b20c1c1 --- /dev/null +++ b/components/ulp/ld/esp32s3.periperals.ld @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +PROVIDE ( RTCCNTL = 0x8000 ); +PROVIDE ( RTCIO = 0xA400 ); +PROVIDE ( SENS = 0xC800 ); diff --git a/components/ulp/project_include.cmake b/components/ulp/project_include.cmake index 1b7326bf04..48e7fa2235 100644 --- a/components/ulp/project_include.cmake +++ b/components/ulp/project_include.cmake @@ -58,6 +58,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) -DULP_APP_NAME=${app_name} -DCOMPONENT_DIR=${COMPONENT_DIR} -DCOMPONENT_INCLUDES=$ + -DIDF_TARGET=${idf_target} -DIDF_PATH=${idf_path} -DSDKCONFIG_HEADER=${SDKCONFIG_HEADER} -DPYTHON=${python} diff --git a/components/ulp/test/CMakeLists.txt b/components/ulp/test/CMakeLists.txt index 3154f7d93e..d658af3e3f 100644 --- a/components/ulp/test/CMakeLists.txt +++ b/components/ulp/test/CMakeLists.txt @@ -1,8 +1,3 @@ -if(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") - #Disabled for now due to RTC bug IDF-4801 - return() -endif() - if(NOT CONFIG_ULP_COPROC_TYPE_FSM AND NOT CONFIG_ULP_COPROC_TYPE_RISCV) # Nothing to test if no co-processor enabled return() diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h index c685bb328e..d6da5cb199 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h @@ -6,4 +6,4 @@ #pragma once #warning Contents of ulp_riscv/ulp_riscv.h have been deprecated. Please include the header which contains the actual definitions you are trying to use, e.g. "ulp_riscv_register_ops.h". -#include "../ulp_riscv_register_ops.h" +#include "../../ulp_core/include/ulp_riscv_register_ops.h" diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h index dff35465f0..9f7b1b5c86 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h @@ -6,5 +6,5 @@ #pragma once -#warning "ulp_riscv_gpio.h has been moved one level up. Please include the file without the ulp_riscv prefix." -#include "../ulp_riscv_gpio.h" +#warning "ulp_riscv_gpio.h has been moved. Please include the file without the ulp_riscv prefix." +#include "../../ulp_core/include/ulp_riscv_gpio.h" diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h index fa0e358f03..fe07242542 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h @@ -5,5 +5,5 @@ */ #pragma once -#warning ulp_riscv_register_ops.h has been moved one level up. Please include the file without the ulp_riscv prefix. -#include "../ulp_riscv_register_ops.h" +#warning ulp_riscv_register_ops.h has been moved. Please include the file without the ulp_riscv prefix. +#include "../../ulp_core/include/ulp_riscv_register_ops.h" diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h index d0a7cfb7fb..ce8c6b3c3c 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h @@ -5,5 +5,5 @@ */ #pragma once -#warning ulp_riscv_utils.h has been moved one level up. Please include the file without the ulp_riscv prefix. -#include "../ulp_riscv_utils.h" +#warning ulp_riscv_utils.h has been moved. Please include the file without the ulp_riscv prefix. +#include "../../ulp_core/include/ulp_riscv_utils.h" diff --git a/components/ulp/ulp_riscv/include/ulp_riscv_adc.h b/components/ulp/ulp_riscv/include/ulp_riscv_adc.h new file mode 100644 index 0000000000..6b0983c75a --- /dev/null +++ b/components/ulp/ulp_riscv/include/ulp_riscv_adc.h @@ -0,0 +1,29 @@ +/* + * 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_bits_width_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); diff --git a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_adc_ulp_core.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_adc_ulp_core.h new file mode 100644 index 0000000000..9c27834c12 --- /dev/null +++ b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_adc_ulp_core.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/adc_ll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Start an ADC conversion and get the converted value. + * + * @note Will block until the conversion is completed + * + * @note ADC should be initilized for ULP by main CPU by calling ulp_riscv_adc_init() + * before calling this. + * + * @param adc_n ADC unit. + * @param channel ADC channel number. + * + * @return Converted value, -1 if conversion failed + */ +int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/ulp_riscv/include/ulp_riscv_gpio.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h similarity index 100% rename from components/ulp/ulp_riscv/include/ulp_riscv_gpio.h rename to components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h diff --git a/components/ulp/ulp_riscv/include/ulp_riscv_register_ops.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_register_ops.h similarity index 100% rename from components/ulp/ulp_riscv/include/ulp_riscv_register_ops.h rename to components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_register_ops.h diff --git a/components/ulp/ulp_riscv/include/ulp_riscv_utils.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h similarity index 100% rename from components/ulp/ulp_riscv/include/ulp_riscv_utils.h rename to components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h diff --git a/components/ulp/ulp_riscv/start.S b/components/ulp/ulp_riscv/ulp_core/start.S similarity index 75% rename from components/ulp/ulp_riscv/start.S rename to components/ulp/ulp_riscv/ulp_core/start.S index b1f4c334a1..02eabfe2fc 100644 --- a/components/ulp/ulp_riscv/start.S +++ b/components/ulp/ulp_riscv/ulp_core/start.S @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ .section .text.vectors .global irq_vector .global reset_vector diff --git a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c new file mode 100644 index 0000000000..72e263689d --- /dev/null +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "ulp_riscv_adc.h" +#include "hal/adc_ll.h" + +int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel) +{ + uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE; + adc_oneshot_ll_clear_event(event); + adc_oneshot_ll_disable_all_unit(); + adc_oneshot_ll_enable(adc_n); + adc_oneshot_ll_set_channel(adc_n, channel); + + adc_oneshot_ll_start(adc_n); + while (adc_oneshot_ll_get_event(event) != true) { + ; + } + int32_t out_raw = adc_oneshot_ll_get_raw_result(adc_n); + if (adc_oneshot_ll_raw_check_valid(adc_n, out_raw) == false) { + return -1; + } + + //HW workaround: when enabling periph clock, this should be false + adc_oneshot_ll_disable_all_unit(); + + return out_raw; +} diff --git a/components/ulp/ulp_riscv/ulp_riscv_utils.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c similarity index 100% rename from components/ulp/ulp_riscv/ulp_riscv_utils.c rename to components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c diff --git a/components/ulp/ulp_riscv/ulp_riscv_adc.c b/components/ulp/ulp_riscv/ulp_riscv_adc.c new file mode 100644 index 0000000000..d5fce3c4a0 --- /dev/null +++ b/components/ulp/ulp_riscv/ulp_riscv_adc.c @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ulp_riscv_adc.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_log.h" +#include "driver/adc.h" +#include "hal/adc_hal_common.h" +#include "esp_private/esp_sleep_internal.h" + + +/* Will be refactored when ADC NG is merged, TODO IDF-5513 */ +extern esp_err_t adc1_rtc_mode_acquire(void); +extern uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan); + +static const char *TAG = "ulp_riscv_adc"; + +esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg) +{ + esp_err_t ret = ESP_OK; + + ESP_GOTO_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, err, TAG, "cfg == NULL"); + ESP_GOTO_ON_FALSE(cfg->adc_n == ADC_UNIT_1, ESP_ERR_INVALID_ARG, err, TAG, "Only ADC_UNIT_1 is supported for now"); + + adc1_config_channel_atten(cfg->channel, cfg->atten); + adc1_config_width(cfg->width); + + //Calibrate the ADC + uint32_t cal_val = get_calibration_offset(cfg->adc_n, cfg->channel); + adc_hal_set_calibration_param(cfg->adc_n, cal_val); + + adc1_rtc_mode_acquire(); + + esp_sleep_enable_adc_tsens_monitor(true); + +err: + return ret; +} diff --git a/examples/system/ulp_riscv/adc/CMakeLists.txt b/examples/system/ulp_riscv/adc/CMakeLists.txt new file mode 100644 index 0000000000..65ed3a2971 --- /dev/null +++ b/examples/system/ulp_riscv/adc/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ulp-riscv-adc-example) diff --git a/examples/system/ulp_riscv/adc/README.md b/examples/system/ulp_riscv/adc/README.md new file mode 100644 index 0000000000..5344d54504 --- /dev/null +++ b/examples/system/ulp_riscv/adc/README.md @@ -0,0 +1,32 @@ +| Supported Targets | ESP32-S3 | +| ----------------- | -------- | + +# ULP-RISC-V ADC Example + +This example demonstrates how to use the ULP-RISC-V coprocessor to poll the ADC in deep sleep. + +The ULP program periodically measures the input voltage on EXAMPLE_ADC_CHANNEL (by default ADC1 channel 0, GPIO1 on both ESP32-S2 and ESP32-S3). The voltage is compared to an upper threshold. If the voltage is higher than the threshold, the ULP wakes up the system. + +By default, the threshold is set to 1.75V, approximately. + +In this example, you need to connect a voltage source (e.g. a DC power supply) to the GPIO pin corresponding to the ADC channel specified in `ulp/example_config.h` (see the macros defined on the top of the header file). Feel free to modify the channel setting. + +### Hardware Required + +* A development board with a SOC which has a RISC-V ULP coprocessor (e.g., ESP32-S2 Saola) +* A USB cable for power supply and programming + +## Example output + +Below is the output from this example. + +``` +Not a ULP-RISC-V wakeup (cause = 0), initializing it! +Entering in deep sleep + +ULP-RISC-V woke up the main CPU +Threshold: high = 2000 +Value = 4095 was above threshold +Entering in deep sleep +``` + diff --git a/examples/system/ulp_riscv/adc/main/CMakeLists.txt b/examples/system/ulp_riscv/adc/main/CMakeLists.txt new file mode 100644 index 0000000000..f14a569f2e --- /dev/null +++ b/examples/system/ulp_riscv/adc/main/CMakeLists.txt @@ -0,0 +1,25 @@ +idf_component_register(SRCS "ulp_riscv_adc_example_main.c" + INCLUDE_DIRS "" + REQUIRES soc ulp esp_adc_cal) + + +# +# ULP support additions to component CMakeLists.txt. +# +# 1. The ULP app name must be unique (if multiple components use ULP). +set(ulp_app_name ulp_${COMPONENT_NAME}) +# +# 2. Specify all C and Assembly source files. +# Files should be placed into a separate directory (in this case, ulp/), +# which should not be added to COMPONENT_SRCS. +set(ulp_riscv_sources "ulp/main.c") + +# +# 3. List all the component source files which include automatically +# generated ULP export file, ${ulp_app_name}.h: +set(ulp_exp_dep_srcs "ulp_riscv_adc_example_main.c") + +# +# 4. Call function to build ULP binary and embed in project using the argument +# values above. +ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}") diff --git a/examples/system/ulp_riscv/adc/main/ulp/example_config.h b/examples/system/ulp_riscv/adc/main/ulp/example_config.h new file mode 100644 index 0000000000..8fa84cd26e --- /dev/null +++ b/examples/system/ulp_riscv/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 + +#include "hal/adc_types.h" + +#define EXAMPLE_ADC_CHANNEL ADC_CHANNEL_0 +#define EXAMPLE_ADC_UNIT ADC_UNIT_1 +#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_11 +#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12 + +/* Set high threshold, approx. 1.75V*/ +#define EXAMPLE_ADC_TRESHOLD 2000 diff --git a/examples/system/ulp_riscv/adc/main/ulp/main.c b/examples/system/ulp_riscv/adc/main/ulp/main.c new file mode 100644 index 0000000000..f049c1122a --- /dev/null +++ b/examples/system/ulp_riscv/adc/main/ulp/main.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* ULP-RISC-V example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This code runs on ULP-RISC-V coprocessor +*/ + +#include +#include "ulp_riscv_utils.h" +#include "ulp_riscv_adc_ulp_core.h" + +#include "example_config.h" + +uint32_t adc_threshold = EXAMPLE_ADC_TRESHOLD; +int32_t wakeup_result; + +int main (void) +{ + int32_t last_result = ulp_riscv_adc_read_channel(EXAMPLE_ADC_UNIT, EXAMPLE_ADC_CHANNEL); + + if (last_result > adc_threshold) { + wakeup_result = last_result; + ulp_riscv_wakeup_main_processor(); + } + + return 0; +} 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 new file mode 100644 index 0000000000..b18951b6d4 --- /dev/null +++ b/examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* ULP riscv example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "esp_sleep.h" +#include "ulp_riscv.h" +#include "ulp_riscv_adc.h" +#include "ulp_main.h" +#include "ulp/example_config.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"); + +static void init_ulp_program(void); + +void app_main(void) +{ + + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + + /* not a wakeup from ULP, load the firmware */ + if ((cause != ESP_SLEEP_WAKEUP_ULP) && (cause != ESP_SLEEP_WAKEUP_TIMER)) { + printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause); + init_ulp_program(); + } + + /* ULP Risc-V read and detected a temperature above the limit */ + if (cause == ESP_SLEEP_WAKEUP_ULP) { + printf("ULP-RISC-V woke up the main CPU\n"); + printf("Threshold: high = %d\n", ulp_adc_threshold); + printf("Value = %d was above threshold\n", ulp_wakeup_result); + } + + /* Go back to sleep, only the ULP Risc-V will run */ + printf("Entering in deep sleep\n\n"); + + /* 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); + + ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); + + esp_deep_sleep_start(); +} + +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, + }; + + ESP_ERROR_CHECK(ulp_riscv_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); + + /* The first argument is the period index, which is not used by the ULP-RISC-V timer + * The second argument is the period in microseconds, which gives a wakeup time period of: 20ms + */ + ulp_set_wakeup_period(0, 20000); + + /* Start the program */ + err = ulp_riscv_run(); + ESP_ERROR_CHECK(err); +} diff --git a/examples/system/ulp_riscv/adc/sdkconfig.defaults b/examples/system/ulp_riscv/adc/sdkconfig.defaults new file mode 100644 index 0000000000..a28f71162e --- /dev/null +++ b/examples/system/ulp_riscv/adc/sdkconfig.defaults @@ -0,0 +1,9 @@ +# Enable ULP +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RISCV=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 +# Set log level to Warning to produce clean output +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_BOOTLOADER_LOG_LEVEL=2 +CONFIG_LOG_DEFAULT_LEVEL_WARN=y +CONFIG_LOG_DEFAULT_LEVEL=2