Inconsistent ULP ISR while using WiFi

ns_esp
Posts: 6
Joined: Sun Jun 13, 2021 2:36 am

Inconsistent ULP ISR while using WiFi

Postby ns_esp » Sun Oct 10, 2021 6:01 am

I am having an issue wherein the main processor occasionally does not wakeup when a command is sent by ULP coprocessor while powersave mode and aspects of the WiFi protocol are active.I get the sense that the ULP ISR has a lower priority than some WiFi or is unable to perform its task on a different core.
In the image below is an oscilloscope capture. The yellow trace indicates the ULP code's wakeup (a pin is toggled high and then low for debugging purposes), and the purple trace is the ISR triggering and sending a pin high and then low. The red arrows are pointing locations where the ISR failed to respond but the ULP has issues a wakeup command:
annotated_pulses.png
annotated_pulses.png (1.21 MiB) Viewed 2032 times
Main core:

Code: Select all

/*** includes ***/
#include "driver/rtc_io.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_periph.h"
#include "soc/soc.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
#include "driver/rtc_cntl.h"
#include "esp_sleep.h"
#include "nvs.h"
#include <rom/ets_sys.h> // needed for us delay
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "esp_pm.h"
#include <stdio.h>
#include "driver/gpio.h"
#include "sdkconfig.h"
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include "driver/uart.h"


static void init_ulp_program()
{    
    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);
    
    // Setup ULP pins
    // yellow trace (ULP wakeup)
    gpio_num_t gpio_TEST = 13; // test pin
    rtc_gpio_init(gpio_TEST);
    rtc_gpio_set_direction(gpio_TEST, RTC_GPIO_MODE_OUTPUT_ONLY);
    gpio_set_level(gpio_TEST,0);
    rtc_gpio_set_level(gpio_TEST, 0);

    // purple trace (ISR response)
    gpio_pad_select_gpio(15);
    gpio_set_direction(15, GPIO_MODE_OUTPUT);
    gpio_set_level(15,0);
    
    esp_deep_sleep_disable_rom_logging(); // suppress boot messages

    esp_sleep_enable_ulp_wakeup(); // this is needed to permit the ISR to work when powersave mode is active.
    
    ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
}

static void IRAM_ATTR ulp_isr_handler(void *args)
{
    gpio_set_level(15, 1); // turn on pin 15 so the oscillosocpe can capture it
    // this delay is necessary without it the isr handler (interrupt) ends too fast and the ulp processor hasn't cleared the wait command in time thereby retriggering the isr
    ets_delay_us(50);
    gpio_set_level(15, 0); // turn on pin 15 so the oscillosocpe can capture it

}

static void ulp_isr_install()
{
    ESP_ERROR_CHECK( rtc_isr_register(&ulp_isr_handler, NULL, RTC_CNTL_SAR_INT_ST_M) );
    REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);
}


void app_main()
{
    nvs_flash_init();      //initialize nvs flash

    printf("start\n");

    ulp_isr_install();
    init_ulp_program();
    
    tcpip_adapter_init();

    esp_pm_config_esp32_t pm = 
    {
        .max_freq_mhz=80,
        .min_freq_mhz=10,
        .light_sleep_enable=true
    };
    esp_pm_configure(&pm);      //Initialize powersave mode, set frequency range, enable sleep 
    

}
ULP code:

Code: Select all

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

 /* Pin Macros */
.macro TEST_P_HI                  // pin set high
    WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S+14,1,1)
.endm

.macro TEST_P_LO                  // pin set low
    WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S+14,1,0)
.endm

    /* Code goes into .text section */
    .text
    .global entry
entry:

    STAGE_RST

WAIT_LOOP:
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    WAIT 500
    STAGE_INC 1
    JUMPS WAKE_CODE, 250, GE
    JUMP WAIT_LOOP
WAKE_CODE:
    TEST_P_HI // set pin hi (yellow trace on oscilloscope)
    // this should trigger the ISR
    wake
    //WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
    // wait commands to create a visible pulse
    WAIT 500 // 0
    WAIT 500 // 1
    WAIT 500 // 2
    WAIT 500 // 3
    WAIT 500 // 4
    WAIT 500 // 5
    WAIT 500 // 6
    WAIT 500 // 7
    WAIT 500 // 8
    WAIT 500 // 9
    WAIT 500 // 10
    WAIT 500 // 11
    WAIT 500 // 12
    WAIT 500 // 13
    WAIT 500 // 14
    WAIT 500 // 15
    TEST_P_LO // set pin low (yellow trace on oscilloscope)
    jump entry
I find that the problem occurs when both tcpip_adapter_init() and esp_pm_configure(&pm) are present. The issue is exacerbated by additional WiFi functionality being present. I would need the ULP ISR to trigger on every WAKE command. Has anyone encountered this or knows a way around this problem?

Thank you.


ns_esp
Posts: 6
Joined: Sun Jun 13, 2021 2:36 am

Re: Inconsistent ULP ISR while using WiFi

Postby ns_esp » Fri Oct 15, 2021 7:40 am

Thank you! This resolved it!

Who is online

Users browsing this forum: Google [Bot] and 150 guests