Page 1 of 1

Deep Sleep ULP wakeup after I_END()

Posted: Mon Sep 16, 2019 8:31 pm
by bonadio
Hello

I am trying to wakeup from Deep Sleep using ULP after calling I_END, reading the docs in https://docs.espressif.com/projects/esp ... acros.html
I understood that if I call I_END the ULP timer would stop and it would start again the next time I call ulp_run() "ULP program will not be restarted anymore until ulp_run function is called"

I built a very simple program to try it but it does not seems to work. What am I missing?

Code: Select all

#include "esp32/ulp.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"

void setup() {
    Serial.begin(115200);
    while( !Serial ){}

    Serial.println("Init");
    esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
    if (cause != ESP_SLEEP_WAKEUP_ULP) {
        printf("Not ULP wakeup, initializing ULP\n");
        init_ulp_program();
    } else {
        printf("ULP wakeup, saving pulse count\n");
        update_pulse_count();
    }

    printf("Entering deep sleep\n\n");
    ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
    esp_deep_sleep_start();
}

void loop(){
}

void init_ulp_program() {
    const ulp_insn_t program[] = {
                M_LABEL(3),        // LABEL 3
                I_MOVI(R0, 0),
                I_RD_REG(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP,RTC_CNTL_RDY_FOR_WAKEUP ),
                M_BGE(4, 1),
                M_BX(3),
                M_LABEL(4),
                I_WAKE(),          // Wake up ESP32
                I_END(),           // If I comment this line the program restarts normally
                I_HALT()           // Halt the coprocessor
    };

    size_t load_addr = 0;
    size_t size = sizeof(program)/sizeof(ulp_insn_t);
    ulp_process_macros_and_load(load_addr, program, &size);

    /* Set ULP wake up period to 2s */
    ulp_set_wakeup_period(0, 2000000);
    
    // ULP can wake ESP
    esp_sleep_enable_ulp_wakeup();

    ulp_run(0);
}

void update_pulse_count() {
   // I understood that calling ulp_run() here would re-enable the timer and the program would wake
    ulp_run(0);
}



Thanks

Re: Deep Sleep ULP wakeup after I_END()

Posted: Tue Sep 17, 2019 12:52 am
by boarchuz
The ULP program begins when ulp_run is called, and RTC_CNTL_RDY_FOR_WAKEUP can be 1 even when the SoC is active (maybe you're expecting it to only be set when in deep sleep?).
So what's happening is that the ULP is running, checking that bit, and then generating the interrupt *before* the SoC has entered deep sleep (and/or registered the ULP interrupt). It ends, and no further interrupt is generated so there is never a wakeup from deep sleep.

Re: Deep Sleep ULP wakeup after I_END()

Posted: Wed Sep 18, 2019 2:37 am
by bonadio
Hello @boarchuz

Thanks for the answer, makes sense.

I am trying to avoid having the ULP coprocessor running while in active mode. I am trying to minimize power consumption, I already changed to 80Mhz, disabled 1 processor and made some changes to BT, now I am at 35mA current consumption with BT in active mode.

Do you know any alternative to be able to stop the ULP while in active mode and enable it for deep sleep?

Thanks

Re: Deep Sleep ULP wakeup after I_END()

Posted: Wed Sep 18, 2019 3:54 am
by ESP_igrr
bonadio: What you intend to do should work, however i think the syntax of I_RD_REG is not correct.

RTC_CNTL_RDY_FOR_WAKEUP is defined as a bit mask, not as a bit number:

#define RTC_CNTL_RDY_FOR_WAKEUP (BIT(19))

While I_RD_REG macro expects to see bit numbers. Can you please try passing RTC_CNTL_RDY_FOR_WAKEUP_S (which is equal to 19) instead?

Re: Deep Sleep ULP wakeup after I_END()

Posted: Wed Sep 18, 2019 2:15 pm
by bonadio
Hello ESP_igrr

Thanks very much, that really worked.

:D :D