Program ULP Co Processor in ESP32 using Arduino IDE

can you guide my how to install ulptool for esp32 1.0.0 for Arduino because I followed the step and run the example code still giving me errors. I also want to know that ulptool given on GitHub is only compatible with esp32 1.0.0 whereas the current version of esp32 I am using in another system is 2.0.14 so is it possible to write program for ulp co processor for esp32 version 2.0.14 using Arduino IDE 1.8

I know this is not really an answer to your question but I found C macros (for ESP32 ULP programming) quite easy to use with Arduino.

You may want to take a look at: Programming ULP FSM Coprocessor Using C Macros (Legacy) - ESP32 - — ESP-IDF Programming Guide latest documentation

Here is an example of using C macros, I was struggling with some time ago:

Sir any tool or extra library required for Arduino IDE to write ULP program for ESP32

Actually I don't know any thing how to program ULP and which library and which command I should use I just know assembly language can help in it but how to program ULP I don't know this. if you can guide and help me out through this i will be very thank full to you

Well, some/any assembly language programming skills seem neccessary. I can answer only specific questions here.

Please go through the example I have sent you and try to understand how it works (line by line) with the help of the documentation which I have also set you earlier.

Each C macro (line) correspond to 1 assembler instruction.

In Assembler you dont't have variables. You only deal with slow memory (a place where normaly C variables exist, 8 kB are available to you, both for data and the ULP code) and processor registers.

Slow memory.is alao accessible to both normal processor kernels. So it can be used to eychange information between ULP and C++ Arduino code.

What exactly are you trying to do?

i just want to count the state changing of my gpio pin from high to low as i applying pulses on it in deep sleep mode

I believe that for reading digital signals with ULP using C macros, this would be a good start:

There are some examples on digital signal reading with ULP using C macros on the Internet, most of them don't really work. This one seems to be credible.

Hello Sir, Thank you very much for sharing. Your post has benefited me a lot.I recently tried using ULP to obtain analog signals and after reaching a certain threshold, ULP woke up the main CPU. I was able to obtain analog signals (thank you again for your code), but I couldn't wake up the main CPU. Have you encountered this problem before? This is my code. If you have time, I would be appreciated to communicate with you and hope you can see my reply. Thank you.

#include <esp_sleep.h>
#include "driver/adc.h"   
#include <Arduino.h>
#include "esp32/ulp.h"
// #include "soc/rtc_io_reg.h"
// #include "soc/sens_reg.h"
#include "soc/rtc_cntl_reg.h"

        // ULP program
        const ulp_insn_t program [] = {
           
            M_LABEL (1),                // do {

                I_MOVI  (R0, 40),          // R0 = n * 1000 / 5, where n is the number of seconds to delay, 200 = 1 s
                M_LABEL (2),                // do {
                    I_DELAY (40000),            // delay (5);                           // since ULP runs at 8 MHz, 40000 cycles correspond to 5 ms (max possible delay is 65535 cycles or 8.19 ms)
                    I_SUBI  (R0, R0, 1),        // R0 --;
             M_BGE (2, 1),               // } while (R0 >= 1); ... jump to label 2 if R0 > 0

                I_ADC   (R3, 0, 7),         // R3 ≈ adc1_get_raw (ADC1_CHANNEL_6);  // GPIO 34
                
                I_ST  (R3, 0, 100),

                I_MOVR  (R0, R3),

            M_BGE (1, 3740),

            I_WAKE(),
            //M_BL    (1, 5000), 
                 
            I_END ()
        };
    size_t load_addr = 0;
    size_t size = sizeof (program)/sizeof (ulp_insn_t);


void setup () {
    Serial.begin (115200);
    
    ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
 
    memset (RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);

    // load ULP program
    ESP_ERROR_CHECK (ulp_process_macros_and_load (load_addr, program, &size));
    Serial.printf ("ULP program occupied %u 32-bit words of RTC_SLOW_MEM, make sure you put your variables after this.\n", size);

    // run ULP program 
    ESP_ERROR_CHECK (ulp_run (load_addr));

    
    Serial.printf("ESP32 is restart now! ");
    //esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, 0);
    Serial.printf("the wakeup reason is :%d\r\n", esp_sleep_get_wakeup_cause());



   

}

void loop () {
    
//    delay (210);
//    Serial.printf (" 100  %d", RTC_SLOW_MEM [100]);
//    Serial.printf ("  %4i", ~RTC_SLOW_MEM [100] & 0xFFF);
//    Serial.printf ("\n");


      delay(3000);
      Serial.println("ESP32 will sleep now!");
      delay(100);
      esp_deep_sleep_start();


}

Hello. I'm glad that the code helped you somehow. Unfortunately I don't really have much experience with ULP. Taking a look at your code it looks all right.

I'm not really sure whether you should put I_HALT () at the end beside I_END (). It is difficult to stop the ULP program from running :slight_smile:

Having some experience with different ESP32 boards, my first guess would be that I_WAKE never executes because some ESP32 boards read analog signals inverted so the value you are getting may be completely different from what you expect. Inverting the bits would help in this case.

I am so happy to receive your reply.I referred to information online and made another piece of code that can wake up the main CPU. Strangely, when I uncomment "I_ ADC (R0, 0, 6)," it cannot wake up. There seems to be some conflict here.

#include "esp32/ulp.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "esp32/ulp.h"
#include "driver/adc.h"                    
 
void init_ulp_program();
 
RTC_DATA_ATTR int bootCount = 0;
 
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;
 
  wakeup_reason = esp_sleep_get_wakeup_cause();
 
  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}
 
void setup() {
    Serial.begin(115200);
    //while( !Serial ){}
 
    Serial.println("Init");
 
    //Increment boot number and print it every reboot
    ++bootCount;
    Serial.println("Boot number: " + String(bootCount));
 
    //Print the wakeup reason for ESP32
    print_wakeup_reason();
 
    esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
    if (cause != ESP_SLEEP_WAKEUP_ULP) {
        Serial.println("Initializing ULP");
        init_ulp_program();
        /* Set ULP wake up period to 5s */
        
        ulp_set_wakeup_period(0, 5 * 1000 * 1000);
    }
 
    Serial.println("Entering deep sleep\n");
    ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
 
    esp_deep_sleep_start();
}
 
void loop(){
}
 
void init_ulp_program() {
    //adc1_ulp_enable();
    const ulp_insn_t program[] = {
//      M_LABEL (1),                // do {
//
                I_MOVI  (R0, 40),          // R0 = n * 1000 / 5, where n is the number of seconds to delay, 200 = 1 s
                M_LABEL (2),                // do {
                    I_DELAY (40000),            // delay (5);                           // since ULP runs at 8 MHz, 40000 cycles correspond to 5 ms (max possible delay is 65535 cycles or 8.19 ms)
                    I_SUBI  (R0, R0, 1),        // R0 --;
                M_BGE (2, 1),               // } while (R0 >= 1); ... jump to label 2 if R0 > 0

                //I_ADC   (R0, 0, 6),         
                
                //I_ST  (R3, 0, 100),

                //I_MOVR  (R0, R3),

            //M_BGE (1, 3740),

            
            // initiate wakeup of the SoC
            I_WAKE(),
            // stop the ULP program
            I_HALT()
    };
 
    size_t load_addr = 0;
    size_t size = sizeof(program)/sizeof(ulp_insn_t);
    ulp_process_macros_and_load(load_addr, program, &size);
    ulp_run(0);
    
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.