Re: ESP32-S3 ULP power consumption
Posted: Mon Mar 17, 2025 9:15 pm
Thanks, I tried it but it only has the effect that when the ULP program crashes, it consumes about 1.5 mA instead of 200 µA before. I have added reading the modified registers on the ULP and writing the values:
Main processor:
ULP:
Before writing the registers on the ULP:
RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x00000001
RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x0000000E
SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x00000002
SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x00000001
After:
RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x00000001
RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x00000000
SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x00000003
SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x00000001
So it does seem to do something, it just doesn't have the expected effect.
Any ideas?
Main processor:
Code: Select all
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "esp_sleep.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "ulp.h"
#include "ulp_main.h"
#include "esp_adc/adc_oneshot.h"
#include "ulp/example_config.h"
#include "ulp_adc.h"
#include "esp_log.h"
#include "soc/rtc_periph.h"
#include "soc/soc.h"
#include "esp32s3/rom/ets_sys.h"
#include "soc/rtc_io_reg.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");
uint32_t regFPU_bef;
uint32_t attnDS_bef;
uint32_t frcXPD_bef;
uint32_t sarCLK_bef;
uint32_t regFPU_aft;
uint32_t attnDS_aft;
uint32_t frcXPD_aft;
uint32_t sarCLK_aft;
/* This function is called once after power-on reset, to load ULP program into
* RTC memory and configure the ADC.
*/
static void init_ulp_program(void);
/* This function is called every time before going into deep sleep.
* It starts the ULP program and resets measurement counter.
*/
static void start_ulp_program(void);
void app_main(void)
{
/* If user is using USB-serial-jtag then idf monitor needs some time to
* re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection
* before we print anything. Otherwise the chip will go back to sleep again before the user
* has time to monitor any output.
*/
vTaskDelay(pdMS_TO_TICKS(1000));
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause != ESP_SLEEP_WAKEUP_ULP) {
printf("Not ULP wakeup\n");
init_ulp_program();
}
else{
printf("RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x%08" PRIX32 "\n", ulp_regFPU_bef);
printf("RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x%08" PRIX32 "\n", ulp_attnDS_bef);
printf("SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x%08" PRIX32 "\n", ulp_frcXPD_bef);
printf("SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x%08" PRIX32 "\n", ulp_sarCLK_bef);
printf("RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x%08" PRIX32 "\n", ulp_regFPU_aft);
printf("RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x%08" PRIX32 "\n", ulp_attnDS_aft);
printf("SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x%08" PRIX32 "\n", ulp_frcXPD_aft);
printf("SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x%08" PRIX32 "\n", ulp_sarCLK_aft);
}
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
void esp_sleep_enable_adc_tsens_monitor(bool enable);
esp_sleep_enable_adc_tsens_monitor(false);
esp_deep_sleep_start();
}
static void init_ulp_program(void)
{
esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
(ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
ESP_ERROR_CHECK(err);
ulp_adc_cfg_t cfg = {
.adc_n = 0,
.channel = 6,
.width = 0,
.atten = 3,
.ulp_mode = ADC_ULP_MODE_FSM,
};
ESP_ERROR_CHECK(ulp_adc_init(&cfg));
/* Set ULP wake up period to 2 s */
ulp_set_wakeup_period(0, 2000000);
#if CONFIG_IDF_TARGET_ESP32
/* Disconnect GPIO12 and GPIO15 to remove current drain through
* 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
}
static void start_ulp_program(void)
{
/* Start the program */
esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}
Code: Select all
#include "soc/rtc_cntl_reg.h"
#include "soc/soc_ulp.h"
#include "soc/sens_reg.h"
#include "soc/rtc_io_reg.h"
// Define variables, which go into .bss section (zero-initialized data)
.bss
.global regFPU_bef
regFPU_bef:
.long 0
.global attnDS_bef
attnDS_bef:
.long 0
.global frcXPD_bef
frcXPD_bef:
.long 0
.global sarCLK_bef
sarCLK_bef:
.long 0
.global regFPU_aft
regFPU_aft:
.long 0
.global attnDS_aft
attnDS_aft:
.long 0
.global frcXPD_aft
frcXPD_aft:
.long 0
.global sarCLK_aft
sarCLK_aft:
.long 0
/* Code goes into .text section */
.text
.global entry
entry:
READ_RTC_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU)
move r1, regFPU_bef
st r0, r1, 0
READ_RTC_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP)
move r1, attnDS_bef
st r0, r1, 0
READ_RTC_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR)
move r1, frcXPD_bef
st r0, r1, 0
READ_RTC_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN)
move r1, sarCLK_bef
st r0, r1, 0
WAIT 1000
WRITE_RTC_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 1)
WRITE_RTC_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, 0)
WRITE_RTC_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3)
WRITE_RTC_REG(SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN_S, 1, 1)
WAIT 1000
READ_RTC_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU)
move r1, regFPU_aft
st r0, r1, 0
READ_RTC_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP)
move r1, attnDS_aft
st r0, r1, 0
READ_RTC_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR)
move r1, frcXPD_aft
st r0, r1, 0
READ_RTC_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN)
move r1, sarCLK_aft
st r0, r1, 0
WAIT 1000
// adc r2, 0, 7
WAIT 100000
jump wake_up
exit:
halt
.global wake_up
wake_up:
/* Check if the system can be woken up */
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
and r0, r0, 1
jump exit, eq
/* Wake up the SoC, end program */
wake
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
halt
RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x00000001
RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x0000000E
SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x00000002
SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x00000001
After:
RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU: 0x00000001
RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP: 0x00000000
SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR: 0x00000003
SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN: 0x00000001
So it does seem to do something, it just doesn't have the expected effect.
Any ideas?