An Issue with high level interrupt

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

An Issue with high level interrupt

Postby opcode_x64 » Thu Apr 16, 2020 6:32 pm

Hello everybody,

for my application I need a high level interrupt which triggers on gpio level change. Actually I want to read out an external ADC which triggers the high level interrupt at the ESP32 when a sample is ready to read out by SPI bit banging. To make deployment faster, I just wrote a minimal-example code which is normally working fine on an ESP32 board. To simulate the trigger of the ADC I just use a gpio on the ESP32 itself.

GPIO35: Interrupt pin which is tied to the High Level Interrupt xt_highint5
GPIO5: Is a "trigger" simulator and its connected to GPIO35.

If I trigger the GPIO5 slowly, the High Level Interrupt is working fine, and the SampleCounter is incremented nicely. If the trigger speed is to high the ESP32 crashes with e.g. Core 1 Panic'ed (Load Prohibited)... I also tried my application on my target board with the ADC which has a SampleRate / TriggerSpeed of only 5.9kHz, which is actually not much and it also crashes..

here you can find my minimal-code:

Assembly File:

Code: Select all

#include <xtensa/coreasm.h>
#include <xtensa/corebits.h>
#include <xtensa/config/system.h>
#include "freertos/xtensa_context.h"
#include "esp_panic.h"
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/gpio_reg.h"
#include "soc/dport_reg.h"


#define aSampleCounter                        a6
#define aVar                                          a9
#define vVar                                        a10
#define temp                                       a11


.section .iram1,"ax"
 .global     xt_highint5
 .type       xt_highint5,@function
 .align      4
xt_highint5:
// clearing the interrupt status of GPIO_NUM_35
movi aVar, GPIO_STATUS1_W1TC_REG
movi temp,  (1<<3)
s32i temp, aVar, 0
memw

//incrementing the SampleCounter
movi    aSampleCounter, SampleCounter
l32i    vVar, aSampleCounter, 0
memw
addi.n  vVar, vVar, 1
s32i    vVar, aSampleCounter, 0
memw

rsr     a0, EXCSAVE_5
rfi     5
Here is the main.c file (only relevant parts!)

Code: Select all

#define NOP __asm__ __volatile__("nop")
volatile int SampleCounter = 0;
void app_main(){
  while(1){
    GPIO.out_w1tc = (1<<TRIGGER_PIN);  
    GPIO.out_w1ts = (1<< TRIGGER_PIN);
    for(i=0;i<1000000;i++){				
        NOP;
     }
    if(SampleCounter==128) break;
    vTaskDelay(1);
    }
    printf("SampleCounter: %d\n",SampleCounter);
}
For i<1000000 in the "NOP" for-loop the high level interrupt is working fine. But for example i<500000 it is crashing... The CPU is running on 240MHz.

I appreciate every help !

Best regards,
opcode_x64

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

Re: An Issue with high level interrupt

Postby opcode_x64 » Fri Apr 17, 2020 9:44 am

Hello,

I just used a12 instead of a11 register and it is working... but the issue is not solved, because I do not understand why using an another register works ?!. As far as I know, only Registers a0,a1 and a3 are restricted and used by compiler.

I am sure that solving this issue/question will help also another esp32 users working on assembly code..

I appreciate every help !

Best regards,
opcode_x64

ESP_igrr
Posts: 2076
Joined: Tue Dec 01, 2015 8:37 am

Re: An Issue with high level interrupt

Postby ESP_igrr » Fri Apr 17, 2020 11:07 am

Please note that the level 5 interrupt can happen at any time. Your interrupt handler simply overwrites the registers and doesn't save/restore their original values. If the code which was interrupted is using the same registers, then upon return from your interrupt handler, the values of the registers will no longer contain the correct values. This can lead to a crash or any other behavior.

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

Re: An Issue with high level interrupt

Postby opcode_x64 » Fri Apr 17, 2020 12:00 pm

Hello ESP_iggr,

can you please show/send me a minimal example what you told me about?

Best regards,
opcode_x64

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

Re: An Issue with high level interrupt

Postby opcode_x64 » Fri Apr 17, 2020 12:16 pm

Hey ESP_iggr,

ignore my last post.. I got you now and you are completly right about this. I will try it and will give feedback here.

Best regards,
opcode_x64

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

Re: An Issue with high level interrupt

Postby opcode_x64 » Fri Apr 17, 2020 7:04 pm

Hello ESP_iggr,

I updated my assembly code with saving/restoring the registers I am using and now it does not crashes anymore ! Stupid me....

But my application is still crashing at a special place:

In the main.c File I have declared a pointer array with 2 elements. First entry shows to an first integer array "BUFFER0" and the second entry shows to a second integer array "BUFFER1". In the High-Level-Interrupt on Core 1 I am accessing to those two pointers to fill the BUFFER0 and BUFFER1. I am using those two BUFFERS as a "flip-flop-Buffer". In main.c I am accessing to those two Buffers by selecting the desired entry in the pointer array. Now I figured out, that the program is crashing with "Load Prohibited in Core 1". In the assembly code I am using the "memw" assembler command like suggested in the Instruction Set for "volatile" variables. The integer buffers BUFFER0 BUFFER1, the pointer Array and also the Index which switches between the two pointers are declared with volatile keyword.
After restoring the registers I am using the "rsync" command before exiting the high-level-interrupt-

Is there anything else which is fundamental to be taken into account by accessing a variable from high-level interrupt on core 1 ?

Thank you !

Best regards,
opcode_x64

ESP_igrr
Posts: 2076
Joined: Tue Dec 01, 2015 8:37 am

Re: An Issue with high level interrupt

Postby ESP_igrr » Sat Apr 18, 2020 7:15 am

Hi opcode_x64,
Pretty hard to say what is wrong based on this information. Please study the panic handler output. LoadProhibited indicates an attempt to load from an invalid address. EXCVADDR register will show the address of the attempted load. The PC will show the location in the program where it is occured. Look at the rest of the registers and see which one is same/close to the EXCVADDR, and correlate this to the instruction being executed.

https://docs.espressif.com/projects/esp ... prohibited

ESP_igrr
Posts: 2076
Joined: Tue Dec 01, 2015 8:37 am

Re: An Issue with high level interrupt

Postby ESP_igrr » Sat Apr 18, 2020 7:16 am

Also you may post the new version of your interrupt handler, with the register saving/restoring code added. Maybe there is some issue there.

opcode_x64
Posts: 47
Joined: Sun Jan 13, 2019 5:39 pm

Re: An Issue with high level interrupt

Postby opcode_x64 » Sat Apr 18, 2020 10:48 am

Hello ESP_iggr,

firstly, thank you very much for your help ! You just wrote, that EXCVADDR (Exception Virtual Address) shows me the memory address where the prohibited load occurs. And the PC (Programm Counter) where in the program it is occurs. I just disassembled my code, but I cannot find the address (left column with hex addresses), neither EXCVADDR or PC... For disassembling I am using following command:

Code: Select all

xtensa-esp32-elf-objdump -h -t -D -C -d PATH_TO_FIRMWARE.ELF
As far as I understand, I used all parameters to show as much as possible in the disassembled file. Did I miss some parameter/argument of
xtensa-esp32-elf-objdump ?

Thank you !

I want to give myself a chance and want to find the error myself, because I will learn on this way more and get a deeper understanding, but if I am not able to find my mistake I will post my Interrupt Handler here =)

Best regards,
opcode_x64

ESP_igrr
Posts: 2076
Joined: Tue Dec 01, 2015 8:37 am

Re: An Issue with high level interrupt

Postby ESP_igrr » Sat Apr 18, 2020 7:19 pm

That's correct, you need to find the PC (program counter) in the disassembled code. Sometimes you may get better results by running xtensa-esp32-elf-gdb <your elf file> and then executing "disassemble /m <0xaddr>" to get the disassembly. If you can't get an exact match, it might help to open the .map file and find which function the address may be part of, and then to disassemble that function.

EXCVADDR in this case is the address which was dereferenced, e.g. it might be a NULL pointer. So no need to disassemble that one.

Who is online

Users browsing this forum: Bytespider, Google [Bot], PerplexityBot and 19 guests