Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@igrr
Last active January 26, 2024 09:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igrr/4b002047fc034180b8f7ca01858e1de5 to your computer and use it in GitHub Desktop.
Save igrr/4b002047fc034180b8f7ca01858e1de5 to your computer and use it in GitHub Desktop.
ESP32 ULP ISR example
#include <stdio.h>
#include <unistd.h>
#include "soc/rtc_cntl_reg.h"
#include "esp32/ulp.h"
#include "driver/rtc_cntl.h"
#include "esp_log.h"
#include "ulp_main.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
static void ulp_isr(void* arg)
{
SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
xSemaphoreGiveFromISR(done);
}
void app_main()
{
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);
ulp_set_wakeup_period(0, 100);
SemaphoreHandle_t ulp_isr_sem = xSemaphoreCreateBinary();
assert(ulp_isr_sem);
err = rtc_isr_register(&ulp_isr, (void*) ulp_isr_sem, RTC_CNTL_SAR_INT_ST_M);
ESP_ERROR_CHECK(err);
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);
err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
ESP_ERROR_CHECK(err);
int result = xSemaphoreTake(ulp_isr_sem, 1000 / portTICK_PERIOD_MS);
if (result == pdPASS) {
printf("ULP ISR triggered\n");
} else {
printf("ULP ISR timeout\n");
}
}
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
.text
.global entry
entry:
/* Do some stuff here */
/* Then wake up */
jump wake_up
wake_up:
/* Wake up the SoC, end program */
wake
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
halt
@MacWyznawca
Copy link

Hello!
Can you point out a similar example, but for ULP RISC-V with ESP-S3?
I am looking for a way to notify the active task on the main processor from ULP code (not in deep sleep).

@darthcloud
Copy link

@MacWyznawca for ULP RISC-V on ESP32-S3

you replace:

    err = rtc_isr_register(&ulp_isr, (void*) ulp_isr_sem, RTC_CNTL_SAR_INT_ST_M);
    ESP_ERROR_CHECK(err);
    REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);

with

    err = rtc_isr_register(&ulp_isr, (void*) ulp_isr_sem, RTC_CNTL_COCPU_INT_ST_M);
    ESP_ERROR_CHECK(err);
    REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_COCPU_INT_ST_M);

and use ulp_riscv_wakeup_main_processor(); function in the riscv application to trigger the interrupt.

@MacWyznawca
Copy link

Thanks @darthcloud!

@mickeyl
Copy link

mickeyl commented Jan 9, 2024

Thanks. The rtc_isr_register seems to take one additional flags argument and is a private function these days. #include "driver/rtc_cntl.h" issues a deprecation warning. Is this still ok to use?

@JellevanKraaij
Copy link

@mickeyl Did you find another solution?

@mickeyl
Copy link

mickeyl commented Jan 26, 2024

Seems to work fine these days. Espressif even added API for it in espressif/esp-idf@a67d15f#diff-62c3d8a0af115257113c79a645b4aa54908b590d97dd7473f705478b8bbd07c6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment