4
0
Эх сурвалжийг харах

use #[no_main] and the entry! macro to specify the main function

Matches cortex-m-rt. See:

https://github.com/rust-embedded/cortex-m-rt/pull/69
https://github.com/rust-embedded/cortex-m-rt/pull/78
Dan Callaghan 6 жил өмнө
parent
commit
3270dd813f
1 өөрчлөгдсөн 35 нэмэгдсэн , 12 устгасан
  1. 35 12
      riscv-rt/src/lib.rs

+ 35 - 12
riscv-rt/src/lib.rs

@@ -55,10 +55,15 @@
 //!
 //! ``` ignore,no_run
 //! #![no_std]
+//! #![no_main]
 //!
+//! #[macro_use(entry)]
 //! extern crate riscv_rt;
 //!
-//! fn main() {
+//! // use `main` as the entry point of this application
+//! entry!(main);
+//!
+//! fn main() -> ! {
 //!     // do something here
 //! }
 //! ```
@@ -174,13 +179,9 @@ extern crate r0;
 
 mod lang_items;
 
-use riscv::asm;
 use riscv::register::{mcause, mstatus};
 
 extern "C" {
-    // NOTE `rustc` forces this signature on us. See `src/lang_items.rs`
-    fn main() -> isize;
-
     // Boundaries of the .bss section
     static mut _ebss: u32;
     static mut _sbss: u32;
@@ -234,6 +235,11 @@ _start:
 #[link_section = ".init.rust"]
 #[export_name = "_start_rust"]
 pub extern "C" fn start_rust() -> ! {
+    extern "C" {
+        // This symbol will be provided by the user via the `entry!` macro
+        fn main() -> !;
+    }
+
     unsafe {
         r0::zero_bss(&mut _sbss, &mut _ebss);
         r0::init_data(&mut _sdata, &mut _edata, &_sidata);
@@ -252,17 +258,34 @@ pub extern "C" fn start_rust() -> ! {
              : "volatile");
     }
 
-    // Neither `argc` or `argv` make sense in bare metal context so we
-    // just stub them
     unsafe {
         main();
     }
+}
 
-    // If `main` returns, then we go into "reactive" mode and simply attend
-    // interrupts as they occur.
-    loop {
-        asm::wfi();
-    }
+
+/// Macro to define the entry point of the program
+///
+/// **NOTE** This macro must be invoked once and must be invoked from an accessible module, ideally
+/// from the root of the crate.
+///
+/// Usage: `entry!(path::to::entry::point)`
+///
+/// The specified function will be called by the reset handler *after* RAM has been initialized.
+///
+/// The signature of the specified function must be `fn() -> !` (never ending function).
+#[macro_export]
+macro_rules! entry {
+    ($path:expr) => {
+        #[inline(never)]
+        #[export_name = "main"]
+        pub extern "C" fn __impl_main() -> ! {
+            // validate the signature of the program entry point
+            let f: fn() -> ! = $path;
+
+            f()
+        }
+    };
 }