1 /*
2  * Copyright (c) 2020 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_ARCH_XTENSA_CORE_INCLUDE_XTENSA_BACKTRACE_H_
8 #define ZEPHYR_ARCH_XTENSA_CORE_INCLUDE_XTENSA_BACKTRACE_H_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #ifndef __ASSEMBLER__
15 
16 #include <stdbool.h>
17 #include <stdint.h>
18 
19 /**
20  * @ingroup xtensa_internal_apis
21  * @{
22  */
23 
24 /**
25  * @brief   Structure used for backtracing
26  *
27  * This structure stores the backtrace information of a particular stack frame
28  * (i.e. the PC and SP). This structure is used iteratively with the
29  * xtensa_cpu_get_next_backtrace_frame() function to traverse each frame
30  * within a single stack. The next_pc represents the PC of the current
31  * frame's caller, thus a next_pc of 0 indicates that the current frame
32  * is the last frame on the stack.
33  *
34  * @note    Call esp_backtrace_get_start() to obtain initialization values for
35  *          this structure
36  */
37 struct xtensa_backtrace_frame_t {
38 	uint32_t pc;       /* PC of the current frame */
39 	uint32_t sp;       /* SP of the current frame */
40 	uint32_t next_pc;  /* PC of the current frame's caller */
41 };
42 
43 /**
44  * Get the first frame of the current stack's backtrace
45  *
46  * Given the following function call flow
47  * (B -> A -> X -> esp_backtrace_get_start),
48  * this function will do the following.
49  * - Flush CPU registers and window frames onto the current stack
50  * - Return PC and SP of function A (i.e. start of the stack's backtrace)
51  * - Return PC of function B (i.e. next_pc)
52  *
53  * @note This function is implemented in assembly
54  *
55  * @param[out] pc       PC of the first frame in the backtrace
56  * @param[out] sp       SP of the first frame in the backtrace
57  * @param[out] next_pc  PC of the first frame's caller
58  * @param[in] interrupted_stack Pointer to interrupted stack
59  */
60 void xtensa_backtrace_get_start(uint32_t *pc,
61 				uint32_t *sp,
62 				uint32_t *next_pc,
63 				int *interrupted_stack);
64 
65 /**
66  * @brief Get the next frame on a stack for backtracing
67  *
68  * Given a stack frame(i), this function will obtain the next
69  * stack frame(i-1) on the same call stack (i.e. the caller of frame(i)).
70  * This function is meant to be called iteratively when doing a backtrace.
71  *
72  * Entry Conditions: Frame structure containing valid SP and next_pc
73  * Exit Conditions:
74  *  - Frame structure updated with SP and PC of frame(i-1).
75  *    next_pc now points to frame(i-2).
76  *  - If a next_pc of 0 is returned, it indicates that frame(i-1)
77  *    is last frame on the stack
78  *
79  * @param[inout] frame  Pointer to frame structure
80  *
81  * @return
82  *  - True if the SP and PC of the next frame(i-1) are sane
83  *  - False otherwise
84  */
85 bool xtensa_backtrace_get_next_frame(struct xtensa_backtrace_frame_t *frame);
86 
87 /**
88  * @brief Print the backtrace of the current stack
89  *
90  * @param depth The maximum number of stack frames to print (should be > 0)
91  * @param interrupted_stack Pointer to interrupted stack
92  *
93  * @return
94  *      - 0    Backtrace successfully printed to completion or to depth limit
95  *      - -1   Backtrace is corrupted
96  */
97 int xtensa_backtrace_print(int depth, int *interrupted_stack);
98 
99 /**
100  * @}
101  */
102 
103 #endif
104 #ifdef __cplusplus
105 }
106 #endif
107 
108 #endif /* ZEPHYR_ARCH_XTENSA_CORE_INCLUDE_XTENSA_BACKTRACE_H_ */
109