1#![no_std]
2use qingke::{
8 register::mtvec::{self, TrapMode},
9 riscv::register::mcause,
10};
11#[cfg(feature = "highcode")]
12pub use qingke_rt_macros::highcode;
13pub use qingke_rt_macros::{entry, interrupt};
14
15use core::arch::global_asm;
16
17mod asm;
18
19#[unsafe(export_name = "error: riscv-rt appears more than once in the dependency graph")]
21#[doc(hidden)]
22pub static __ONCE__: () = ();
23
24unsafe extern "C" {
25 fn Exception();
26
27 fn InstructionMisaligned();
28 fn InstructionFault();
29 fn IllegalInstruction();
30 fn LoadMisaligned();
31 fn LoadFault();
32 fn StoreMisaligned();
33 fn StoreFault();
34
35 fn NonMaskableInt();
36 fn MachineEnvCall();
37 fn UserEnvCall();
38 fn Breakpoint();
39 fn SysTick();
40 fn Software();
41}
42
43#[doc(hidden)]
44#[unsafe(no_mangle)]
45#[unsafe(link_section = ".vector_table.exceptions")]
46pub static __EXCEPTIONS: [Option<unsafe extern "C" fn()>; 12] = [
47 Some(InstructionMisaligned), Some(InstructionFault),
49 Some(IllegalInstruction),
50 Some(Breakpoint),
51 Some(LoadMisaligned),
52 Some(LoadFault), Some(StoreMisaligned),
54 Some(StoreFault), Some(UserEnvCall), None,
57 None,
58 Some(MachineEnvCall),
59];
60
61#[derive(Copy, Clone, Debug, PartialEq, Eq)]
62#[repr(u8)]
63pub enum CoreInterrupt {
64 NonMaskableInt = 2,
65 Exception = 3,
66 MachineEnvCall = 5,
67 UserEnvCall = 8,
68 Breakpoint = 9,
69 SysTick = 12,
70 Software = 14,
71}
72
73impl CoreInterrupt {
74 pub fn try_from(irq: u8) -> Result<Self, u8> {
75 match irq {
76 2 => Ok(CoreInterrupt::NonMaskableInt),
77 3 => Ok(CoreInterrupt::Exception),
78 5 => Ok(CoreInterrupt::MachineEnvCall),
79 8 => Ok(CoreInterrupt::UserEnvCall),
80 9 => Ok(CoreInterrupt::Breakpoint),
81 12 => Ok(CoreInterrupt::SysTick),
82 14 => Ok(CoreInterrupt::Software),
83
84 _ => Err(irq),
85 }
86 }
87}
88
89#[doc(hidden)]
91#[unsafe(no_mangle)]
92#[used]
93#[unsafe(link_section = ".vector_table.core_interrupts")]
94pub static __CORE_INTERRUPTS: [Option<unsafe extern "C" fn()>; 15] = [
95 None,
97 Some(NonMaskableInt), Some(Exception), None,
100 Some(MachineEnvCall), None,
102 None,
103 Some(UserEnvCall), Some(Breakpoint), None,
106 None,
107 Some(SysTick), None,
109 Some(Software), None,
111];
112#[unsafe(link_section = ".init.rust")]
115#[unsafe(export_name = "_setup_interrupts")]
116unsafe extern "C" fn qingke_setup_interrupts() {
117 #[cfg(feature = "v2")]
136 unsafe {
137 core::arch::asm!(
138 "
139 li t0, 0x1880
140 csrw mstatus, t0
141 li t0, 0x3
142 csrw 0x804, t0
143 "
144 );
145 }
146
147 #[cfg(feature = "v3")]
149 unsafe {
150 #[cfg(feature = "u-mode")]
151 core::arch::asm!(
152 "
153 li t0, 0x80
154 csrs mstatus, t0
155 "
156 );
157 #[cfg(not(feature = "u-mode"))]
158 core::arch::asm!(
159 "
160 li t0, 0x1880
161 csrs mstatus, t0
162 "
163 );
164 }
165
166 #[cfg(any(
169 feature = "v4",
170 not(any(feature = "v2", feature = "v3", feature = "v4")) ))]
172 unsafe {
173 #[cfg(feature = "u-mode")]
174 core::arch::asm!(
175 "
176 li t0, 0x1f
177 csrw 0xbc0, t0
178 li t0, 0x3
179 csrw 0x804, t0
180 li t0, 0x80
181 csrs mstatus, t0
182 "
183 );
184 #[cfg(not(feature = "u-mode"))]
185 core::arch::asm!(
186 "
187 li t0, 0x1f
188 csrw 0xbc0, t0
189 li t0, 0x3
190 csrw 0x804, t0
191 li t0, 0x1880
192 csrs mstatus, t0
193 "
194 );
195 qingke::register::gintenr::set_enable();
196 }
197
198 unsafe {
201 #[cfg(feature = "highcode")]
202 mtvec::write(0x20000000, TrapMode::VectoredAddress);
203
204 #[cfg(not(feature = "highcode"))]
205 mtvec::write(0x00000000, TrapMode::VectoredAddress);
206
207 qingke::pfic::wfi_to_wfe(true);
208 }
209}
210
211#[doc(hidden)]
212#[unsafe(no_mangle)]
213#[allow(non_snake_case)]
214pub fn DefaultInterruptHandler() {
215 loop {
216 continue;
219 }
220}
221
222#[doc(hidden)]
223#[unsafe(no_mangle)]
224#[allow(non_snake_case)]
225pub fn DefaultExceptionHandler() -> ! {
226 loop {
227 continue;
230 }
231}
232
233global_asm!(
235 r#"
236 .section .trap, "ax"
237 .global _exception_handler
238 _exception_handler:
239 addi sp, sp, -4
240 sw ra, 0(sp)
241 jal _exception_handler_rust
242 lw ra, 0(sp)
243 addi sp, sp, 4
244 mret
245 "#
246);
247
248#[doc(hidden)]
249#[unsafe(link_section = ".trap.rust")]
250#[unsafe(export_name = "_exception_handler_rust")]
251pub unsafe extern "C" fn qingke_exception_handler() {
252 unsafe extern "C" {
254 fn ExceptionHandler();
255 }
256
257 let cause = mcause::read();
258 let code = cause.code();
259
260 if cause.is_exception() {
261 if code < __EXCEPTIONS.len() {
262 let h = &__EXCEPTIONS[code];
263 if let Some(handler) = h {
264 unsafe { handler() };
265 } else {
266 unsafe { ExceptionHandler() };
267 }
268 } else {
269 unsafe { ExceptionHandler() };
270 }
271 } else {
272 loop {
273 continue;
276 }
277 }
278}