Sure, this is the code for RISCV.
Main Processor:
Code: Select all
#include <stdio.h>
#include <inttypes.h>
#include "esp_sleep.h"
#include "ulp_riscv.h"
#include "ulp_adc.h"
#include "ulp_main.h"
#include "ulp/example_config.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");
static void init_ulp_program(void);
void app_main(void)
{
vTaskDelay(pdMS_TO_TICKS(1000));
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();
}
/* 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_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,
};
// Commenting out this line will drop the current consumption to ~9 µA
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);
/* 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: 2 s
*/
ulp_set_wakeup_period(0, 2000000);
/* Start the program */
err = ulp_riscv_run();
ESP_ERROR_CHECK(err);
}
ULP:
Code: Select all
#include <stdint.h>
#include "ulp_riscv_utils.h"
#include "ulp_riscv_adc_ulp_core.h"
int main (void)
{
SENS.sar_peri_clk_gate_conf.saradc_clk_en = 0;
SENS.sar_power_xpd_sar.force_xpd_sar = 0x2;
return 0;
}
This is the code for FSM.
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 "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");
/* 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();
}
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();
}
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 = EXAMPLE_ADC_UNIT,
.channel = EXAMPLE_ADC_CHANNEL,
.width = EXAMPLE_ADC_WIDTH,
.atten = EXAMPLE_ADC_ATTEN,
.ulp_mode = ADC_ULP_MODE_FSM,
};
// Commenting out this line will drop the current consumption to ~9 µA
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);
}
ULP:
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"
/* Code goes into .text section */
.text
.global entry
entry:
// Disable the SAR ADC
WRITE_RTC_REG(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_SARADC_CLK_EN_S, 1, 0)
WRITE_RTC_REG(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN_S, 1, 0)
WRITE_RTC_REG(SENS_SAR_POWER_XPD_SAR_REG, SENS_SARCLK_EN_S, 1, 0)
WRITE_RTC_REG(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR_S, 2, 2)
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
This is the schematic of the board I'm using:
https://www.wemos.cc/en/latest/_static/ ... v1.0.0.pdf
I have removed the RGB-LED and I'm powering the 3.3 V directly, bypassing the regulator.
Since the current drops to about 9 µA when just the single line is commented where the ADC is enabled, I am fairly certain that the problem is not on the board. The differences between the chips are coming definitely from the chips themselves. I know that because I swapped chips between two boards (one at ~20 µA, one at ~50 µA) and the consumption stayed with the chip.