Category: MicroController

How to decode the exception backtrace of an ESP32

ESP32

When the execution of code on an ESP32 throws an exception, the output might look like this:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.??
??
Core  1 register dump:??
PC      : 0x420383b2  PS      : 0x00060c30  A0      : 0x820059ec  A1      : 0x3fcebd70  ??
A2      : 0x3fc97708  A3      : 0x3fcebdcb  A4      : 0x00000001  A5      : 0x0000ff00  ??
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x3fcecf5b  A9      : 0x0000723f  ??
A10     : 0x3fcecf5b  A11     : 0x00000001  A12     : 0x00000001  A13     : 0x3fcf06b4  ??
A14     : 0x00000001  A15     : 0x00000003  SAR     : 0x00000017  EXCCAUSE: 0x0000001c  ??
EXCVADDR: 0x0000728b  LBEG    : 0x40056f08  LEND    : 0x40056f12  LCOUNT  : 0x00000000  ??
??
??
Backtrace: 0x420383af:0x3fcebd70 0x420059e9:0x3fcebd90 0x42004e26:0x3fcebdb0 0x420035a2:0x3fcebe00 0x42003595:0x3fcebe20 0x4200542c:0x3fcebe40 0x42008891:0x3fcebe60??
...

The Espressif tools contain a binary called xtensa-esp32-elf-addr2line which will decode the backtrace addresses and return details about the source files, lines and function names, etc.

To run the tool, call:

/home/user/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-addr2line -fe /path/to/build/<ELFFILE>.elf <BACKTRACE>

In the command above, simply…

  • replace the path to the xtensa-esp32-elf-addr2line binary
    (in my case the binary is located in the users home directory in the folder .espressif)
  • replace the path to your elf file
    (normally, the elf file is located in the build path and generated during compilation)
  • replace the backtrace output string
    (it’s the string that is shown after Backtrace: )

 

ESP32: Stack canary watchpoint triggered (loopTask)

ESP32

Recently, I stumble upon the following error on an ESP32:

Guru Meditation Error: Core  1 panic'ed (Unhandled debug exception)
Debug exception reason: Stack canary watchpoint triggered (loopTask) 
Core 1 register dump:
PC      : 0x40083774  PS      : 0x00060b36  A0      : 0x3ffb0120  A1      : 0x3ffb0060  
A2      : 0x68efa751  A3      : 0x3ffb0938  A4      : 0x3ffb0720  A5      : 0xfb879c5c  
A6      : 0x61b36b71  A7      : 0x0006970f  A8      : 0x01709af4  A9      : 0x01709af4  
A10     : 0xfaa5dfed  A11     : 0x01a3ff3b  A12     : 0x76651dec  A13     : 0x00000001  
A14     : 0x00000000  A15     : 0x04adbe74  SAR     : 0x0000001e  EXCCAUSE: 0x00000001  
EXCVADDR: 0x00000000  LBEG    : 0x400f1cc5  LEND    : 0x400f1cc9  LCOUNT  : 0x00000000  

ELF file SHA256: 0000000000000000

The reason for this was an infinite loop that was caused by two methods that where called from each other. So the execution of the first method never ended. The code looked something like this (extremly simplified):

void loop() {
  methodOne();
}

void methodOne() {
  // ... some other code and conditions
  methodTwo();
}
void methodTwo() {
  // ... some other code and conditions
  methodOne();
}

Foto von Vishnu Mohanan auf Unsplash

 

ESP32: how to read and write the partition table of an ESP device?

ESP32

To communicate with an ESP32 the ESP-IDF (Espressif IoT Development Framework) can be used. This framework provides a collection of useful scripts to communicate with your ESP device. The framework is supported on Windows, Linux and macOS.

You can download the ESP-IDF repository and extract the contents into a folder.

Note that you need to have python 3 installed. For example by using brew install python on macOS. In addition, the esptool library is required by running pip install esptool in your terminal.

Reading the Partition Table

The partition table is located at 0x8000 (32768) on older, and on 0x9000 (36384) on newer systems. Its length is always 0xc00 (3072) bytes.

With the esptool.py, this can be read out, for example by the command

python $(IDF_PATH)/components/esptool_py/esptool/esptool.py read_flash 0x9000 0xc00 partitions.img

To create a “human” readable csv file, you can use the gen_esp32part.py tool:

python $(IDF_PATH)/components/partition_table/gen_esp32part.py partitions.img > partitions.csv

In my case, the partition table looks as follows:

Writing the Partition Table

When using an IDE like PlatformIO, the flashing of the partition table is part of the build process. For this, just add the following line to your platformio.ini:

board_build.partitions = partitions.csv

The Manual Way

First, you have to generate the partition table binaries. This can be done with idf.py:

python $(IDF_PATH)/components/partition_table/gen_esp32part.py partitions.csv partitions.bin

Then you can use esptool.py (which we already used for reading) for writing:

python $(IDF_PATH)/components/esptool_py/esptool/esptool.py write_flash -z 0x9000 partitions.bin

More details about Partition Tables, how to create custom tables, handle different partition types and the flashing precedure are listed on the official Espressif documentation.

Foto von Vishnu Mohanan auf Unsplash