Page 1 of 1

Level 5 interrupt causing core0 paniced due to interrupt wdt timeout

Posted: Thu Jun 20, 2024 9:41 am
by wxd2024
Hi,
chip: esp32-U4WDH
IDF version:v4.4 with commit 8153bfe412
platform: vscode on linux
description:
Need low latency gpio interrupt, so wrote the following code in assembly to test the feasibility. ETS_GPIO_INTR_SOURCE is linked to number 31 of the interrupt matrix using intr_matrix_set(). The triggering mode is GPIO_INTR_NEGEDGE. The isr is on level5 using xt_highint5. The isr simply toggles gpio13 once.
Bluetooth has been disabled and CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL is set to 4.
problem:
The isr is triggered by desired condition and voltage toggle is observed using oscilloscope, but program crashes due to interrupt wdt timeout on core0. The followings are backtrace infos and detailed coredump is in the attachment:
  1. Guru Meditation Error: Core  0 panic'ed (Interrupt wdt timeout on CPU0).
  2.  
  3. Core  0 register dump:
  4. PC      : 0x401b207e  PS      : 0x00060e34  A0      : 0x800d2bc6  A1      : 0x3ffc6240  
  5. 0x401b207e: esp_pm_impl_waiti at /home/wxd/esp/esp-idf/components/esp_pm/pm_impl.c:839
  6.  
  7. A2      : 0x3ffbe910  A3      : 0x00060e20  A4      : 0x80090320  A5      : 0x3ffc2ec0  
  8. A6      : 0x00000003  A7      : 0x00060023  A8      : 0x80127025  A9      : 0x3ffc6230  
  9. A10     : 0x00000003  A11     : 0x00060e23  A12     : 0x00060e20  A13     : 0x3ffb0b40  
  10. A14     : 0x3ffb13d0  A15     : 0x3ffb13d0  SAR     : 0x0000001d  EXCCAUSE: 0x00000005  
  11. EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  
  12.  
  13.  
  14. Backtrace:0x401b207b:0x3ffc62400x400d2bc3:0x3ffc6260 0x4008e14c:0x3ffc6280
  15. 0x401b207b: cpu_ll_waiti at /home/wxd/esp/esp-idf/components/hal/esp32/include/hal/cpu_ll.h:183
  16.  (inlined by) esp_pm_impl_waiti at /home/wxd/esp/esp-idf/components/esp_pm/pm_impl.c:837
  17.  
  18. 0x400d2bc3: esp_vApplicationIdleHook at /home/wxd/esp/esp-idf/components/esp_system/freertos_hooks.c:63
  19.  
  20. 0x4008e14c: prvIdleTask at /home/wxd/esp/esp-idf/components/freertos/tasks.c:3974
The assembly codes are the followings:
  1. #include <xtensa/coreasm.h>
  2. #include <xtensa/corebits.h>
  3. #include <xtensa/config/system.h>
  4. #include "freertos/xtensa_context.h"
  5. #include "esp_private/panic_reason.h"
  6. #include "sdkconfig.h"
  7. #include "soc/soc.h"
  8. #include "soc/gpio_reg.h"
  9. #include "soc/dport_reg.h"
  10.  
  11. #define L5_INTR_STACK_SIZE  12
  12. #define LX_INTR_A15_OFFSET  0
  13. #define LX_INTR_A14_OFFSET  4
  14. #define LX_INTR_A13_OFFSET  8
  15.  
  16. #define STB_PIN     4
  17. #define LOAD_PIN    0 // 32 - 32
  18. #define CLK_PIN     1 // 33 - 32
  19. #define BIT_PIN     4 // 36 - 32
  20. #define BSY_PIN     13
  21. #define BUF_SIZE    20480
  22.     .data
  23. _l5_intr_stack:
  24.     .space      L5_INTR_STACK_SIZE
  25.     .section .iram1,"ax"
  26.     .global     xt_highint5
  27.     .type       xt_highint5,@function
  28.     .align      4
  29.  
  30. xt_highint5:
  31.     movi    a0, _l5_intr_stack // assuming a0 saved restored by EXCSAVE_5 at the end of this
  32.     s32i    a15, a0, LX_INTR_A15_OFFSET
  33.     s32i    a14, a0, LX_INTR_A14_OFFSET
  34.     s32i    a13, a0, LX_INTR_A13_OFFSET
  35.  
  36.     /* Clear interupt on STB_PIN which gpio4 in current hardware design */
  37.     movi    a14, GPIO_STATUS_W1TC_REG
  38.     movi    a15, (1 << STB_PIN)
  39.     s32i    a15, a14, 0
  40.     memw
  41.  
  42.     // set busy high
  43.     movi    a12, GPIO_OUT_W1TS_REG
  44.     movi    a13, GPIO_OUT_W1TC_REG
  45.     movi    a15, (1 << BSY_PIN)
  46.     s32i    a15, a12, 0
  47.     s32i    a15, a13, 0
  48.  
  49.     l32i    a15, a0, LX_INTR_A15_OFFSET
  50.     l32i    a14, a0, LX_INTR_A14_OFFSET
  51.     l32i    a13, a0, LX_INTR_A13_OFFSET
  52.  
  53.     rsr     a0, EXCSAVE_5 // restore a0
  54.     rfi     5
  55.  
  56.     .global ld_include_xt_highint5
  57. ld_include_xt_highint5:
After reading some posts on this forum, it feels like freeRtos isr that feeds the wdt is kinda blocked and interrupt wdt is never fed once the level5 isr is triggered.
Digging into the backtrace, it shows that "waiti 0" command somehow causes the problem.
Any hint on the reason and possible fixes?

Thanks & Regards
wxd

Re: Level 5 interrupt causing core0 paniced due to interrupt wdt timeout

Posted: Fri Jun 21, 2024 9:18 pm
by MicroController
Typo?

Code: Select all

movi    a12, GPIO_OUT_W1TS_REG
...
s32i    a15, a12, 0
a12 isn't saved/restored. Guess you meant to use a14 instead.

Re: Level 5 interrupt causing core0 paniced due to interrupt wdt timeout

Posted: Mon Jun 24, 2024 9:25 am
by wxd2024
Dear MicroController,

Thanks a lot for the reply, thought the topic has sunk. Using a14 to store gpio address for further toggling is indeed what should've been done and I will make the correction.
Besides this, since I am not familiar with using assembly language and the code's frame was adopted from certain posts written by some experienced guys, may I ask a question about saving and restoing the register values at the beginning of this code? e.g. saving a13, a14, a15 means I can only use these 3 registers in the following assembly routine while all other registers' value must remain unchanged, otherwise the program cannot be restored to its former state before entering isr, and to use other registers(if it is possible), I must save their values first and restore them just like the thing that is done to a13, a14, a15. Is this the basic concept isr in assembly should stick to? Really appreciate it if you could give a rough guidance.

Best regards
wxd

Re: Level 5 interrupt causing core0 paniced due to interrupt wdt timeout

Posted: Fri Jun 28, 2024 10:06 am
by MicroController
You're welcome :)

Yes, your understanding is exactly correct: When the ISR returns, all registers must contain the value they had when the ISR was entered. The original content of all registers used/'clobbered' by the ISR needs to be saved to some location in RAM and loaded back before exiting the ISR. Failure to do so can have absolutely any consequences in terms of erroneous behaviour of the application, and the problems tend to be completely unpredictable and non-deterministic because the state of the program/CPU right before entering the ISR usually is, and consequently so is the thing that will break.

You can use any and all registers you want in an ISR, as long as you save and restore them before returning. Primarily, these are the 'general purpose' a0...a15 registers, but other CPU state may need to be added to the list, like for example the 'shift-amount register' (SAR) if the ISR does a 'dynamic' shift (like "1 << some_variable" in C).