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