test_backtrace.c 3.2 KB

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