xtensa_lx_rt/exception/
context.rs

1use super::ExceptionCause;
2
3/// State of the CPU saved when entering exception or interrupt
4///
5/// Must be aligned with assembly frame format in asm.rs
6#[repr(C)]
7#[allow(non_snake_case)]
8#[derive(Debug, Clone, Copy)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub struct Context {
11    pub PC: u32,
12    pub PS: u32,
13
14    pub A0: u32,
15    pub A1: u32,
16    pub A2: u32,
17    pub A3: u32,
18    pub A4: u32,
19    pub A5: u32,
20    pub A6: u32,
21    pub A7: u32,
22    pub A8: u32,
23    pub A9: u32,
24    pub A10: u32,
25    pub A11: u32,
26    pub A12: u32,
27    pub A13: u32,
28    pub A14: u32,
29    pub A15: u32,
30    pub SAR: u32,
31    pub EXCCAUSE: u32,
32    pub EXCVADDR: u32,
33    pub LBEG: u32,
34    pub LEND: u32,
35    pub LCOUNT: u32,
36    pub THREADPTR: u32,
37    pub SCOMPARE1: u32,
38    pub BR: u32,
39    pub ACCLO: u32,
40    pub ACCHI: u32,
41    pub M0: u32,
42    pub M1: u32,
43    pub M2: u32,
44    pub M3: u32,
45    #[cfg(XCHAL_HAVE_CP)]
46    // Either F64R_LO or CPENABLE depending on `float-save-restore`.
47    pub F64R_LO_CPENABLE: u32,
48    // F64R_HI is only meaningful with cfg!(XCHAL_HAVE_DFP_ACCEL) but it's present in the stack
49    // frame unconditionally
50    #[cfg(feature = "float-save-restore")]
51    pub F64R_HI: u32,
52    // F64S is only meaningful with cfg!(XCHAL_HAVE_DFP_ACCEL) but it's present in the stack frame
53    // unconditionally
54    #[cfg(feature = "float-save-restore")]
55    pub F64S: u32,
56    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
57    pub FCR: u32,
58    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
59    pub FSR: u32,
60    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
61    pub F0: u32,
62    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
63    pub F1: u32,
64    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
65    pub F2: u32,
66    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
67    pub F3: u32,
68    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
69    pub F4: u32,
70    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
71    pub F5: u32,
72    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
73    pub F6: u32,
74    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
75    pub F7: u32,
76    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
77    pub F8: u32,
78    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
79    pub F9: u32,
80    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
81    pub F10: u32,
82    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
83    pub F11: u32,
84    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
85    pub F12: u32,
86    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
87    pub F13: u32,
88    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
89    pub F14: u32,
90    #[cfg(all(feature = "float-save-restore", XCHAL_HAVE_FP))]
91    pub F15: u32,
92}
93
94impl Default for Context {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100impl Context {
101    /// Creates a new, zeroed out context.
102    pub const fn new() -> Self {
103        unsafe { core::mem::zeroed() }
104    }
105}
106
107unsafe extern "Rust" {
108    /// The exception assembly jumps here once registers have been spilled
109    fn __exception(cause: ExceptionCause, save_frame: &mut Context);
110    /// This symbol will be provided by the user via `#[exception]`
111    fn __user_exception(cause: ExceptionCause, save_frame: &mut Context);
112    /// No attribute is supplied for this symbol as the double exception can
113    /// hardly occur
114    fn __double_exception(cause: ExceptionCause, save_frame: &mut Context);
115
116    /// This symbol will be provided by the user via `#[interrupt(1)]`
117    fn __level_1_interrupt(save_frame: &mut Context);
118    /// This symbol will be provided by the user via `#[interrupt(2)]`
119    fn __level_2_interrupt(save_frame: &mut Context);
120    /// This symbol will be provided by the user via `#[interrupt(3)]`
121    fn __level_3_interrupt(save_frame: &mut Context);
122    /// This symbol will be provided by the user via `#[interrupt(4)]`
123    fn __level_4_interrupt(save_frame: &mut Context);
124    /// This symbol will be provided by the user via `#[interrupt(5)]`
125    fn __level_5_interrupt(save_frame: &mut Context);
126    /// This symbol will be provided by the user via `#[interrupt(6)]`
127    fn __level_6_interrupt(save_frame: &mut Context);
128    /// This symbol will be provided by the user via `#[interrupt(7)]`
129    fn __level_7_interrupt(save_frame: &mut Context);
130}
131
132#[unsafe(no_mangle)]
133#[unsafe(link_section = ".rwtext")]
134unsafe extern "C" fn __default_exception(cause: ExceptionCause, save_frame: &mut Context) {
135    unsafe { __user_exception(cause, save_frame) }
136}
137
138#[unsafe(no_mangle)]
139#[unsafe(link_section = ".rwtext")]
140extern "C" fn __default_user_exception(cause: ExceptionCause, save_frame: &Context) {
141    #[cfg(any(feature = "esp32", feature = "esp32s3"))]
142    if cause == ExceptionCause::Cp0Disabled {
143        panic!(
144            "Access to the floating point coprocessor is not allowed. You may want to enable the `float-save-restore` feature of the `xtensa-lx-rt` crate. {:08x?}",
145            save_frame
146        )
147    }
148
149    panic!("Exception: {:?}, {:08x?}", cause, save_frame)
150}
151
152#[unsafe(no_mangle)]
153#[unsafe(link_section = ".rwtext")]
154extern "C" fn __default_interrupt(level: u32, save_frame: &Context) {
155    panic!("Interrupt: {:?}, {:08x?}", level, save_frame)
156}
157
158#[unsafe(no_mangle)]
159#[unsafe(link_section = ".rwtext")]
160extern "C" fn __default_double_exception(cause: ExceptionCause, save_frame: &Context) {
161    panic!("Double Exception: {:?}, {:08x?}", cause, save_frame)
162}