Skip to content

Read the console and backtraces

Goal: Read the board’s log and turn a backtrace from your own build into source lines.

You need: Start here done, a CrossPad on USB, the build that is on the board, ESP-IDF loaded as in 2. Build the firmware, and the crosspad-hil venv from 1. Set up the toolchain active. Used the one-line installer? crosspad-hil already works, and you use crosspad-idf in place of idf.py.

Run every command from the project root (~/CrossPad, Windows C:\CrossPad\firmware).

  1. Open the serial console

    The ESP32-S3 logs on the STM32 bridge port (0483:5740, 115200 baud), shown as /dev/ttyACM… on Linux and COMx on Windows; the first command below lists the ports so you can find it. Opening the port resets the ESP, so open it before you reproduce the problem.

    Terminal window
    python3 -m serial.tools.list_ports -v
    idf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 -p <port> monitor

    This is for a v2 board. A v1 board has no USB console: wire a USB-UART adapter as in the v1 note of Flash or recover over UART.

    You should see: the board restart and its log scroll by, starting with a line that begins ESP-ROM:esp32s3. Ctrl+] exits.

    If not: nothing prints: no boot log on the console. The port is busy: serial port is busy. Permission denied: permission denied on the serial port. idf.py is not found: idf.py command not found.

  2. Confirm a healthy boot

    A good boot prints these lines in this order. Each has an I (…) <tag>: prefix in the log.

    You should see:

    Platform fully initialized
    STM32 ident: ...
    Crosspad initialization complete
    All systems operational - Crosspad ready
    App registry initialized
    LoadMainScreen completed successfully

    All systems operational - Crosspad ready means the firmware is up; the last two lines follow a few seconds later, once the launcher is on the screen.

    If not: the log stops before LoadMainScreen completed successfully: go on to step 3. The log restarts again and again: board boot-loops after a flash.

  3. Find the error lines

    When your build stops on an error, ESP-IDF prints one of these lines (it calls this a panic). It also prints a Backtrace: line of 0x…:0x… address pairs, which steps 4 and 5 turn into source lines.

    Guru Meditation
    abort() was called
    Task watchdog
    ESP-ROM:esp32s3 (repeating = boot loop)

    You should see: one of these lines, usually with a Backtrace: line soon after it.

    If not: a boot loop that never reaches the launcher: board boot-loops after a flash.

  4. Capture an error report

    diagnose finds the error in the log, decodes the backtrace with your ELF, and adds the reset reason, the heap and the log around it. Close the monitor first (Ctrl+]): both need the same port.

    Terminal window
    crosspad-hil diagnose --elf build_v2/CrossPad.elf

    Without --log it listens to the board for 3 seconds (--seconds for longer) and does not reset it; add --log <file> to read a saved log instead. From Claude, call crosspad_diagnose_crash after crosspad_toolsets action=enable toolset=device.

    You should see: a report like this, and exit code 1 because it found an error:

    PANIC core 0: <cause>
    pc=0x… excvaddr=0x… reset=…
    backtrace:
    #0 0x… <function> <file>:<line>
    elf: …/CrossPad.elf (matches the log)
    likely cause: …
    context: hil_logs/… (… lines around the panic)

    The first frame is often in ROM and shows ??; that is normal. no panic in console:dev_xxxx means the log had no error while diagnose listened.

    If not: DOES NOT match the log: the ELF is not the build on the board; see diagnose says the ELF does not match the log. Exit code 2 naming addr2line: ESP-IDF is not loaded in this terminal; see idf.py command not found.

  5. Decode addresses by hand

    Use this when you have a backtrace but no crosspad-hil, or one address to check. Pass the ELF from your board’s build folder and the first address of each 0x…:0x… pair after Backtrace:.

    Terminal window
    xtensa-esp32s3-elf-addr2line -e build_v2/CrossPad.elf <addr> <addr>

    You should see: one <file>:<line> per address, in the order you passed them. ROM addresses print ??:0.

    If not: the command is not found: idf.py command not found. The lines make no sense: the ELF is from another build; see diagnose says the ELF does not match the log.

  6. Trace STM32 variables over SWD

    Use crosspad_trace to watch STM32 variables (pads, power, charger) live; the swd-tracer guide covers its setup. It needs an ST-Link on the STM32’s SWD pins and the STM32 Debug build; in Claude, enable the tool and run its self-check first:

    crosspad_toolsets action=enable toolset=trace
    crosspad_trace action=doctor

    You should see: a report that lists any issues and whether a probe is connected.

    If not: follow the guide’s setup for each issue it names. If Claude shows no crosspad tools: Claude shows no crosspad tools.

  7. Save a support bundle

    doctor checks your tools and the board. support packs its findings, your project state and the last update log into a zip to attach when you ask for help.

    Terminal window
    python3 tools/app_manager.py doctor
    python3 tools/app_manager.py support

    One-line installer: cptools doctor and cptools support.

    You should see: the doctor ends with Ready. or N thing(s) to fix., then Saved …/.crosspad/support/crosspad-support-<date>-<time>.zip.

    If not: doctor reports things to fix

Terminal window
crosspad-hil diagnose

With no error in the log it prints no panic in console:dev_xxxx (… lines, 0 boots) and exits 0.