I'm quite new to esp-idf and I'm building an app where I really need to intercept exceptions, disable faulty components and do some raw user/app-controlled tracing, but I'm afraid I need a custom error handler.
I hate the idea of modifying the official esp-idf's components just to add something that will need to be re-implemented every time I'll have to update ESP-IDF, but this is all I can think of for now.
This is what I'm changing:
esp-idf/components/freertos/include/xtensa_api.h location: see this
- /* Typedef for C-callable standard error handler callback */
- typedef void (*xt_error_handler_callback)(XtExcFrame *, int core_id, bool is_abort);
- /*
- -------------------------------------------------------------------------------
- Call this function to set a callback for the standard error handler.
- The callback will be called by the commonErrorHandler on all errors.
- f - Callback function address, NULL to uninstall callback.
- The callback will be passed a pointer to the exception frame, which is created
- on the stack of the thread that caused the exception, the core id and
- a bool to signal if abort() has been called.
- The callback is called with watchdogs disabled.
- -------------------------------------------------------------------------------
- */
- extern xt_error_handler_callback xt_set_error_handler_callback(xt_error_handler_callback f);
esp-idf/components/esp32/panic.c here
- #if CONFIG_ESP32_PANIC_CALLBACK
- /*
- * Custom error handler callback registration.
- */
- xt_error_handler_callback customErrorHandler = NULL;
- xt_error_handler_callback xt_set_error_handler_callback(xt_error_handler_callback f)
- {
- xt_error_handler_callback old = customErrorHandler;
- customErrorHandler = f;
- return old;
- }
- #endif //CONFIG_ESP32_PANIC_CALLBACK
The following one is then added inside of the commonErrorHandler() location: see this
- #if CONFIG_ESP32_PANIC_CALLBACK
- if (customErrorHandler) {
- disableAllWdts();
- customErrorHandler(frame, core_id, abort_called);
- reconfigureAllWdts();
- }
- #endif
Finally, I added an entry to KConfig in order to configure the ESP32_PANIC_CALLBACK variable:
Code: Select all
menu "Custom Error Handling"
config ESP32_PANIC_CALLBACK
bool "Support registration of a user defined callback for the panic handler"
default y
help
Use xt_set_error_handler_callback() to register a custom callback.
The callback is called by the common error handler so catches exceptions,
panics and abort() calls.
endmenu
Expected results:
This should, in theory, allow me to register a custom handler function, so that inside of my main:
- #include "freertos/xtensa_api.h" // Forgot to mention but was there
- // I should be able to set my handler callback calling
- xt_set_error_handler_callback(ErrorCallback);
- void Boot::ErrorCallback(XtExcFrame *frame, int core_id, bool is_abort)
- {
- boot_data.crash_data.core_id = core_id;
- boot_data.crash_data.is_abort = is_abort;
- // Save registers:
- for (int i = 0; i < 24; i++)
- boot_data.crash_data.reg[i] = ((uint32_t *)frame)[i + 1];
- // Save backtrace:
- // (see panic.c::doBacktrace() for code template)
- #define _adjusted_pc(pc) (((pc)&0x80000000) ? (((pc)&0x3fffffff) | 0x40000000) : (pc))
- uint32_t i = 0, pc = frame->pc, sp = frame->a1;
- boot_data.crash_data.bt[0].pc = _adjusted_pc(pc);
- pc = frame->a0;
- while (++i < SENSE_BT_LEVELS)
- {
- uint32_t psp = sp;
- if (!esp_stack_ptr_is_sane(sp))
- break;
- sp = *((uint32_t *)(sp - 0x10 + 4));
- boot_data.crash_data.bt[i].pc = _adjusted_pc(pc - 3);
- pc = *((uint32_t *)(psp - 0x10));
- if (pc < 0x40000000)
- break;
- }
- }
Issues with the code above:
- The code seems to be compiling successfully until I get an "undefined reference error" when I call the xt_set_error_handler_callback(ErrorCallback):
Code: Select all
cmd.exe /C "cd . && C:\Users\me\.espressif\tools\xtensa-esp32-elf\esp-2019r2-8.2.0\xtensa-esp32-elf\bin\xtensa-esp32-elf-g++.exe -mlongcalls -Wno-frame-address -nostdlib @CMakeFiles\app.elf.rsp -o app.elf && cd ."
c:/users/me/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(app_boot.cpp.obj):(.literal._ZN4BootC2Ev+0x38): undefined reference to `xt_set_error_handler_callback(void (*)(XtExcFrame*, int, bool))'
c:/users/me/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(app_boot.cpp.obj): in function `Boot::Boot()':
c:\development\app\build/../main/app_boot.cpp:158: undefined reference to `xt_set_error_handler_callback(void (*)(XtExcFrame*, int, bool))'
- I would love to find a different solution so that I don't have to adjust those files inside esp-idf every time I have to perform an update. Suggestion are very welcome
Some help would be really appreciated, thank you in advance.