summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@adafruit.com>2020-05-28 22:10:46 -0400
committerGitHub <noreply@github.com>2020-05-28 22:10:46 -0400
commit7ea95457eeb67fcaccfa911a4d979fa642262da5 (patch)
treeb99da88cb1b8792b1ec493867ded60046aa33376
parent6ace4ee7e834eb5960876f2c6e75febb3760f9cf (diff)
parent2fb4fa328946b07d90bd951d4a134ea8d31be7e8 (diff)
Merge pull request #2974 from tannewt/esp32s2_spill
Spill registers before scanning the stack.
-rw-r--r--ports/esp32s2/mphalport.c20
-rw-r--r--ports/esp32s2/tools/decode_backtrace.py23
2 files changed, 42 insertions, 1 deletions
diff --git a/ports/esp32s2/mphalport.c b/ports/esp32s2/mphalport.c
index 772b61c9e..da5258b0e 100644
--- a/ports/esp32s2/mphalport.c
+++ b/ports/esp32s2/mphalport.c
@@ -37,6 +37,24 @@ void mp_hal_delay_us(mp_uint_t delay) {
mp_hal_delay_ms(delay / 1000);
}
-mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) {
+// This is provided by the esp-idf/components/xtensa/esp32s2/libhal.a binary
+// blob.
+extern void xthal_window_spill(void);
+
+mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs, uint8_t reg_count) {
+ // xtensa has more registers than an instruction can address. The 16 that
+ // can be addressed are called the "window". When a function is called or
+ // returns the window rotates. This allows for more efficient function calls
+ // because ram doesn't need to be used. It's only used if the window wraps
+ // around onto itself. At that point values are "spilled" to empty spots in
+ // the stack that were set aside. When the window rotates back around (on
+ // function return), the values are restored into the register from ram.
+
+ // So, in order to read the values in the stack scan we must make sure all
+ // of the register values we care about have been spilled to RAM. Luckily,
+ // there is a HAL call to do it. There is a bit of a race condition here
+ // because the register value could change after it's been restored but that
+ // is unlikely to happen with a heap pointer while we do a GC.
+ xthal_window_spill();
return (mp_uint_t) __builtin_frame_address(0);
}
diff --git a/ports/esp32s2/tools/decode_backtrace.py b/ports/esp32s2/tools/decode_backtrace.py
new file mode 100644
index 000000000..3f078895a
--- /dev/null
+++ b/ports/esp32s2/tools/decode_backtrace.py
@@ -0,0 +1,23 @@
+"""Simple script that translates "Backtrace:" lines from the ESP output to files
+ and line numbers.
+
+ Run with: python3 tools/decode_backtrace.py <board>
+
+ Enter the backtrace line at the "? " prompt. CTRL-C to exit the script.
+ """
+
+import subprocess
+import sys
+
+board = sys.argv[1]
+print(board)
+
+while True:
+ addresses = input("? ")
+ if addresses.startswith("Backtrace:"):
+ addresses = addresses[len("Backtrace:"):]
+ addresses = addresses.strip().split()
+ addresses = [address.split(":")[0] for address in addresses]
+ print('got', addresses)
+ subprocess.run(["xtensa-esp32s2-elf-addr2line",
+ "-e", "build-{}/firmware.elf".format(board)] + addresses)