ESP32ULP wakeup question

snehapawar#
Posts: 23
Joined: Wed Jan 13, 2021 1:11 pm

ESP32ULP wakeup question

Postby snehapawar# » Wed Jan 13, 2021 1:28 pm

Hi all,
I'm using esp32-pico chip, on custom designed board. i'm trying to implement ulp with rtc-gpio pulse wakeup.
Below is my code.
I'm unable to wakeup by ulp. i have interfaced button on GPIO_36.
Same pin, with assembly code of esp-idf is working with same board. but i need to run it on my esp32 arduino framework. I port assembly code into MACRO LEGACY, but it's not waking my system from deep sleep mode.
Attachments are the files which i'm refering. This is a example code given in esp-idf "......\esp\esp-idf\examples\system\ulp"

Please i'm new for using esp32(also with ulp).

Any suggestion is appreciate.



Code: Select all

void init_ulp_program(uint32_t us) {

uint32_t _rsm_size = ( ( (uint32_t)(&RSM_END) - (uint32_t)(&(RTC_SLOW_MEM[0])) )/4 ) + 1;
// device by 4 as all RSM is 32bit
// add to be safe
_log("BURNING ULP CODE, RMS_OFFSET should be = %u", _rsm_size);


_log("init_ulp_program - before entry");
const ulp_insn_t  ulp_pulse[] = {
   
//entry
      M_LABEL(entry), // BEGIN

     /* Load io_number */
     I_MOVI(R3, io_number),
     I_LD(R3, R3, 0),        // R3 <- RTC_SLOW_MEM[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.
      */
     I_MOVR(R0, R3),
     M_BGE(read_io_high, 16), //I_BXZI(read_io_high);//EQ – jump if last ALU operation result was zero

     /* Read the value of lower 16 RTC IOs into R0 */
     //READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16),
     //I_RD_REG((((RTC_GPIO_IN_REG) - DR_REG_RTCCNTL_BASE) / 4), ((RTC_GPIO_IN_NEXT_S) + (16) - 1), (RTC_GPIO_IN_NEXT_S)),
     I_RD_REG(RTC_GPIO_IN_REG,RTC_GPIO_IN_NEXT_S,16),
     I_RSHR(R0, R0, R3),
     M_BX(read_done),//I_BXI(read_done);// GOTO M_LABEL(2)


/* Read the value of RTC IOs 16-17, into R0 */
M_LABEL(read_io_high), //read_io_high

   //READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2),
   //I_RD_REG((((RTC_GPIO_IN_REG) - DR_REG_RTCCNTL_BASE) / 4), ((RTC_GPIO_IN_NEXT_S+16) + (2) - 1), (RTC_GPIO_IN_NEXT_S+16)),
   I_RD_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2), 
   I_SUBI(R3, R3, 16),
   I_RSHR(R0, R0, R3),


M_LABEL(read_done),//read_done

     I_ANDI(R0, R0, 1),
     /* State of input changed? */
     I_MOVI(R3, next_edge),
     I_LD(R3, R3, 0),
     I_ADDR(R3, R0, R3),
     I_ANDI(R3, R3, 1),
     M_BXZ(changed),//I_BXZI(changed);//EQ – jump if last ALU operation result was zero

     /* Not changed */
     /* Reset debounce_counter to debounce_max_count */
     I_MOVI(R3,debounce_max_count),
     I_MOVI(R2,debounce_counter),
     I_LD(R3,R3,0),
     I_ST(R3,R2,0),
     /* End program */
     I_HALT(),//halt


M_LABEL(changed),//changed
    
     /* Input state changed */
     /* Has debounce_counter reached zero? */
     I_MOVI(R3,debounce_counter),
     I_LD(R2,R3,0),
     I_ANDI(R2, R2, 0),/* dummy ADD to use "jump if ALU result is zero" */
     M_BXZ(edge_detected),//I_BXZI(edge_detected);
     /* Not yet. Decrement debounce_counter */
     I_SUBI(R2,R2,1),
     I_ST(R2,R3,0),
     /* End program */
     I_HALT(),//halt


M_LABEL(edge_detected), //edge_detected


   /* Reset debounce_counter to
    debounce_max_count */
   I_MOVI(R3,debounce_max_count),
   I_MOVI(R2,debounce_counter),
   I_LD(R3,R3,0),
   I_ST(R3,R2,0),
   // Flip next_edge //
   I_MOVI(R3,next_edge),
   I_LD(R2,R3,0),
   I_ADDI(R2, R2, 1),
   I_ANDI(R2, R2, 1),
   I_ST(R2,R3,0),
   // Increment edge_count //
   I_MOVI(R3,edge_count),
   I_LD(R2,R3,0),
   I_ADDI(R2, R2, 1),
   I_ST(R2,R3,0),
   // Compare edge_count to edge_count_to_wake_up //
   I_MOVI(R3,edge_count_to_wake_up),
   I_LD(R3,R3,0),
   I_SUBR(R3,R3,R2),
   M_BXZ(wake_up),//I_BXZI(wake_up);
   // Not yet. End program //
   I_HALT(),//halt


M_LABEL(wake_up),  //wake_up
/*   
   I_MOVI(R3,edge_count_original),
   I_MOVI(R2,edge_count),
   I_LD(R3,R3,0),
   I_ST(R3,R2,0),

  // Wake up the SoC, end program //
  I_WAKE(),//wake
  I_HALT()//halt
      */
      /* Check if the system can be woken up */
      //READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP),
      I_RD_REG(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP, RTC_CNTL_RDY_FOR_WAKEUP),
      //READ_RTC_REG(RTC_CNTL_DIAG0_REG, 19, 1)
      //I_RD_REG(RTC_CNTL_DIAG0_REG, RTC_CNTL_RDY_FOR_WAKEUP_S, 1),
      I_ANDI(R0, R0, 1),
      //M_BL(wake_up, 16),
      M_BXZ(wake_up),

      /* Wake up the SoC, end program */
      I_WAKE(),//wake
      I_HALT()//halt

};

/* GPIO used for pulse counting. */
    gpio_num_t gpio_num = GPIO_NUM_36;
    int rtcio_num = rtc_io_number_get(gpio_num);
    assert(rtc_gpio_is_valid_gpio(gpio_num) && "GPIO used for pulse counting must be an RTC IO");

    /* Initialize some variables used by ULP program.
     * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
     * These variables are declared in an auto generated header file,
     * 'ulp_main.h', name of this file is defined in component.mk as ULP_APP_NAME.
     * These variables are located in RTC_SLOW_MEM and can be accessed both by the
     * ULP and the main CPUs.
     *
     * Note that the ULP reads only the lower 16 bits of these variables.
     */
    ulp_debounce_counter = 3;
    ulp_debounce_max_count = 3;
    ulp_next_edge = 0;
    ulp_edge_count_original = 0;
    ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# *//* GPIO_36 is RTC_IO 0 */
    ulp_edge_count_to_wake_up = 2;//10;

    /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */
    rtc_gpio_init(gpio_num);
    rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
    rtc_gpio_pulldown_dis(gpio_num);
    rtc_gpio_pullup_dis(gpio_num);
    rtc_gpio_hold_en(gpio_num);

    /* Disconnect GPIO12 and GPIO15 to remove current drain through
     * pullup/pulldown resistors.
     * GPIO12 may be pulled high to select flash voltage.
     */
    rtc_gpio_isolate(GPIO_NUM_12);
    rtc_gpio_isolate(GPIO_NUM_15);
    esp_deep_sleep_disable_rom_logging(); // suppress boot messages

/* Set ULP wake up period to T = 20ms.
     * Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
     */
      ulp_set_wakeup_period(0, us); 

/* Start the program */
  size_t size = sizeof(ulp_pulse) / sizeof(ulp_insn_t);
  ulp_process_macros_and_load((&ulp_entry - RTC_SLOW_MEM), ulp_pulse, &size);
  esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
  //ulp_process_macros_and_load(0, ulp_pulse, &size);
  //esp_err_t err = ulp_run(0);

  _log("ulp_run : err %d\r\n",err);
  _log("init_ulp_program - passed\r\n");

}
Attachments
wake_up.h
(783 Bytes) Downloaded 381 times
ulp_example_main.cpp
(5.03 KiB) Downloaded 365 times
pulse_cnt.h
(4.29 KiB) Downloaded 364 times

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: RTC-gpio with esp32 Macro legacy not detecting

Postby boarchuz » Wed Jan 13, 2021 2:39 pm

snehapawar# wrote:
Wed Jan 13, 2021 1:28 pm
I_RD_REG(RTC_GPIO_IN_REG,RTC_GPIO_IN_NEXT_S,16),
All of these need a look. I_RD_REG is defined as I_RD_REG(reg, low_bit, high_bit) (ie. last arg is *high* bit, not *num bits*).

I'll also give https://github.com/boarchuz/HULP a plug. There might be some useful bits in there (it will also support the next release of ESP32 Arduino).

snehapawar#
Posts: 23
Joined: Wed Jan 13, 2021 1:11 pm

Re: ESP32-S2 module custom programming

Postby snehapawar# » Wed Jan 13, 2021 5:13 pm

Hello boarchuz,
Thank you so much for ur reply.
May i ask you, that is the only "I_RD_REG", showing problem??
That is the only wrong part in this code?? Please confirm
Should i write low bit 0, and high bit"RTC_GPIO_IN_NEXT_S" ???

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: ESP32-S2 module custom programming

Postby boarchuz » Wed Jan 13, 2021 6:41 pm

It's not clear where ULP variable offsets are coming from (eg. debounce_max_count). Maybe I missed something.

For RTCIOs 0-15, you would want RTC_GPIO_IN_NEXT_S to RTC_GPIO_IN_NEXT_S+15. For the upper two you want RTC_GPIO_IN_NEXT_S+16 to RTC_GPIO_IN_NEXT_S+16+1.

RTC_CNTL_RDY_FOR_WAKEUP -> RTC_CNTL_RDY_FOR_WAKEUP_S

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S2 module custom programming

Postby ESP_Sprite » Thu Jan 14, 2021 1:50 am

snehapawar#: I'm splitting your question up to a separate topic, as it's entirely unrelated to the one you posted in. Please start a new topic in the future rather than posting in an unrelated one.

snehapawar#
Posts: 23
Joined: Wed Jan 13, 2021 1:11 pm

Re: ESP32ULP wakeup question

Postby snehapawar# » Thu Jan 14, 2021 10:57 am

Hello Boarchuz,

Thank you so much for your reply.

I did changes as per your suggestion.
but system still couldn't come out of deep sleep mode using ULP pulse by button. as you are told, esp-idf code with assembly files (pulse.s and wake.s) are perfectly working with my board.
After converting assembly files into MACRO LEGACY programming, program didn't work.

my current code after your suggestion is as below:

Is it ok if i used "I_RD_REG" instead of using "READ_RTC_FIELD" or "READ_RTC_REG" ???
I have tried to replicate by using same functions in my code to read RTC reg, but it gives me error :"error: 'REG_RD' was not declared in this scope"
And that's why i used I_RD_REG.(as you know pulse.s and wake.s files have used "READ_RTC_FIELD" or "READ_RTC_REG")

Code: Select all

//*************************************************************************************************************************************************//

void ulp_setup() {
  // microseconds to delay between halt and wake states
  init_ulp_program(20000); //20msec
  
  _log("ulp_setup - passed");
}


void init_ulp_program(uint32_t us) {

uint32_t _rsm_size = ( ( (uint32_t)(&RSM_END) - (uint32_t)(&(RTC_SLOW_MEM[0])) )/4 ) + 1;
// device by 4 as all RSM is 32bit
// add to be safe
_log("BURNING ULP CODE, RMS_OFFSET should be = %u", _rsm_size);


_log("init_ulp_program - before entry");
const ulp_insn_t  ulp_pulse[] = {
   
//entry
      M_LABEL(entry), // BEGIN

     /* Load io_number */
     I_MOVI(R3, io_number),
     I_LD(R3, R3, 0),        // R3 <- RTC_SLOW_MEM[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.
      */
     I_MOVR(R0, R3),
     M_BGE(read_io_high, 16), //I_BXZI(read_io_high);//EQ – jump if last ALU operation result was zero

     /* Read the value of lower 16 RTC IOs into R0 */
     I_RD_REG(RTC_GPIO_IN_REG,RTC_GPIO_IN_NEXT_S,RTC_GPIO_IN_NEXT_S+15),//@

     I_RSHR(R0, R0, R3),
     M_BX(read_done),//I_BXI(read_done);// GOTO M_LABEL(2)


/* Read the value of RTC IOs 16-17, into R0 */
M_LABEL(read_io_high), //read_io_high

   I_RD_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, RTC_GPIO_IN_NEXT_S + 16+1), //@
   I_SUBI(R3, R3, 16),
   I_RSHR(R0, R0, R3),


M_LABEL(read_done),//read_done

     I_ANDI(R0, R0, 1),
     /* State of input changed? */
     I_MOVI(R3, next_edge),
     I_LD(R3, R3, 0),
     I_ADDR(R3, R0, R3),
     I_ANDI(R3, R3, 1),
     M_BXZ(changed),//I_BXZI(changed);//EQ – jump if last ALU operation result was zero

     /* Not changed */
     /* Reset debounce_counter to debounce_max_count */
     I_MOVI(R3,debounce_max_count),
     I_MOVI(R2,debounce_counter),
     I_LD(R3,R3,0),
     I_ST(R3,R2,0),
     /* End program */
     I_HALT(),//halt


M_LABEL(changed),//changed
    
     /* Input state changed */
     /* Has debounce_counter reached zero? */
     I_MOVI(R3,debounce_counter),
     I_LD(R2,R3,0),
     I_ANDI(R2, R2, 0),/* dummy ADD to use "jump if ALU result is zero" */
     M_BXZ(edge_detected),//I_BXZI(edge_detected);
     /* Not yet. Decrement debounce_counter */
     I_SUBI(R2,R2,1),
     I_ST(R2,R3,0),
     /* End program */
     I_HALT(),//halt


M_LABEL(edge_detected), //edge_detected


   /* Reset debounce_counter to
    debounce_max_count */
   I_MOVI(R3,debounce_max_count),
   I_MOVI(R2,debounce_counter),
   I_LD(R3,R3,0),
   I_ST(R3,R2,0),
   // Flip next_edge //
   I_MOVI(R3,next_edge),
   I_LD(R2,R3,0),
   I_ADDI(R2, R2, 1),
   I_ANDI(R2, R2, 1),
   I_ST(R2,R3,0),
   // Increment edge_count //
   I_MOVI(R3,edge_count),
   I_LD(R2,R3,0),
   I_ADDI(R2, R2, 1),
   I_ST(R2,R3,0),
   // Compare edge_count to edge_count_to_wake_up //
   I_MOVI(R3,edge_count_to_wake_up),
   I_LD(R3,R3,0),
   I_SUBR(R3,R3,R2),
   M_BXZ(wake_up),//I_BXZI(wake_up);
   // Not yet. End program //
   I_HALT(),//halt


M_LABEL(wake_up),  //wake_up

      /* Check if the system can be woken up */
      I_RD_REG(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP_S, RTC_CNTL_RDY_FOR_WAKEUP_S),
      I_ANDI(R0, R0, 1),
      M_BXZ(wake_up),

      /* Wake up the SoC, end program */
      I_WAKE(),//wake
      I_HALT()//halt

};

/* GPIO used for pulse counting. */
    gpio_num_t gpio_num = GPIO_NUM_36;
    int rtcio_num = rtc_io_number_get(gpio_num);
    assert(rtc_gpio_is_valid_gpio(gpio_num) && "GPIO used for pulse counting must be an RTC IO");

    /* Initialize some variables used by ULP program.
     * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
     * These variables are declared in an auto generated header file,
     * 'ulp_main.h', name of this file is defined in component.mk as ULP_APP_NAME.
     * These variables are located in RTC_SLOW_MEM and can be accessed both by the
     * ULP and the main CPUs.
     *
     * Note that the ULP reads only the lower 16 bits of these variables.
     */
    ulp_debounce_counter = 3;
    ulp_debounce_max_count = 3;
    ulp_next_edge = 0;
    ulp_edge_count_original = 0;
    ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# *//* GPIO_36 is RTC_IO 0 */
    ulp_edge_count_to_wake_up = 2;//10;

    /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */
    rtc_gpio_init(gpio_num);
    rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
    rtc_gpio_pulldown_dis(gpio_num);
    rtc_gpio_pullup_dis(gpio_num);
    rtc_gpio_hold_en(gpio_num);

    /* Disconnect GPIO12 and GPIO15 to remove current drain through
     * pullup/pulldown resistors.
     * GPIO12 may be pulled high to select flash voltage.
     */
    rtc_gpio_isolate(GPIO_NUM_12);
    rtc_gpio_isolate(GPIO_NUM_15);
    esp_deep_sleep_disable_rom_logging(); // suppress boot messages

/* Set ULP wake up period to T = 20ms.
     * Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
     */
      ulp_set_wakeup_period(0, us); 

/* Start the program */
  size_t size = sizeof(ulp_pulse) / sizeof(ulp_insn_t);
  ulp_process_macros_and_load((&ulp_entry - RTC_SLOW_MEM), ulp_pulse, &size);
  esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
  //ulp_process_macros_and_load(0, ulp_pulse, &size);
  //esp_err_t err = ulp_run(0);

  _log("ulp_run : err %d\r\n",err);
  _log("init_ulp_program - passed\r\n");

}

snehapawar#
Posts: 23
Joined: Wed Jan 13, 2021 1:11 pm

Re: ESP32-S2 module custom programming

Postby snehapawar# » Thu Jan 14, 2021 11:00 am

ESP_Sprite wrote:
Thu Jan 14, 2021 1:50 am
snehapawar#: I'm splitting your question up to a separate topic, as it's entirely unrelated to the one you posted in. Please start a new topic in the future rather than posting in an unrelated one.
Hello ESP_Sprite,
Sorry for doing that, but i'm new to this forum and i couldn't find where to start a new topic for my problem.

Thank you for your pointing out, it's completely agreeable.
Will start a new topic for sure for next issue.

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: ESP32ULP wakeup question

Postby boarchuz » Thu Jan 14, 2021 1:29 pm

It's not clear where ULP variable offsets are coming from (eg. debounce_max_count). Maybe I missed something.

The xxx->ulp_xxx pattern is only used when compiling ULP assembly. You can't do it that way with legacy macros.

See here for an alternative with macros (and ulp_var_t in HULP examples for another approach):
https://github.com/espressif/esp-idf/bl ... ple_main.c
(particularly ULP_DATA_OFFSET, ulp_data_write, ulp_data_read)

Who is online

Users browsing this forum: No registered users and 95 guests