Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

NuttyMonk
Posts: 8
Joined: Mon Jun 06, 2022 6:04 pm

Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby NuttyMonk » Tue Aug 02, 2022 6:42 pm

Hi all,

I'm running some code on an ESP32 PICO that would work fine on an Arduino or other microcontroller (i've run the same code on Atmega328p, SAMD21 and ESP32 C3) but on an ESP32 PICO i get the following error (shown at the bottom). I've done some reading and the EXCVADDR: 0x80081122 seems to point to memory where the exception occurred but that doesn't help me at all since i'm working in the Arduino IDE. The lines of code i have identified are the following...

decaySlopeFLOAT = (1023 - sustainDAC) / decayTicksFLOAT;

or

releaseSlopeFLOAT = sustainDAC / releaseTicksFLOAT;

It's just some simple maths involving floats and integers which is getting called once a second but i can't figure out why it would cause any problems. The code is run in an ISR which is called by a timer which was created by a task running the code on core 0. Here is some of the relevant code snippets.

Code: Select all

hw_timer_t * timer = NULL;

TaskHandle_t Task1;

void IRAM_ATTR onTimer() {
  getPotValues();
}

void setup()
{
  //create a task that will be executed in the vTaskFunction() function, with priority 2 and executed on core 0
  xTaskCreatePinnedToCore(
                    vTaskFunction,   /* Task function. */
                    "Task1",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    &Task1,      /* Task handle to keep track of created task */
                    0); 
}

// Create the timer then delete the task that created it
void vTaskFunction( void * pvParameters )
{
  Serial.print("vTaskFunction running on core ");
  Serial.println(xPortGetCoreID());

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
  
  // delete this task
  vTaskDelete( Task1 );
}

void getPotValues()
{
  // there is a whole bunch of code here doing analog reads and calcs on the values it gets from the reads
  // then this line will cause the Guru Meditation Error
  // i've tried reworking it in different ways but always get the same result
  decaySlopeFLOAT = (1023 - sustainDAC) / decayTicksFLOAT;
}

Code: Select all

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x40084186  PS      : 0x00050d31  A0      : 0x80081116  A1      : 0x3ffbe89c  
A2      : 0x00000040  A3      : 0x00018040  A4      : 0x000637ff  A5      : 0x3ffbe87c  
A6      : 0x00000000  A7      : 0x3ffbdbdc  A8      : 0x3ffb938c  A9      : 0x00000000  
A10     : 0x000f4240  A11     : 0x3ffbeeb4  A12     : 0x800811dc  A13     : 0x3ffbe82c  
A14     : 0x00000000  A15     : 0x3ffbe82c  SAR     : 0x00000015  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x80081122  LBEG    : 0x400860b9  LEND    : 0x400860c9  LCOUNT  : 0xffffffff  

Backtrace:0x40084183:0x3ffbe89c |<-CORRUPTED

ELF file SHA256: 0000000000000000

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:12812
load:0x40080400,len:3032
entry 0x400805e4
Does anyone have advice on how to go about figuring this out? I can't really use the ESP32 PICO if i can't run some simple code on it for some obscure reason which is impossible to figure out.

Cheers

NM

p.s. does the Stack Size of the task have anything to do with it? (10000)

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby ESP_Sprite » Wed Aug 03, 2022 1:30 am

You can't do floating point calculations in an interrupt, as the FPU is not context-switched on an interrupt. You can either make the offending variable a double (which gets handled without the FPU) or have the timer unblock a second task and do the calculations in there.

NuttyMonk
Posts: 8
Joined: Mon Jun 06, 2022 6:04 pm

Re: Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby NuttyMonk » Wed Aug 03, 2022 1:47 am

Ah, OK. Thanks Sprite.

I wasn't sure if it was something simple or not.

I'm surprised that it can't do floating point in an ISR though when other microcontrollers can. Is that just part of the xtensa architecture?

Cheers

NM

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby ESP_Sprite » Wed Aug 03, 2022 7:45 am

It's a choice we made when we wrote the context switching code. To allow the FPU to work in an interrupt, we'd have to stash/restore its state on every interrupt, and that would add a fair bit of latency to the (already somewhat slow) interrupt handler times. Given that people generally don't tend to use the FPU in interrupts anyway, we saw that as a good tradeoff.

ESP-IDF actually has an optional ability to have the FPU used in ISRs by stashing/restoring the FPU state, it's in menuconfig somewhere. For Arduino, unless you want to recompile the base libraries, that's not an option, but you can try an older solution someone else came up with there.

NuttyMonk
Posts: 8
Joined: Mon Jun 06, 2022 6:04 pm

Re: Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby NuttyMonk » Wed Aug 03, 2022 6:46 pm

Hi Sprite,

i moved the code that i was using in the ISR into the task itself and i'm just using the ISR to set a bool variable to indicate to the task that the code should be run in it. That all works fine.

Now i've got a watchdog error on core 0, where this task is running, telling me that the task watchdog got triggered because core 0 was idle.

Code: Select all

E (14150) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (14150) task_wdt:  - IDLE (CPU 0)
E (14150) task_wdt: Tasks currently running:
E (14150) task_wdt: CPU 0: Task1
E (14150) task_wdt: CPU 1: IDLE
E (14150) task_wdt: Aborting.

abort() was called at PC 0x400d9a8d on core 0

Backtrace:0x40082f11:0x3ffbe7bc |<-CORRUPTED

ELF file SHA256: 0000000000000000

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:12812
load:0x40080400,len:3032
entry 0x400805e4
Surely, if i want to run a task less frequently, that's up to me. Why is the microcontroller resetting itself because a task isn't running quickly. Can i turn this task watchdog timer off? I'm running it 4 times a second just now.

Code: Select all

// use the timer ISR to activate read of analog inputs
void IRAM_ATTR onTimer() {
  timeToReadInputs = true;
}

// Create the timer then update analog inputs when required
void vTaskFunction( void * pvParameters )
{
  Serial.print("vTaskFunction running on core ");
  Serial.println(xPortGetCoreID());

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 250000, true);
  timerAlarmEnable(timer);

  for (;;)
  {
    if (timeToReadInputs)
    {
	timeToReadInputs = false;
    	// read inputs and do some calcs here
    }
  }
}
Every time i think i'm getting somewhere with the PICO i end up back here pretty much straight away asking for help again. :(

Cheers

NM

p.s. i know i need to put something like vTaskDelay() or delay() in the for(;;) loop but eventually i want to run this task faster than 1kHz and i know that delay only goes down to 1ms. If i want to run at 10kHz i would need to enter a value of 0.1ms in the delay() function which won't work as it only accepts integers.

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: Guru Meditation Error (LoadProhibited) EXCVADDR: 0x80081122

Postby ESP_Sprite » Thu Aug 04, 2022 12:57 am

That's a misunderstanding of the WDT - it doesn't complain because your task doesn't run often enough, it complains because the idle task on that core doesn't get any CPU time as you're hogging the CPU in that infinite for() loop. The thing is that the ESP32 is running a RTOS, and up to a point it requires the tasks to 'play nice' and block every once in a while to let other tasks (like the WiFi stack, or the idle task which also does some housekeeping jobs) run as well.

The solution is to not use a bool, but to use RTOS-aware constructs that tell the RTOS not to bother running your task until some condition is true. The direct equivalent of what your code wants to do is a binary semaphore, for instance.

Who is online

Users browsing this forum: lbernstone and 41 guests