1#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
12#![doc(html_logo_url = "https://docs.espressif.com/projects/rust/esp-rs-grey-bg.svg")]
13#![deny(missing_docs)]
14#![no_std]
15
16use core::arch::global_asm;
17
18pub use riscv;
19pub use riscv_rt::{TrapFrame, entry};
20
21#[doc(hidden)]
22#[unsafe(no_mangle)]
23pub unsafe extern "C" fn _dispatch_exception(trap_frame: &TrapFrame, _code: usize) {
24 unsafe extern "C" {
25 fn _start_trap_rust_hal(trap_frame: &TrapFrame);
26 }
27
28 unsafe {
29 _start_trap_rust_hal(trap_frame);
30 }
31}
32
33macro_rules! cfg_global_asm {
35 {@inner, [$($x:tt)*], } => {
36 global_asm!{$($x)*}
37 };
38 (@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => {
39 #[cfg($meta)]
40 cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
41 #[cfg(not($meta))]
42 cfg_global_asm!{@inner, [$($x)*], $($rest)*}
43 };
44 {@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => {
45 cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
46 };
47 {$($asms:tt)*} => {
48 cfg_global_asm!{@inner, [], $($asms)*}
49 };
50}
51
52cfg_global_asm! {
53 r#"
54.section .init, "ax"
55.weak __pre_init
56__pre_init:"#,
57 #[cfg(feature = "rtc-ram")]
59 r#"
60 la a0, _rtc_fast_bss_start
61 la a1, _rtc_fast_bss_end
62 bge a0, a1, 2f
63 mv a3, x0
64 1:
65 sw a3, 0(a0)
66 addi a0, a0, 4
67 blt a0, a1, 1b
68 2:
69"#,
70 #[cfg(feature = "rtc-ram")]
72 r#"
73 mv a0, zero
74 mv t0, ra
75 call rtc_get_reset_reason
76 mv ra, t0
77 addi a1, zero, 1
78 bne a0, a1, 2f
79 la a0, _rtc_fast_persistent_start
80 la a1, _rtc_fast_persistent_end
81 bge a0, a1, 2f
82 mv a3, x0
83 1:
84 sw a3, 0(a0)
85 addi a0, a0, 4
86 blt a0, a1, 1b
87 2:
88"#,
89 r#"
91 la a0, _dram2_uninit_bss_start
92 la a1, _dram2_uninit_bss_end
93 bge a0, a1, 2f
94 mv a3, x0
95 1:
96 sw a3, 0(a0)
97 addi a0, a0, 4
98 blt a0, a1, 1b
99 2:
100"#,
101r#"
102 ret
103
104/*
105 Move SP to a valid memory region if needed.
106*/
107
108.section .trap.start, "ax"
109.extern _pre_default_start_trap_ret
110.global _pre_default_start_trap
111_pre_default_start_trap:
112 // move SP to some safe place if it's pointing below the RAM
113 // or into .trap / .rwtext.
114 //
115 // Otherwise we won't be able to do anything reasonable
116 // (since we don't have a working stack)
117 //
118 // most probably we will just print something and halt in this case
119 // we actually can't do anything else
120 csrw mscratch, t0
121 la t0, _dram_data_start
122 bge sp, t0, 1f
123
124 // use the reserved exception cause 14 to signal we detected a stack overflow
125 li t0, 14
126 csrw mcause, t0
127
128 // set SP to the start of the stack
129 la sp, _stack_start
130 li t0, 4 // make sure stack start is in RAM
131 sub sp, sp, t0
132 andi sp, sp, -16 // Force 16-byte alignment
133
134 1:
135 csrr t0, mscratch
136
137 j _pre_default_start_trap_ret
138
139/*
140 Interrupt vector table (_vector_table)
141*/
142
143.section .trap, "ax"
144.weak _vector_table
145.type _vector_table, @function
146
147.option push
148.balign 0x100
149.option norelax
150.option norvc
151
152_vector_table:
153 j _start_trap
154 j _start_Trap1_trap
155 j _start_Trap2_trap
156 j _start_Trap3_trap
157 j _start_Trap4_trap
158 j _start_Trap5_trap
159 j _start_Trap6_trap
160 j _start_Trap7_trap
161 j _start_Trap8_trap
162 j _start_Trap9_trap
163 j _start_Trap10_trap
164 j _start_Trap11_trap
165 j _start_Trap12_trap
166 j _start_Trap13_trap
167 j _start_Trap14_trap
168 j _start_Trap15_trap
169 j _start_Trap16_trap
170 j _start_Trap17_trap
171 j _start_Trap18_trap
172 j _start_Trap19_trap
173 j _start_Trap20_trap
174 j _start_Trap21_trap
175 j _start_Trap22_trap
176 j _start_Trap23_trap
177 j _start_Trap24_trap
178 j _start_Trap25_trap
179 j _start_Trap26_trap
180 j _start_Trap27_trap
181 j _start_Trap28_trap
182 j _start_Trap29_trap
183 j _start_Trap30_trap
184 j _start_Trap31_trap
185"#,
186 #[cfg(feature = "clic-48")]
187r#"
188 j _start_Trap32_trap
189 j _start_Trap33_trap
190 j _start_Trap34_trap
191 j _start_Trap35_trap
192 j _start_Trap36_trap
193 j _start_Trap37_trap
194 j _start_Trap38_trap
195 j _start_Trap39_trap
196 j _start_Trap40_trap
197 j _start_Trap41_trap
198 j _start_Trap42_trap
199 j _start_Trap43_trap
200 j _start_Trap44_trap
201 j _start_Trap45_trap
202 j _start_Trap46_trap
203 j _start_Trap47_trap
204"#,
205r#"
206 .option pop
207"#,
208}
209
210macro_rules! define_interrupt {
211 ($num:literal, $name:ident, $fname:ident) => {
212 #[derive(Copy, Clone)]
213 struct $name;
214
215 unsafe impl riscv_rt::InterruptNumber for $name {
216 const MAX_INTERRUPT_NUMBER: usize = if cfg!(feature = "clic-48") { 47 } else { 31 };
217
218 fn number(self) -> usize {
219 $num
220 }
221
222 fn from_number(_value: usize) -> riscv_rt::result::Result<Self> {
223 Ok($name)
224 }
225 }
226
227 unsafe impl riscv_rt::CoreInterruptNumber for $name {}
228
229 #[unsafe(naked)]
230 #[unsafe(link_section = ".trap.start")]
231 #[riscv_rt::core_interrupt($name)]
232 extern "C" fn $fname() {
233 core::arch::naked_asm! {
234 concat!(
235 "
236 li a0,",$num,"
237 j handle_interrupts
238 "
239 )
240 }
241 }
242 };
243}
244
245define_interrupt!(1, Trap1, trap1);
246define_interrupt!(2, Trap2, trap2);
247define_interrupt!(3, Trap3, trap3);
248define_interrupt!(4, Trap4, trap4);
249define_interrupt!(5, Trap5, trap5);
250define_interrupt!(6, Trap6, trap6);
251define_interrupt!(7, Trap7, trap7);
252define_interrupt!(8, Trap8, trap8);
253define_interrupt!(9, Trap9, trap9);
254define_interrupt!(10, Trap10, trap10);
255define_interrupt!(11, Trap11, trap11);
256define_interrupt!(12, Trap12, trap12);
257define_interrupt!(13, Trap13, trap13);
258define_interrupt!(14, Trap14, trap14);
259define_interrupt!(15, Trap15, trap15);
260define_interrupt!(16, Trap16, trap16);
261define_interrupt!(17, Trap17, trap17);
262define_interrupt!(18, Trap18, trap18);
263define_interrupt!(19, Trap19, trap19);
264define_interrupt!(20, Trap20, trap20);
265define_interrupt!(21, Trap21, trap21);
266define_interrupt!(22, Trap22, trap22);
267define_interrupt!(23, Trap23, trap23);
268define_interrupt!(24, Trap24, trap24);
269define_interrupt!(25, Trap25, trap25);
270define_interrupt!(26, Trap26, trap26);
271define_interrupt!(27, Trap27, trap27);
272define_interrupt!(28, Trap28, trap28);
273define_interrupt!(29, Trap29, trap29);
274define_interrupt!(30, Trap30, trap30);
275define_interrupt!(31, Trap31, trap31);
276
277#[cfg(feature = "clic-48")]
278mod clic {
279 define_interrupt!(32, Trap32, trap32);
280 define_interrupt!(33, Trap33, trap33);
281 define_interrupt!(34, Trap34, trap34);
282 define_interrupt!(35, Trap35, trap35);
283 define_interrupt!(36, Trap36, trap36);
284 define_interrupt!(37, Trap37, trap37);
285 define_interrupt!(38, Trap38, trap38);
286 define_interrupt!(39, Trap39, trap39);
287 define_interrupt!(40, Trap40, trap40);
288 define_interrupt!(41, Trap41, trap41);
289 define_interrupt!(42, Trap42, trap42);
290 define_interrupt!(43, Trap43, trap43);
291 define_interrupt!(44, Trap44, trap44);
292 define_interrupt!(45, Trap45, trap45);
293 define_interrupt!(46, Trap46, trap46);
294 define_interrupt!(47, Trap47, trap47);
295}