359
359
//! If the `v-trap` feature is enabled, the trap vector is set to `_vector_table`
360
360
//! in vectored mode. Users can override this function by defining their own `_setup_interrupts`.
361
361
//!
362
+ //! This function can be redefined in the following way:
363
+ //!
364
+ //! ``` no_run
365
+ //! #[export_name = "_setup_interrupts"]
366
+ //! pub fn setup_interrupts() {
367
+ //! // ...
368
+ //! }
369
+ //! ```
370
+ //!
371
+ //! ## `hal_main`
372
+ //!
373
+ //! Internally, `riscv-rt` does not jump to the `main` function created by the user using the
374
+ //! [`#[entry]`][attr-entry] attribute. Instead, it jumps to the `hal_main` function.
375
+ //! The linker will map `hal_main` to `main` if the prior is not defined, which is the typical case.
376
+ //! However, the `hal_main` function allows HALs to inject additional code before jumping to the
377
+ //! user's `main` function. This might be useful for certain HALs that need to perform additional
378
+ //! configuration before the main function is executed.
379
+ //!
362
380
//! # Attributes
363
381
//!
364
382
//! ## Core exception handlers
@@ -552,10 +570,16 @@ pub mod exceptions;
552
570
pub mod interrupts;
553
571
554
572
#[ cfg( feature = "s-mode" ) ]
555
- use riscv:: register:: scause as xcause;
573
+ use riscv:: register:: {
574
+ scause as xcause,
575
+ stvec:: { self as xtvec, Stvec as Xtvec , TrapMode } ,
576
+ } ;
556
577
557
578
#[ cfg( not( feature = "s-mode" ) ) ]
558
- use riscv:: register:: mcause as xcause;
579
+ use riscv:: register:: {
580
+ mcause as xcause,
581
+ mtvec:: { self as xtvec, Mtvec as Xtvec , TrapMode } ,
582
+ } ;
559
583
560
584
pub use riscv_pac:: * ;
561
585
pub use riscv_rt_macros:: { core_interrupt, entry, exception, external_interrupt} ;
@@ -571,6 +595,60 @@ pub use riscv_rt_macros::pre_init;
571
595
#[ doc( hidden) ]
572
596
pub static __ONCE__: ( ) = ( ) ;
573
597
598
+ /// Rust entry point (_start_rust)
599
+ ///
600
+ /// Configures interrupts and calls main. This function never returns.
601
+ ///
602
+ /// # Safety
603
+ ///
604
+ /// This function should not be called directly by the user, and should instead
605
+ /// be invoked by the runtime implicitly.
606
+ #[ cfg_attr(
607
+ any( target_arch = "riscv32" , target_arch = "riscv64" ) ,
608
+ link_section = ".init.rust"
609
+ ) ]
610
+ #[ export_name = "_start_rust" ]
611
+ pub unsafe extern "C" fn start_rust ( a0 : usize , a1 : usize , a2 : usize ) -> ! {
612
+ extern "Rust" {
613
+ fn _setup_interrupts ( ) ;
614
+ fn hal_main ( a0 : usize , a1 : usize , a2 : usize ) -> !;
615
+ }
616
+
617
+ _setup_interrupts ( ) ;
618
+ hal_main ( a0, a1, a2) ;
619
+ }
620
+
621
+ /// Default implementation of `_setup_interrupts`.
622
+ ///
623
+ /// In direct mode (i.e., `v-trap` feature disabled), it sets the trap vector to `_start_trap`.
624
+ /// In vectored mode (i.e., `v-trap` feature enabled), it sets the trap vector to `_vector_table`.
625
+ ///
626
+ /// # Note
627
+ ///
628
+ /// Users can override this function by defining their own `_setup_interrupts` function.
629
+ ///
630
+ /// # Safety
631
+ ///
632
+ /// This function should not be called directly by the user, and should instead
633
+ /// be invoked by the runtime implicitly. It is expected to be called before the main function.
634
+ #[ export_name = "_default_setup_interrupts" ]
635
+ pub unsafe extern "Rust" fn setup_interrupts ( ) {
636
+ extern "C" {
637
+ #[ cfg( not( feature = "v-trap" ) ) ]
638
+ fn _start_trap ( ) ;
639
+ #[ cfg( feature = "v-trap" ) ]
640
+ fn _vector_table ( ) ;
641
+ }
642
+
643
+ let xtvec_val = match ( ) {
644
+ #[ cfg( not( feature = "v-trap" ) ) ]
645
+ _ => Xtvec :: new ( _start_trap as usize , TrapMode :: Direct ) ,
646
+ #[ cfg( feature = "v-trap" ) ]
647
+ _ => Xtvec :: new ( _vector_table as usize , TrapMode :: Vectored ) ,
648
+ } ;
649
+ xtvec:: write ( xtvec_val) ;
650
+ }
651
+
574
652
/// Registers saved in trap handler
575
653
#[ repr( C ) ]
576
654
#[ derive( Debug ) ]
0 commit comments