test_backtrace.c 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Note: Currently, the backtraces must still be checked manually. Therefore,
  3. * these test cases should always pass.
  4. * Todo: Automate the checking of backtrace addresses.
  5. */
  6. #include <stdlib.h>
  7. #include "unity.h"
  8. #include "freertos/FreeRTOS.h"
  9. #include "freertos/task.h"
  10. #include "freertos/xtensa_api.h"
  11. #include "esp_intr_alloc.h"
  12. #include "esp_rom_sys.h"
  13. #include "esp_rom_uart.h"
  14. #define SW_ISR_LEVEL_1 7
  15. #define SW_ISR_LEVEL_3 29
  16. #define RECUR_DEPTH 3
  17. #define ACTION_ABORT -1
  18. #define ACTION_INT_WDT -2
  19. // Set to (-1) for abort(), (-2) for interrupt watchdog
  20. static int backtrace_trigger_source;
  21. /*
  22. * Recursive functions to generate a longer call stack. When the max specified
  23. * recursion depth is reached, the following actions can be taken.
  24. */
  25. static void __attribute__((__noinline__)) recursive_func(int recur_depth, int action)
  26. {
  27. if (recur_depth > 1) {
  28. recursive_func(recur_depth - 1, action);
  29. } else if (action >= 0) {
  30. xt_set_intset(1 << action);
  31. } else if (action == ACTION_ABORT) {
  32. abort();
  33. // Todo: abort() causes problems in GDB Stub backtrace due to being 'non returning'.
  34. } else if (action == ACTION_INT_WDT) {
  35. portDISABLE_INTERRUPTS();
  36. while (1) {
  37. ;
  38. }
  39. }
  40. }
  41. static void level_three_isr (void *arg)
  42. {
  43. xt_set_intclear(1 << SW_ISR_LEVEL_3); //Clear interrupt
  44. recursive_func(RECUR_DEPTH, backtrace_trigger_source); //Abort at the max recursive depth
  45. }
  46. static void level_one_isr(void *arg)
  47. {
  48. xt_set_intclear(1 << SW_ISR_LEVEL_1); //Clear interrupt
  49. recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_3); //Trigger nested interrupt max recursive depth
  50. }
  51. TEST_CASE("Test backtrace from abort", "[reset_reason][reset=abort,SW_CPU_RESET]")
  52. {
  53. //Allocate level one and three SW interrupts
  54. esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, 0, level_one_isr, NULL, NULL); //Level 1 SW intr
  55. esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, 0, level_three_isr, NULL, NULL); //Level 3 SW intr
  56. backtrace_trigger_source = ACTION_ABORT;
  57. recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_1); //Trigger lvl 1 SW interrupt at max recursive depth
  58. }
  59. TEST_CASE("Test backtrace from interrupt watchdog timeout", "[reset_reason][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET]")
  60. {
  61. //Allocate level one and three SW interrupts
  62. esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, 0, level_one_isr, NULL, NULL); //Level 1 SW intr
  63. esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, 0, level_three_isr, NULL, NULL); //Level 3 SW intr
  64. backtrace_trigger_source = ACTION_INT_WDT;
  65. recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_1); //Trigger lvl 1 SW interrupt at max recursive depth
  66. }
  67. static void write_char_crash(char c)
  68. {
  69. esp_rom_uart_putc(c);
  70. *(char*) 0x00000001 = 0;
  71. }
  72. TEST_CASE("Test backtrace with a ROM function", "[reset_reason][reset=StoreProhibited,SW_CPU_RESET]")
  73. {
  74. ets_install_putc1(&write_char_crash);
  75. esp_rom_printf("foo");
  76. }