Need help overriding "_ulp_riscv_interrupt_handler"

derock
Posts: 1
Joined: Fri Apr 25, 2025 9:52 pm

Need help overriding "_ulp_riscv_interrupt_handler"

Postby derock » Fri Apr 25, 2025 9:57 pm

I would like to know the cause of a ULP wakeup. I read on the datasheet for the S3 that the wakeup reason is stored in the q1 register. Looking at the ESP-IDF source, it registers a weak function `_ulp_riscv_interrupt_handler` that gets called with the wakeup reason as it's first parameter:

Code: Select all

/* This is the global interrupt handler for ULP RISC-V.
 * It is called from ulp_riscv_vectors.S
 */
void __attribute__((weak)) _ulp_riscv_interrupt_handler(uint32_t q1)
{
    /* Call respective interrupt handlers based on the interrupt status in q1 */

    /* Internal Interrupts */
    if (q1 & ULP_RISCV_INTERNAL_INTERRUPT) {
        // TODO
    }

    /* External/Peripheral interrupts */
    if (q1 & ULP_RISCV_PERIPHERAL_INTERRUPT) {
        /* RTC Peripheral interrupts */
        uint32_t cocpu_int_st = READ_PERI_REG(SENS_SAR_COCPU_INT_ST_REG);
        if (cocpu_int_st) {
            ulp_riscv_handle_rtc_periph_intr(cocpu_int_st);
        }

        /* RTC IO interrupts */
        uint32_t rtcio_int_st = REG_GET_FIELD(RTC_GPIO_STATUS_REG, RTC_GPIO_STATUS_INT);
        if (rtcio_int_st) {
            ulp_riscv_handle_rtc_io_intr(rtcio_int_st);
        }

        /* TODO: RTC I2C interrupt */
    }
}
From: https://github.com/espressif/esp-idf/bl ... upt.c#L110

My goal is to differentiate between wakeups due to timer and wakeups due to RTC GPIO changes.

In my ULP main.c file, I've attempted to override the function:

Code: Select all

/**
 * This function overrides the weak default implementation.
 * It is called by the assembly vector code (ulp_riscv_vectors.S)
 * https://github.com/espressif/esp-idf/blob/465b159cd8771ffab6be70c7675ecf6705b62649/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c#L16
 *
 * Default interrupt handler has "// TODO" for timer interrupts which we need.
 */
void _ulp_riscv_interrupt_handler(uint32_t q1) {
  ulp_error_flags++; // This is just a random variable I have that I can read from main CPU
}
It seems, though, that my overriden `_ulp_riscv_interrupt_handler` never gets called. If I move my `ulp_error_flags++;` to the `void main()` of the ULP main.c, then I can read from the main CPU that the number increments as the timer fires and as GPIO changes.

What do I have to do to override the original `_ulp_riscv_interrupt_handler`? I've done a fullclean and rebuild.

Who is online

Users browsing this forum: Qwantbot and 2 guests