From 3d61c6d7d7f599aa195ccc59841dc418d3b6a206 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 5 Jul 2022 17:37:13 +0800 Subject: [PATCH] ulp: remove ESP32 ULP TSENS references Due to poor accuracy the ESP32 ULP TSENS instructions is not recommend for use. We keep the instruction itself to support users which are already using it, but should remove it from examples and docs to avoid encouring any new usage of it. --- components/ulp/test/ulp_fsm/test_ulp.c | 6 +- components/ulp/ulp_fsm/include/esp32/ulp.h | 2 +- .../system/ulp_instruction_set.rst | 33 +-- .../system/deep_sleep/main/Kconfig.projbuild | 11 - .../deep_sleep/main/deep_sleep_example_main.c | 195 +----------------- 5 files changed, 22 insertions(+), 225 deletions(-) diff --git a/components/ulp/test/ulp_fsm/test_ulp.c b/components/ulp/test/ulp_fsm/test_ulp.c index 31d01032b0..03a3349ebc 100644 --- a/components/ulp/test/ulp_fsm/test_ulp.c +++ b/components/ulp/test/ulp_fsm/test_ulp.c @@ -549,6 +549,7 @@ TEST_CASE("ULP FSM timer setting", "[ulp]") #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //IDF-5131 +#if !DISABLED_FOR_TARGETS(ESP32) TEST_CASE("ULP FSM can use temperature sensor (TSENS) in deep sleep", "[ulp][ignore]") { assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 260 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig"); @@ -562,9 +563,7 @@ TEST_CASE("ULP FSM can use temperature sensor (TSENS) in deep sleep", "[ulp][ign // Allow TSENS to be controlled by the ULP SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S); -#if CONFIG_IDF_TARGET_ESP32 - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, SENS_FORCE_XPD_SAR_FSM, SENS_FORCE_XPD_SAR_S); -#elif CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, SENS_FORCE_XPD_SAR_FSM, SENS_FORCE_XPD_SAR_S); SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL2_REG, SENS_TSENS_CLKGATE_EN); #elif CONFIG_IDF_TARGET_ESP32S3 @@ -616,6 +615,7 @@ TEST_CASE("ULP FSM can use temperature sensor (TSENS) in deep sleep", "[ulp][ign esp_deep_sleep_start(); UNITY_TEST_FAIL(__LINE__, "Should not get here!"); } +#endif //#if !DISABLED_FOR_TARGETS(ESP32) TEST_CASE("ULP FSM can use ADC in deep sleep", "[ulp][ignore]") { diff --git a/components/ulp/ulp_fsm/include/esp32/ulp.h b/components/ulp/ulp_fsm/include/esp32/ulp.h index 25de6a0801..3ba944cc73 100644 --- a/components/ulp/ulp_fsm/include/esp32/ulp.h +++ b/components/ulp/ulp_fsm/include/esp32/ulp.h @@ -90,7 +90,7 @@ extern "C" { #define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */ #define SUB_OPCODE_SLEEP 1 /*!< Stop executing the program and run it again after selected interval */ -#define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement */ +#define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement. Poor accuracy, not recommended for most use-cases */ #define OPCODE_HALT 11 /*!< Halt the coprocessor */ diff --git a/docs/en/api-reference/system/ulp_instruction_set.rst b/docs/en/api-reference/system/ulp_instruction_set.rst index 6e193f876c..6dbb0dc3c9 100644 --- a/docs/en/api-reference/system/ulp_instruction_set.rst +++ b/docs/en/api-reference/system/ulp_instruction_set.rst @@ -796,10 +796,10 @@ The detailed description of all instructions is presented below: Conditions *LE* and *GE* are implemented in the assembler using two **JUMPR** instructions:: // JUMPR target, threshold, LE is implemented as: - + JUMPR target, threshold, EQ JUMPR target, threshold, LT - + // JUMPR target, threshold, GE is implemented as: JUMPR target, threshold, EQ @@ -1041,27 +1041,28 @@ The detailed description of all instructions is presented below: 2: .set wait_cnt, 10 // Set a constant WAIT wait_cnt // wait for 10 cycles +.. only:: not esp32 -**TSENS** – do measurement with temperature sensor --------------------------------------------------- + **TSENS** – do measurement with temperature sensor + -------------------------------------------------- -**Syntax** - - **TSENS** *Rdst, Wait_Delay* + **Syntax** + - **TSENS** *Rdst, Wait_Delay* -**Operands** - - *Rdst* – Destination Register R[0..3], result will be stored to this register - - *Wait_Delay* – number of cycles used to perform the measurement + **Operands** + - *Rdst* – Destination Register R[0..3], result will be stored to this register + - *Wait_Delay* – number of cycles used to perform the measurement -**Cycles** - 2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction + **Cycles** + 2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction -**Description** - The instruction performs measurement using TSENS and stores the result into a general purpose register. + **Description** + The instruction performs measurement using TSENS and stores the result into a general purpose register. -**Examples**:: + **Examples**:: - 1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles, - // and store result to R1 + 1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles, + // and store result to R1 **ADC** – do measurement with ADC diff --git a/examples/system/deep_sleep/main/Kconfig.projbuild b/examples/system/deep_sleep/main/Kconfig.projbuild index 89cdcfca01..06bb60aa8b 100644 --- a/examples/system/deep_sleep/main/Kconfig.projbuild +++ b/examples/system/deep_sleep/main/Kconfig.projbuild @@ -8,17 +8,6 @@ menu "Example Configuration" This option enables wake up from deep sleep using touch pads TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32. - config EXAMPLE_ULP_TEMPERATURE_WAKEUP - bool "Enable temperature monitoring by ULP" - default y - depends on IDF_TARGET_ESP32 - help - This option enables wake up from deep sleep using ULP. - ULP program monitors the on-chip temperature sensor and - wakes up the chip when the temperature goes outside of - the window defined by the initial temperature and a threshold - around it. - config EXAMPLE_EXT0_WAKEUP bool "Enable wakeup from GPIO (ext0)" default y diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index 519d7e268e..aa9fe11346 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -22,10 +22,6 @@ #include "driver/rtc_io.h" #include "soc/rtc.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/ulp.h" -#endif - #if SOC_TOUCH_SENSOR_NUM > 0 #include "soc/sens_periph.h" #include "driver/touch_pad.h" @@ -42,53 +38,6 @@ static RTC_DATA_ATTR struct timeval sleep_enter_time; -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 - -/* - * Offset (in 32-bit words) in RTC Slow memory where the data is placed - * by the ULP coprocessor. It can be chosen to be any value greater or equal - * to ULP program size, and less than the CONFIG_ULP_COPROC_RESERVE_MEM/4 - 6, - * where 6 is the number of words used by the ULP coprocessor. - */ -#define ULP_DATA_OFFSET 36 - -_Static_assert(ULP_DATA_OFFSET < CONFIG_ULP_COPROC_RESERVE_MEM/4 - 6, - "ULP_DATA_OFFSET is set too high, or CONFIG_ULP_COPROC_RESERVE_MEM is not sufficient"); - -/** - * @brief Start ULP temperature monitoring program - * - * This function loads a program into the RTC Slow memory and starts up the ULP. - * The program monitors on-chip temperature sensor and wakes up the SoC when - * the temperature goes lower or higher than certain thresholds. - */ -static void start_ulp_temperature_monitoring(void); - -/** - * @brief Utility function which reads data written by ULP program - * - * @param offset offset from ULP_DATA_OFFSET in RTC Slow memory, in words - * @return lower 16-bit part of the word writable by the ULP - */ -static inline uint16_t ulp_data_read(size_t offset) -{ - return RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] & 0xffff; -} - -/** - * @brief Utility function which writes data to be ready by ULP program - * - * @param offset offset from ULP_DATA_OFFSET in RTC Slow memory, in words - * @param value lower 16-bit part of the word to be stored - */ -static inline void ulp_data_write(size_t offset, uint16_t value) -{ - RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] = value; -} -#endif // CONFIG_IDF_TARGET_ESP32 -#endif // CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP - #ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP #if CONFIG_IDF_TARGET_ESP32 #define TOUCH_THRESH_NO_USE 0 @@ -143,37 +92,12 @@ void app_main(void) break; } #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 - case ESP_SLEEP_WAKEUP_ULP: { - printf("Wake up from ULP\n"); - int16_t diff_high = (int16_t) ulp_data_read(3); - int16_t diff_low = (int16_t) ulp_data_read(4); - if (diff_high < 0) { - printf("High temperature alarm was triggered\n"); - } else if (diff_low < 0) { - printf("Low temperature alarm was triggered\n"); - } else { - assert(false && "temperature has stayed within limits, but got ULP wakeup\n"); - } - break; - } -#endif // CONFIG_IDF_TARGET_ESP32 -#endif // CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP + case ESP_SLEEP_WAKEUP_UNDEFINED: default: printf("Not a deep sleep reset\n"); } -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 - if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED) { - printf("ULP did %d temperature measurements in %d ms\n", ulp_data_read(1), sleep_time_ms); - printf("Initial T=%d, latest T=%d\n", ulp_data_read(0), ulp_data_read(2)); - } -#endif // CONFIG_IDF_TARGET_ESP32 -#endif // CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP - vTaskDelay(1000 / portTICK_PERIOD_MS); const int wakeup_time_sec = 20; @@ -288,13 +212,6 @@ void app_main(void) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 - printf("Enabling ULP wakeup\n"); - esp_sleep_enable_ulp_wakeup(); -#endif -#endif - #if CONFIG_IDF_TARGET_ESP32 // Isolate GPIO12 pin from external circuits. This is needed for modules // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER) @@ -305,12 +222,6 @@ void app_main(void) printf("Entering deep sleep\n"); gettimeofday(&sleep_enter_time, NULL); -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 - start_ulp_temperature_monitoring(); -#endif -#endif - esp_deep_sleep_start(); } @@ -339,107 +250,3 @@ static void calibrate_touch_pad(touch_pad_t pad) } #endif #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP - -#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP -#if CONFIG_IDF_TARGET_ESP32 -static void start_ulp_temperature_monitoring(void) -{ - /* - * This ULP program monitors the on-chip temperature sensor and wakes the chip up when - * the temperature goes outside of certain window. - * When the program runs for the first time, it saves the temperature measurement, - * it is considered initial temperature (T0). - * - * On each subsequent run, temperature measured and compared to T0. - * If the measured value is higher than T0 + max_temp_diff or lower than T0 - max_temp_diff, - * the chip is woken up from deep sleep. - */ - - /* Temperature difference threshold which causes wakeup - * With settings here (TSENS_CLK_DIV=2, 8000 cycles), - * TSENS measurement is done in units of 0.73 degrees Celsius. - * Therefore, max_temp_diff below is equivalent to ~2.2 degrees Celsius. - */ - const int16_t max_temp_diff = 3; - - // Number of measurements ULP should do per second - const uint32_t measurements_per_sec = 5; - - // Allow TSENS to be controlled by the ULP - SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 2, SENS_TSENS_CLK_DIV_S); - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); - CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); - CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); - CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE); - - // Clear the part of RTC_SLOW_MEM reserved for the ULP. Makes debugging easier. - memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM); - - // The first word of memory (at data offset) is used to store the initial temperature (T0) - // Zero it out here, then ULP will update it on the first run. - ulp_data_write(0, 0); - // The second word is used to store measurement count, zero it out as well. - ulp_data_write(1, 0); - - const ulp_insn_t program[] = { - // load data offset into R2 - I_MOVI(R2, ULP_DATA_OFFSET), - // load/increment/store measurement counter using R1 - I_LD(R1, R2, 1), - I_ADDI(R1, R1, 1), - I_ST(R1, R2, 1), - // enable temperature sensor - I_WR_REG(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_S, SENS_FORCE_XPD_SAR_S + 1, 3), - // do temperature measurement and store result in R3 - I_TSENS(R3, 8000), - // disable temperature sensor - I_WR_REG(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_S, SENS_FORCE_XPD_SAR_S + 1, 0), - // Save current measurement at offset+2 - I_ST(R3, R2, 2), - // load initial value into R0 - I_LD(R0, R2, 0), - // if threshold value >=1 (i.e. initialized), goto 1 - M_BGE(1, 1), - // otherwise, save the current value as initial (T0) - I_MOVR(R0, R3), - I_ST(R0, R2, 0), - M_LABEL(1), - // check if the temperature is greater or equal (T0 + max_temp_diff) - // uses R1 as scratch register, difference is saved at offset + 3 - I_ADDI(R1, R0, max_temp_diff - 1), - I_SUBR(R1, R1, R3), - I_ST(R1, R2, 3), - M_BXF(2), - // check if the temperature is less or equal (T0 - max_temp_diff) - // uses R1 as scratch register, difference is saved at offset + 4 - I_SUBI(R1, R0, max_temp_diff - 1), - I_SUBR(R1, R3, R1), - I_ST(R1, R2, 4), - M_BXF(2), - // temperature is within (T0 - max_temp_diff; T0 + max_temp_diff) - // stop ULP until the program timer starts it again - I_HALT(), - M_LABEL(2), - // temperature is out of bounds - // disable ULP program timer - I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0), - // initiate wakeup of the SoC - I_WAKE(), - // stop the ULP program - I_HALT() - }; - - // Load ULP program into RTC_SLOW_MEM, at offset 0 - size_t size = sizeof(program)/sizeof(ulp_insn_t); - ESP_ERROR_CHECK( ulp_process_macros_and_load(0, program, &size) ); - assert(size < ULP_DATA_OFFSET && "ULP_DATA_OFFSET needs to be greater or equal to the program size"); - - // Set ULP wakeup period - const uint32_t sleep_cycles = rtc_clk_slow_freq_get_hz() / measurements_per_sec; - REG_WRITE(SENS_ULP_CP_SLEEP_CYC0_REG, sleep_cycles); - - // Start ULP - ESP_ERROR_CHECK( ulp_run(0) ); -} -#endif // CONFIG_IDF_TARGET_ESP32 -#endif // CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP