ULP never becomes ready to wake the CPU

themadsens
Posts: 17
Joined: Wed Sep 05, 2018 6:49 pm

ULP never becomes ready to wake the CPU

Postby themadsens » Sun Apr 07, 2019 5:53 pm

I must be doing something wrong here! But what is it?!

I have an ULP program to wake the CPU when an RTC GPIO has been high for a full second (5 iterations of 200ms).

However, as shown in the IDF examples, there must be a loop awaiting the RTC_CNTL_RDY_FOR_WAKEUP flag before we can call wake.
It seems that this loop keeps spinning forever for some reason. What could be the cause?

In the code below the 'num_high' will reach 'num_thres' and then the code is stuck in the 'loop_rdy' loop. This is seen as 'num_high' never incremented further and 'helloworld is set to 0xBEEF, but never 0xACED as one would expect.

Any help apprecieted!

/Flemming

Code: Select all

#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"

        /* ------ Define variables, which go into .bss section (zero-initialized data) ------ */
        .bss

        /* Number of logical '1's read so far. Wake up when we pass num_thres */
        .global num_high
num_high:
        .long 0

        /* Number of successive highs before wake.  Set by main program. */
        .global num_thres
num_thres:
        .long 0

        /* RTC IO number used to sample the input signal.  Set by main program. */
        .global io_psdown
io_psdown:
        .long 0

        .global helloworld
helloworld:
        .long 0

        /* ------ Code goes into .text section ------ */
        .text
        .global entry
entry:
        /* Say hello */
        move r3, helloworld
        move r2, 0xC0DE;
        st r2, r3, 0                 // helloworld = 0xC0DE;

        /* Load io_number */         // R0:1 = gpio_rtc[io_number]
        move r3, io_psdown
        ld r3, r3, 0

        /* Lower 16 IOs and higher need to be handled separately,
         * because r0-r3 registers are 16 bit wide.
         * Check which IO this is.
         */
        move r0, r3
        jumpr read_io_high, 16, ge

        /* Read the value of lower 16 RTC IOs into R0 */
        READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16)
        rsh r0, r0, r3
        jump read_done

        /* Read the value of RTC IOs 16-17, into R0 */
read_io_high:
        READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2)
        sub r3, r3, 16
        rsh r0, r0, r3

read_done:
        and r0, r0, 1                // if (R0:1) goto is_low else:
        jump is_low, eq
        /* Load counter */
        move r3, num_high            // num_high = num_high + 1 (part 1)
        ld r3, r3, 0
        add r0, r3, 1
        /* Save counter */
        move r3, num_high            // num_high = num_high + 1 (part 2)
        st r0, r3, 0
        /* Load threshold */
        move r3, num_thres
        ld r3, r3, 0
        sub r0, r3, r0
        jump wake_up, ov             // if (R0 > num_thres) goto wake_up else:

        /* End program */
        halt

is_low:
        /* Reset counter */
        move r0, 0                   // num_high = 0
        move r3, num_high
        st r0, r3, 0
exit:
        /* End program */
        halt

wake_up:
        move r3, helloworld          // helloworld = 0xBEEF
        move r2, 0xBEEF;
        st r2, r3, 0

        /* Loop until the system can be woken up */
loop_rdy:
        READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
        and r0, r0, 1
        jump loop_rdy, eq
        //jump exit, eq

        move r3, helloworld          // helloworld = 0xACED
        move r2, 0xACED;
        st r2, r3, 0

        /* Wake up the SoC, end program */
        wake
        WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
        halt


ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: ULP never becomes ready to wake the CPU

Postby ESP_igrr » Sun Apr 07, 2019 10:16 pm

Is your application code entering deep sleep or light sleep?

If yes, which wakeup methods do you have enabled?

themadsens
Posts: 17
Joined: Wed Sep 05, 2018 6:49 pm

Re: ULP never becomes ready to wake the CPU

Postby themadsens » Mon Apr 08, 2019 9:43 am

It is entering deepsleep.

The debugging is done by just starting the ULP while the power is on. Ie. not entering deepsleep, but just watching the ulp_* variables

I start the code like below at boot time in order to debug the ULP

Code: Select all

    ulp_set_wakeup_period(0, 200000); // Set ULP wake up period to 200ms
    ESP_ERROR_CHECK(ulp_load_binary(0, ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t)));
    ulp_num_thres = 100;  //5;               // Wakeup when PS_DOWN was high for 1 sec
    ulp_num_high  = 42; // Reset counter
    ulp_io_psdown = esp32_gpioMux[LG_GPIO_PSDOWN].rtc; // Evaluates to: 1
    log_info("ULP INIT: TH:%d,%p NH:%d,%p IO:%d,%p HL:%d,%p", ulp_num_thres,&ulp_num_thres, ulp_num_high,&ulp_num_high, ulp_io_psdown,&ulp_io_psdown, ulp_helloworld,&ulp_helloworld);

    ulp_run(&ulp_entry - RTC_SLOW_MEM); // For testing
 
And here is the code for when the power-down actually happens. The code that initiates the shutdown monitors the GPIO via ADC readings in order to react as early as possible (We might port this to another ULP program at a later stage)

Code: Select all

    ulp_num_high  = 0; // Reset counter
    ulp_num_thres = 5; // Wakeup when PS_DOWN was high for 1 sec
    pinMode(LG_GPIO_PSDOWN, INPUT); // ULP reads it as a GPIO (Not an ADC) (pinMode() is an arduino API)
    //delay(5);
    esp_sleep_enable_ulp_wakeup();
    ulp_run(&ulp_entry - RTC_SLOW_MEM);
    log_warn("ULP: NH:%x TH:%x", ulp_num_high, ulp_num_thres);
    esp_deep_sleep_start();

ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: ULP never becomes ready to wake the CPU

Postby ESP_igrr » Mon Apr 08, 2019 9:55 am

But the problem is, if the power is on, then the system never enters sleep state, where it can be woken up. So RTC_CNTL_RDY_FOR_WAKEUP never gets set.

For debugging, i would suggest entering deep sleep and enabling timer wakeup. After wakeup, you can check the wakeup cause. If the wakeup was caused by the timer, you can treat this as "ULP wakeup timeout" case and print out the values of debugging variables.

themadsens
Posts: 17
Joined: Wed Sep 05, 2018 6:49 pm

Re: ULP never becomes ready to wake the CPU

Postby themadsens » Mon Apr 08, 2019 10:48 am

Ahh. OK, and thanks! :-)

Will it be OK to call 'wake' without waiting for RTC_CNTL_RDY_FOR_WAKEUP when power is on?
This way I can use the ULP for watching the voltage level on the GPIO and generate an RTC interrupt without polling from the main CPU.

/Flemming

themadsens
Posts: 17
Joined: Wed Sep 05, 2018 6:49 pm

Re: ULP never becomes ready to wake the CPU

Postby themadsens » Mon Apr 08, 2019 10:59 am

Also: I think the documentation for 'wake' is a bit unclear on this: It specifically says you have to wait for RTC_CNTL_RDY_FOR_WAKEUP, otherwise the instruction will have no effect .. I guess some clarification in the docs regarding this issue would be nice :-)

ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: ULP never becomes ready to wake the CPU

Postby ESP_igrr » Mon Apr 08, 2019 2:02 pm

If the main CPU is not in sleep mode, it is okay to execute 'wake' instruction to generate an RTC interrupt, yes. Will update the documentation to mention this.

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 225 guests