mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-30 04:42:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			86 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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"
 | |
| #include "freertos/FreeRTOS.h"
 | |
| #include "freertos/task.h"
 | |
| #include "freertos/xtensa_api.h"
 | |
| #include "esp_intr_alloc.h"
 | |
| #include "esp_rom_sys.h"
 | |
| #include "esp_rom_uart.h"
 | |
| 
 | |
| #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
 | |
| }
 | |
| 
 | |
| static void write_char_crash(char c)
 | |
| {
 | |
|     esp_rom_uart_putc(c);
 | |
|     *(char*) 0x00000001 = 0;
 | |
| }
 | |
| 
 | |
| TEST_CASE("Test backtrace with a ROM function", "[reset_reason][reset=StoreProhibited,SW_CPU_RESET]")
 | |
| {
 | |
|     ets_install_putc1(&write_char_crash);
 | |
|     esp_rom_printf("foo");
 | |
| }
 | 
