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: 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
}
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
Thank you.