249
249
//! ```
250
250
//!
251
251
//! Default implementation of this function wakes hart 0 and busy-loops all the other harts.
252
+ //!
253
+ //! ### `ExceptionHandler`
254
+ //!
255
+ //! This function is called when exception is occured. The exception reason can be decoded from the
256
+ //! `mcause` register.
257
+ //!
258
+ //! This function can be redefined in the following way:
259
+ //!
260
+ //! ``` no_run
261
+ //! #[export_name = "ExceptionHandler"]
262
+ //! fn custom_exception_handler(trap_frame: &riscv_rt::TrapFrame) -> ! {
263
+ //! // ...
264
+ //! }
265
+ //! ```
266
+ //! or
267
+ //! ``` no_run
268
+ //! #[no_mangle]
269
+ //! fn ExceptionHandler(trap_frame: &riscv_rt::TrapFrame) -> ! {
270
+ //! // ...
271
+ //! }
272
+ //! ```
273
+ //!
274
+ //! Default implementation of this function stucks in a busy-loop.
275
+ //!
276
+ //!
277
+ //! ### Core interrupt handlers
278
+ //!
279
+ //! This functions are called when corresponding interrupt is occured.
280
+ //! You can define an interrupt handler with one of the following names:
281
+ //! * `UserSoft`
282
+ //! * `SupervisorSoft`
283
+ //! * `MachineSoft`
284
+ //! * `UserTimer`
285
+ //! * `SupervisorTimer`
286
+ //! * `MachineTimer`
287
+ //! * `UserExternal`
288
+ //! * `SupervisorExternal`
289
+ //! * `MachineExternal`
290
+ //!
291
+ //! For example:
292
+ //! ``` no_run
293
+ //! #[export_name = "MachineTimer"]
294
+ //! fn custom_timer_handler() {
295
+ //! // ...
296
+ //! }
297
+ //! ```
298
+ //! or
299
+ //! ``` no_run
300
+ //! #[no_mangle]
301
+ //! fn MachineTimer() {
302
+ //! // ...
303
+ //! }
304
+ //! ```
305
+ //!
306
+ //! If interrupt handler is not explicitly defined, `DefaultHandler` is called.
307
+ //!
308
+ //! ### `DefaultHandler`
309
+ //!
310
+ //! This function is called when interrupt without defined interrupt handler is occured.
311
+ //! The interrupt reason can be decoded from the `mcause` register.
312
+ //!
313
+ //! This function can be redefined in the following way:
314
+ //!
315
+ //! ``` no_run
316
+ //! #[export_name = "DefaultHandler"]
317
+ //! fn custom_interrupt_handler() {
318
+ //! // ...
319
+ //! }
320
+ //! ```
321
+ //! or
322
+ //! ``` no_run
323
+ //! #[no_mangle]
324
+ //! fn DefaultHandler() {
325
+ //! // ...
326
+ //! }
327
+ //! ```
328
+ //!
329
+ //! Default implementation of this function stucks in a busy-loop.
252
330
253
331
// NOTE: Adapted from cortex-m/src/lib.rs
254
332
#![ no_std]
@@ -261,7 +339,7 @@ extern crate r0;
261
339
262
340
pub use macros:: { entry, pre_init} ;
263
341
264
- use riscv:: register:: mstatus ;
342
+ use riscv:: register:: mcause ;
265
343
266
344
#[ export_name = "error: riscv-rt appears more than once in the dependency graph" ]
267
345
#[ doc( hidden) ]
@@ -310,33 +388,134 @@ pub unsafe extern "C" fn start_rust() -> ! {
310
388
main ( ) ;
311
389
}
312
390
391
+ /// Registers saved in trap handler
392
+ #[ allow( missing_docs) ]
393
+ #[ repr( C ) ]
394
+ pub struct TrapFrame {
395
+ pub ra : usize ,
396
+ pub t0 : usize ,
397
+ pub t1 : usize ,
398
+ pub t2 : usize ,
399
+ pub t3 : usize ,
400
+ pub t4 : usize ,
401
+ pub t5 : usize ,
402
+ pub t6 : usize ,
403
+ pub a0 : usize ,
404
+ pub a1 : usize ,
405
+ pub a2 : usize ,
406
+ pub a3 : usize ,
407
+ pub a4 : usize ,
408
+ pub a5 : usize ,
409
+ pub a6 : usize ,
410
+ pub a7 : usize ,
411
+ }
412
+
313
413
314
414
/// Trap entry point rust (_start_trap_rust)
315
415
///
316
- /// mcause is read to determine the cause of the trap. XLEN-1 bit indicates
317
- /// if it's an interrupt or an exception. The result is converted to an element
318
- /// of the Interrupt or Exception enum and passed to handle_interrupt or
319
- /// handle_exception.
416
+ /// `mcause` is read to determine the cause of the trap. XLEN-1 bit indicates
417
+ /// if it's an interrupt or an exception. The result is examined and ExceptionHandler
418
+ /// or one of the core interrupt handlers is called.
320
419
#[ link_section = ".trap.rust" ]
321
420
#[ export_name = "_start_trap_rust" ]
322
- pub extern "C" fn start_trap_rust ( ) {
421
+ pub extern "C" fn start_trap_rust ( trap_frame : * const TrapFrame ) {
323
422
extern "C" {
324
- fn trap_handler ( ) ;
423
+ fn ExceptionHandler ( trap_frame : & TrapFrame ) -> !;
424
+ fn DefaultHandler ( ) ;
325
425
}
326
426
327
427
unsafe {
328
- // dispatch trap to handler
329
- trap_handler ( ) ;
428
+ let cause = mcause:: read ( ) ;
429
+ if cause. is_exception ( ) {
430
+ ExceptionHandler ( & * trap_frame)
431
+ } else {
432
+ let code = cause. code ( ) ;
433
+ if code < __INTERRUPTS. len ( ) {
434
+ let h = & __INTERRUPTS[ code] ;
435
+ if h. reserved == 0 {
436
+ DefaultHandler ( ) ;
437
+ } else {
438
+ ( h. handler ) ( ) ;
439
+ }
440
+ } else {
441
+ DefaultHandler ( ) ;
442
+ }
443
+ }
444
+ }
445
+ }
330
446
331
- // mstatus, remain in M-mode after mret
332
- mstatus:: set_mpp ( mstatus:: MPP :: Machine ) ;
447
+ #[ doc( hidden) ]
448
+ #[ no_mangle]
449
+ #[ allow( unused_variables, non_snake_case) ]
450
+ pub fn DefaultExceptionHandler ( trap_frame : & TrapFrame ) -> ! {
451
+ loop {
452
+ // Prevent this from turning into a UDF instruction
453
+ // see rust-lang/rust#28728 for details
454
+ continue ;
333
455
}
334
456
}
335
457
458
+ #[ doc( hidden) ]
459
+ #[ no_mangle]
460
+ #[ allow( unused_variables, non_snake_case) ]
461
+ pub fn DefaultInterruptHandler ( ) {
462
+ loop {
463
+ // Prevent this from turning into a UDF instruction
464
+ // see rust-lang/rust#28728 for details
465
+ continue ;
466
+ }
467
+ }
468
+
469
+ /* Interrupts */
470
+ #[ doc( hidden) ]
471
+ pub enum Interrupt {
472
+ UserSoft ,
473
+ SupervisorSoft ,
474
+ MachineSoft ,
475
+ UserTimer ,
476
+ SupervisorTimer ,
477
+ MachineTimer ,
478
+ UserExternal ,
479
+ SupervisorExternal ,
480
+ MachineExternal ,
481
+ }
482
+
483
+ pub use self :: Interrupt as interrupt;
484
+
485
+ extern "C" {
486
+ fn UserSoft ( ) ;
487
+ fn SupervisorSoft ( ) ;
488
+ fn MachineSoft ( ) ;
489
+ fn UserTimer ( ) ;
490
+ fn SupervisorTimer ( ) ;
491
+ fn MachineTimer ( ) ;
492
+ fn UserExternal ( ) ;
493
+ fn SupervisorExternal ( ) ;
494
+ fn MachineExternal ( ) ;
495
+ }
496
+
497
+ #[ doc( hidden) ]
498
+ pub union Vector {
499
+ handler : unsafe extern "C" fn ( ) ,
500
+ reserved : usize ,
501
+ }
336
502
337
503
#[ doc( hidden) ]
338
504
#[ no_mangle]
339
- pub fn default_trap_handler ( ) { }
505
+ pub static __INTERRUPTS: [ Vector ; 12 ] = [
506
+ Vector { handler : UserSoft } ,
507
+ Vector { handler : SupervisorSoft } ,
508
+ Vector { reserved : 0 } ,
509
+ Vector { handler : MachineSoft } ,
510
+ Vector { handler : UserTimer } ,
511
+ Vector { handler : SupervisorTimer } ,
512
+ Vector { reserved : 0 } ,
513
+ Vector { handler : MachineTimer } ,
514
+ Vector { handler : UserExternal } ,
515
+ Vector { handler : SupervisorExternal } ,
516
+ Vector { reserved : 0 } ,
517
+ Vector { handler : MachineExternal } ,
518
+ ] ;
340
519
341
520
#[ doc( hidden) ]
342
521
#[ no_mangle]
0 commit comments