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