2021-06-03 11:40:09 +00:00
|
|
|
/*
|
2022-01-17 09:44:25 +00:00
|
|
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
2021-06-03 11:40:09 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2019-01-04 12:38:33 +00:00
|
|
|
/*
|
|
|
|
* Note: Currently, the backtraces must still be checked manually. Therefore,
|
|
|
|
* these test cases should always pass.
|
|
|
|
* Todo: Automate the checking of backtrace addresses.
|
|
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "unity.h"
|
2021-04-06 12:38:34 +00:00
|
|
|
|
|
|
|
#if __XTENSA__
|
|
|
|
|
2019-01-04 12:38:33 +00:00
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
|
|
|
#include "freertos/xtensa_api.h"
|
|
|
|
#include "esp_intr_alloc.h"
|
2020-07-21 05:07:34 +00:00
|
|
|
#include "esp_rom_sys.h"
|
|
|
|
#include "esp_rom_uart.h"
|
2019-01-04 12:38:33 +00:00
|
|
|
|
|
|
|
#define SW_ISR_LEVEL_1 7
|
|
|
|
#define SW_ISR_LEVEL_3 29
|
|
|
|
#define RECUR_DEPTH 3
|
|
|
|
#define ACTION_ABORT -1
|
|
|
|
#define ACTION_INT_WDT -2
|
|
|
|
|
|
|
|
// Set to (-1) for abort(), (-2) for interrupt watchdog
|
|
|
|
static int backtrace_trigger_source;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Recursive functions to generate a longer call stack. When the max specified
|
|
|
|
* recursion depth is reached, the following actions can be taken.
|
|
|
|
*/
|
|
|
|
static void __attribute__((__noinline__)) recursive_func(int recur_depth, int action)
|
|
|
|
{
|
|
|
|
if (recur_depth > 1) {
|
|
|
|
recursive_func(recur_depth - 1, action);
|
|
|
|
} else if (action >= 0) {
|
|
|
|
xt_set_intset(1 << action);
|
|
|
|
} else if (action == ACTION_ABORT) {
|
|
|
|
abort();
|
|
|
|
// Todo: abort() causes problems in GDB Stub backtrace due to being 'non returning'.
|
|
|
|
} else if (action == ACTION_INT_WDT) {
|
|
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
while (1) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void level_three_isr (void *arg)
|
|
|
|
{
|
|
|
|
xt_set_intclear(1 << SW_ISR_LEVEL_3); //Clear interrupt
|
|
|
|
recursive_func(RECUR_DEPTH, backtrace_trigger_source); //Abort at the max recursive depth
|
|
|
|
}
|
|
|
|
|
|
|
|
static void level_one_isr(void *arg)
|
|
|
|
{
|
|
|
|
xt_set_intclear(1 << SW_ISR_LEVEL_1); //Clear interrupt
|
|
|
|
recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_3); //Trigger nested interrupt max recursive depth
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Test backtrace from abort", "[reset_reason][reset=abort,SW_CPU_RESET]")
|
|
|
|
{
|
|
|
|
//Allocate level one and three SW interrupts
|
|
|
|
esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, 0, level_one_isr, NULL, NULL); //Level 1 SW intr
|
|
|
|
esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, 0, level_three_isr, NULL, NULL); //Level 3 SW intr
|
|
|
|
backtrace_trigger_source = ACTION_ABORT;
|
|
|
|
recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_1); //Trigger lvl 1 SW interrupt at max recursive depth
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Test backtrace from interrupt watchdog timeout", "[reset_reason][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET]")
|
|
|
|
{
|
|
|
|
//Allocate level one and three SW interrupts
|
|
|
|
esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, 0, level_one_isr, NULL, NULL); //Level 1 SW intr
|
|
|
|
esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, 0, level_three_isr, NULL, NULL); //Level 3 SW intr
|
|
|
|
backtrace_trigger_source = ACTION_INT_WDT;
|
|
|
|
recursive_func(RECUR_DEPTH, SW_ISR_LEVEL_1); //Trigger lvl 1 SW interrupt at max recursive depth
|
|
|
|
}
|
2020-01-02 17:50:32 +00:00
|
|
|
|
|
|
|
static void write_char_crash(char c)
|
|
|
|
{
|
2020-07-21 05:07:34 +00:00
|
|
|
esp_rom_uart_putc(c);
|
2020-01-02 17:50:32 +00:00
|
|
|
*(char*) 0x00000001 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Test backtrace with a ROM function", "[reset_reason][reset=StoreProhibited,SW_CPU_RESET]")
|
|
|
|
{
|
2022-01-17 09:44:25 +00:00
|
|
|
esp_rom_install_channel_putc(1, write_char_crash);
|
2020-07-21 05:07:34 +00:00
|
|
|
esp_rom_printf("foo");
|
2020-01-02 17:50:32 +00:00
|
|
|
}
|
2021-04-06 12:38:34 +00:00
|
|
|
|
|
|
|
#endif
|