From f8f93d936e0494c02e9416d3033b433e2849b1c2 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 28 Feb 2022 18:12:28 +0800 Subject: [PATCH] ulp-riscv: add support for using ADC as well as an example show-casing it. --- .../src/bootloader_random_esp32s3.c | 2 - components/driver/adc_common.c | 2 +- .../include/esp_private/esp_sleep_internal.h | 26 ++++++ components/esp_hw_support/sleep_modes.c | 4 +- .../test_apps/rtc_power_modes/README.md | 4 +- .../rtc_power_modes/main/test_rtc_power.c | 8 +- .../hal/platform_port/include/hal/assert.h | 4 +- components/ulp/CMakeLists.txt | 3 +- components/ulp/cmake/CMakeLists.txt | 7 +- components/ulp/component.mk | 3 +- .../ulp/include/esp32s3/ulp_riscv_adc.h | 32 ++++++++ components/ulp/ld/esp32s2.periperals.ld | 9 +++ components/ulp/ld/esp32s3.periperals.ld | 9 +++ components/ulp/project_include.cmake | 1 + .../ulp_riscv/ulp_riscv_adc_ulp_core.h | 32 ++++++++ components/ulp/ulp_riscv/ulp_riscv_adc.c | 20 +++++ components/ulp/ulp_riscv_adc.c | 40 ++++++++++ examples/system/ulp_riscv/adc/CMakeLists.txt | 6 ++ examples/system/ulp_riscv/adc/README.md | 32 ++++++++ .../system/ulp_riscv/adc/main/CMakeLists.txt | 25 ++++++ .../ulp_riscv/adc/main/ulp/example_config.h | 15 ++++ examples/system/ulp_riscv/adc/main/ulp/main.c | 37 +++++++++ .../adc/main/ulp_riscv_adc_example_main.c | 79 +++++++++++++++++++ .../system/ulp_riscv/adc/sdkconfig.defaults | 5 ++ .../ulp_riscv/adc/sdkconfig.defaults.esp32s3 | 4 + 25 files changed, 394 insertions(+), 15 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/esp_sleep_internal.h create mode 100644 components/ulp/include/esp32s3/ulp_riscv_adc.h create mode 100644 components/ulp/ld/esp32s2.periperals.ld create mode 100644 components/ulp/ld/esp32s3.periperals.ld create mode 100644 components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_adc_ulp_core.h create mode 100644 components/ulp/ulp_riscv/ulp_riscv_adc.c create mode 100644 components/ulp/ulp_riscv_adc.c create mode 100644 examples/system/ulp_riscv/adc/CMakeLists.txt create mode 100644 examples/system/ulp_riscv/adc/README.md create mode 100644 examples/system/ulp_riscv/adc/main/CMakeLists.txt create mode 100644 examples/system/ulp_riscv/adc/main/ulp/example_config.h create mode 100644 examples/system/ulp_riscv/adc/main/ulp/main.c create mode 100644 examples/system/ulp_riscv/adc/main/ulp_riscv_adc_example_main.c create mode 100644 examples/system/ulp_riscv/adc/sdkconfig.defaults create mode 100644 examples/system/ulp_riscv/adc/sdkconfig.defaults.esp32s3 diff --git a/components/bootloader_support/src/bootloader_random_esp32s3.c b/components/bootloader_support/src/bootloader_random_esp32s3.c index 2953db4917..5d7042c49a 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_common.c b/components/driver/adc_common.c index 3cd949aa4b..672f57feca 100644 --- a/components/driver/adc_common.c +++ b/components/driver/adc_common.c @@ -224,7 +224,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_ll_num_t adc_n, adc_channel_t chan) +uint32_t get_calibration_offset(adc_ll_num_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_ll_num_t adc_n, adc_channel_t channel, 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 9ef2c72c74..ff8a127022 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -178,7 +178,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; @@ -1364,7 +1364,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 16d9ff09c2..99f6eafb77 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 @@ -15,6 +15,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"; @@ -29,8 +30,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(); } @@ -107,8 +107,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 45e9b13874..1bfeada1f5 100644 --- a/components/hal/platform_port/include/hal/assert.h +++ b/components/hal/platform_port/include/hal/assert.h @@ -30,7 +30,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 8e66e073e3..6ab71eaf34 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -5,7 +5,8 @@ if(NOT (IDF_TARGET STREQUAL "esp32c3") AND NOT (IDF_TARGET STREQUAL "esp32h2")) "ulp_macro.c") if(CONFIG_ESP32S2_ULP_COPROC_RISCV OR CONFIG_ESP32S3_ULP_COPROC_RISCV) - list(APPEND srcs "ulp_riscv.c") + list(APPEND srcs "ulp_riscv.c" + "ulp_riscv_adc.c") endif() idf_component_register(SRCS ${srcs} diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 674a20c039..9a5cd051f3 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -68,11 +68,14 @@ add_custom_target(${ULP_APP_NAME}_ld_script DEPENDS ${ULP_LD_SCRIPT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +# To avoid warning "Manually-specified variables were not used by the project" +set(bypassWarning "${IDF_TARGET}") 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_riscv_utils.c" + "${IDF_PATH}/components/ulp/ulp_riscv/ulp_riscv_adc.c") #dummy loop to force pre-processed linker file generation: foreach(ulp_s_source ${ULP_S_SOURCES}) @@ -96,6 +99,8 @@ if(ULP_COCPU_IS_RISCV) 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_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/component.mk b/components/ulp/component.mk index ef4db2af12..f68d25bf8f 100644 --- a/components/ulp/component.mk +++ b/components/ulp/component.mk @@ -1 +1,2 @@ -COMPONENT_OBJEXCLUDE := ulp_riscv.o +COMPONENT_OBJEXCLUDE := ulp_riscv.o \ + ulp_riscv_adc.o diff --git a/components/ulp/include/esp32s3/ulp_riscv_adc.h b/components/ulp/include/esp32s3/ulp_riscv_adc.h new file mode 100644 index 0000000000..27f53efbfa --- /dev/null +++ b/components/ulp/include/esp32s3/ulp_riscv_adc.h @@ -0,0 +1,32 @@ +/* + * 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_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 ADC1 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); + +#ifdef __cplusplus +} +#endif 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 cac5a950d8..ac6e3ef1af 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} -DIDF_TARGET=${idf_target} -DSDKCONFIG_HEADER=${SDKCONFIG_HEADER} diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_adc_ulp_core.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_adc_ulp_core.h new file mode 100644 index 0000000000..9c27834c12 --- /dev/null +++ b/components/ulp/ulp_riscv/include/ulp_riscv/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/ulp_riscv_adc.c b/components/ulp/ulp_riscv/ulp_riscv_adc.c new file mode 100644 index 0000000000..236c88b0cc --- /dev/null +++ b/components/ulp/ulp_riscv/ulp_riscv_adc.c @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "ulp_riscv/ulp_riscv_adc_ulp_core.h" +#include "hal/adc_ll.h" + +int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel) +{ + adc_ll_rtc_enable_channel(adc_n, channel); + + adc_ll_rtc_start_convert(adc_n, channel); + while (adc_ll_rtc_convert_is_done(adc_n) != true) { + ; + } + int32_t out_raw = adc_ll_rtc_get_convert_value(adc_n); + + return out_raw; +} diff --git a/components/ulp/ulp_riscv_adc.c b/components/ulp/ulp_riscv_adc.c new file mode 100644 index 0000000000..99825d7e22 --- /dev/null +++ b/components/ulp/ulp_riscv_adc.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3/ulp_riscv_adc.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_log.h" +#include "driver/adc.h" +#include "hal/adc_hal.h" +#include "esp_private/esp_sleep_internal.h" + + +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"); + + adc1_config_channel_atten(cfg->channel, cfg->atten); + adc1_config_width(cfg->width); + + //Calibrate the ADC + uint32_t cal_val = get_calibration_offset(ADC_UNIT_1, cfg->channel); + adc_hal_set_calibration_param(ADC_NUM_1, 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..ad6aca3f33 --- /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.5) + +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..9ce79500df --- /dev/null +++ b/examples/system/ulp_riscv/adc/main/ulp/example_config.h @@ -0,0 +1,15 @@ +/* + * 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_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..f009b10702 --- /dev/null +++ b/examples/system/ulp_riscv/adc/main/ulp/main.c @@ -0,0 +1,37 @@ +/* + * 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/ulp_riscv.h" +#include "ulp_riscv/ulp_riscv_utils.h" +#include "ulp_riscv/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(ADC_NUM_1, 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..61514365bc --- /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 "esp32s3/ulp.h" +#include "esp32s3/ulp_riscv.h" +#include "esp32s3/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 = { + .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..302c87aa9a --- /dev/null +++ b/examples/system/ulp_riscv/adc/sdkconfig.defaults @@ -0,0 +1,5 @@ +# 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 diff --git a/examples/system/ulp_riscv/adc/sdkconfig.defaults.esp32s3 b/examples/system/ulp_riscv/adc/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000000..165e30dd58 --- /dev/null +++ b/examples/system/ulp_riscv/adc/sdkconfig.defaults.esp32s3 @@ -0,0 +1,4 @@ +# Enable ULP +CONFIG_ESP32S3_ULP_COPROC_ENABLED=y +CONFIG_ESP32S3_ULP_COPROC_RISCV=y +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096