aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2021-01-21 12:49:15 +0000
committerGravatar GitHub <noreply@github.com> 2021-01-21 12:49:15 +0000
commit4bb29e702b650e7cc245d21dc33b5ce1d44b3147 (patch)
tree8ae18a27ed280be33e5f2760738db356888231c8
parent2dfbe1127f681dba9d3fc49c92fcbad0867a9987 (diff)
parent4426f26ab0aed70ae2cc433f55ee48f62d7eb46b (diff)
downloadcortex-m-4bb29e702b650e7cc245d21dc33b5ce1d44b3147.tar.gz
cortex-m-4bb29e702b650e7cc245d21dc33b5ce1d44b3147.tar.zst
cortex-m-4bb29e702b650e7cc245d21dc33b5ce1d44b3147.zip
Merge #301
301: Initialize RAM in assembly r=adamgreig a=jonas-schievink Fixes #300 Co-authored-by: Jonas Schievink <jonasschievink@gmail.com> Co-authored-by: Adam Greig <adam@adamgreig.com>
-rw-r--r--cortex-m-rt/Cargo.toml1
-rw-r--r--cortex-m-rt/asm.S105
-rw-r--r--cortex-m-rt/asm.s67
-rwxr-xr-xcortex-m-rt/assemble.sh14
-rw-r--r--cortex-m-rt/bin/thumbv6m-none-eabi.abin1490 -> 1618 bytes
-rw-r--r--cortex-m-rt/bin/thumbv7em-none-eabi.abin1434 -> 1598 bytes
-rw-r--r--cortex-m-rt/bin/thumbv7em-none-eabihf.abin1434 -> 1622 bytes
-rw-r--r--cortex-m-rt/bin/thumbv7m-none-eabi.abin1434 -> 1598 bytes
-rw-r--r--cortex-m-rt/bin/thumbv8m.base-none-eabi.abin1494 -> 1622 bytes
-rw-r--r--cortex-m-rt/bin/thumbv8m.main-none-eabi.abin1438 -> 1602 bytes
-rw-r--r--cortex-m-rt/bin/thumbv8m.main-none-eabihf.abin1438 -> 1626 bytes
-rw-r--r--cortex-m-rt/build.rs8
-rw-r--r--cortex-m-rt/link.x.in9
-rw-r--r--cortex-m-rt/src/lib.rs92
14 files changed, 133 insertions, 163 deletions
diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml
index fa5e775..bbb6254 100644
--- a/cortex-m-rt/Cargo.toml
+++ b/cortex-m-rt/Cargo.toml
@@ -17,7 +17,6 @@ autoexamples = true
links = "cortex-m-rt" # Prevent multiple versions of cortex-m-rt being linked
[dependencies]
-r0 = "1.0"
cortex-m-rt-macros = { path = "macros", version = "=0.6.11" }
# Note: Do not depend on `cortex-m` here. This crate is used for testing `cortex-m`, so we need to
# avoid pulling in multiple versions of `cortex-m`.
diff --git a/cortex-m-rt/asm.S b/cortex-m-rt/asm.S
new file mode 100644
index 0000000..6254129
--- /dev/null
+++ b/cortex-m-rt/asm.S
@@ -0,0 +1,105 @@
+ .cfi_sections .debug_frame
+
+ # Notes for function attributes:
+ # .type and .thumb_func are _both_ required, otherwise the Thumb mode bit
+ # will not be set and an invalid vector table is generated.
+ # LLD requires that section flags are set explicitly.
+
+ .section .HardFaultTrampoline, "ax"
+ .global HardFaultTrampoline
+ .type HardFaultTrampoline,%function
+ .thumb_func
+ .cfi_startproc
+ # HardFault exceptions are bounced through this trampoline which grabs the
+ # stack pointer at the time of the exception and passes it to the user's
+ # HardFault handler in r0.
+HardFaultTrampoline:
+ # Depending on the stack mode in EXC_RETURN, fetch stack pointer from
+ # PSP or MSP.
+ mov r0, lr
+ mov r1, #4
+ tst r0, r1
+ bne 0f
+ mrs r0, MSP
+ b HardFault
+0:
+ mrs r0, PSP
+ b HardFault
+ .cfi_endproc
+ .size HardFaultTrampoline, . - HardFaultTrampoline
+
+ .section .Reset, "ax"
+ .global Reset
+ .type Reset,%function
+ .thumb_func
+ .cfi_startproc
+ # Main entry point after reset. This jumps to the user __pre_init function,
+ # which cannot be called from Rust code without invoking UB, then
+ # initialises RAM. If the target has an FPU, it is enabled. Finally, jumps
+ # to the user main function.
+Reset:
+ # ARMv6-M does not initialise LR, but many tools expect it to be 0xFFFF_FFFF
+ # when reaching the first call frame, so we set it at startup.
+ # ARMv7-M and above initialise LR to 0xFFFF_FFFF at reset.
+ ldr r4,=0xffffffff
+ mov lr,r4
+
+ # Run user pre-init code, which must be executed immediately after startup,
+ # before the potentially time-consuming memory initialisation takes place.
+ # Example use cases include disabling default watchdogs or enabling RAM.
+ bl __pre_init
+
+ # Restore LR after calling __pre_init (r4 is preserved by subroutines).
+ mov lr,r4
+
+ # Initialise .bss memory. `__sbss` and `__ebss` come from the linker script.
+ ldr r0,=__sbss
+ ldr r1,=__ebss
+ mov r2,#0
+0:
+ cmp r1, r0
+ beq 1f
+ stm r0!, {r2}
+ b 0b
+1:
+
+ # Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the
+ # linker script. Copy from r2 into r0 until r0 reaches r1.
+ ldr r0,=__sdata
+ ldr r1,=__edata
+ ldr r2,=__sidata
+2:
+ cmp r1, r0
+ beq 3f
+ # load 1 word from r2 to r3, inc r2
+ ldm r2!, {r3}
+ # store 1 word from r3 to r0, inc r0
+ stm r0!, {r3}
+ b 2b
+3:
+
+#ifdef HAS_FPU
+ # Conditionally enable the FPU.
+ # Address of SCB.CPACR.
+ ldr r0, =0xE000ED88
+ # Enable access to CP10 and CP11 from both privileged and unprivileged mode.
+ ldr r1, =(0b1111 << 20)
+ # RMW.
+ ldr r2, [r0]
+ orr r2, r2, r1
+ str r2, [r0]
+ # Barrier is required on some processors.
+ dsb
+ isb
+#endif
+
+4:
+ # Jump to user main function. We use bl for the extended range, but the
+ # user main function may not return.
+ bl main
+
+ # Trap on return.
+ udf
+
+ .cfi_endproc
+ .size Reset, . - Reset
diff --git a/cortex-m-rt/asm.s b/cortex-m-rt/asm.s
deleted file mode 100644
index 58ed274..0000000
--- a/cortex-m-rt/asm.s
+++ /dev/null
@@ -1,67 +0,0 @@
- .cfi_sections .debug_frame
-
- # LLD requires that the section flags are explicitly set here
- .section .HardFaultTrampoline, "ax"
- .global HardFaultTrampoline
- # .type and .thumb_func are both required; otherwise its Thumb bit does not
- # get set and an invalid vector table is generated
- .type HardFaultTrampoline,%function
- .thumb_func
- .cfi_startproc
-HardFaultTrampoline:
- # depending on the stack mode in EXC_RETURN, fetch stack pointer from
- # PSP or MSP
- mov r0, lr
- mov r1, #4
- tst r0, r1
- bne 0f
- mrs r0, MSP
- b HardFault
-0:
- mrs r0, PSP
- b HardFault
- .cfi_endproc
- .size HardFaultTrampoline, . - HardFaultTrampoline
-
- .section .text.FpuTrampoline, "ax"
- .global FpuTrampoline
- # .type and .thumb_func are both required; otherwise its Thumb bit does not
- # get set and an invalid vector table is generated
- .type FpuTrampoline,%function
- .thumb_func
- .cfi_startproc
- # This enables the FPU and jumps to the main function.
-FpuTrampoline:
- # Address of SCB.CPACR.
- ldr r0, =0xE000ED88
- # Enable access to CP10 and CP11 from both privileged and unprivileged mode.
- ldr r1, =(0b1111 << 20)
- # RMW.
- ldr r2, [r0]
- orr r2, r2, r1
- str r2, [r0]
- # Barrier is required on some processors.
- dsb
- isb
- # Hand execution over to `main`.
- bl main
- # Note: `main` must not return. `bl` is used only because it has a wider range than `b`.
- .cfi_endproc
- .size FpuTrampoline, . - FpuTrampoline
-
- # ARMv6-M leaves LR in an unknown state on Reset
- # this trampoline sets LR before it's pushed onto the stack by Reset
- .section .PreResetTrampoline, "ax"
- .global PreResetTrampoline
- # .type and .thumb_func are both required; otherwise its Thumb bit does not
- # get set and an invalid vector table is generated
- .type PreResetTrampoline,%function
- .thumb_func
- .cfi_startproc
-PreResetTrampoline:
- # set LR to the initial value used by the ARMv7-M (0xFFFF_FFFF)
- ldr r0,=0xffffffff
- mov lr,r0
- b Reset
- .cfi_endproc
- .size PreResetTrampoline, . - PreResetTrampoline
diff --git a/cortex-m-rt/assemble.sh b/cortex-m-rt/assemble.sh
index cdb3205..b914fed 100755
--- a/cortex-m-rt/assemble.sh
+++ b/cortex-m-rt/assemble.sh
@@ -9,21 +9,25 @@ crate=cortex-m-rt
# remove existing blobs because otherwise this will append object files to the old blobs
rm -f bin/*.a
-arm-none-eabi-as -march=armv6s-m asm.s -o bin/$crate.o
+arm-none-eabi-gcc -c -march=armv6s-m asm.S -o bin/$crate.o
ar crs bin/thumbv6m-none-eabi.a bin/$crate.o
-arm-none-eabi-as -march=armv7-m asm.s -o bin/$crate.o
+arm-none-eabi-gcc -c -march=armv7-m asm.S -o bin/$crate.o
ar crs bin/thumbv7m-none-eabi.a bin/$crate.o
-arm-none-eabi-as -march=armv7e-m asm.s -o bin/$crate.o
+arm-none-eabi-gcc -c -march=armv7e-m asm.S -o bin/$crate.o
ar crs bin/thumbv7em-none-eabi.a bin/$crate.o
+
+arm-none-eabi-gcc -c -march=armv7e-m asm.S -DHAS_FPU -o bin/$crate.o
ar crs bin/thumbv7em-none-eabihf.a bin/$crate.o
-arm-none-eabi-as -march=armv8-m.base asm.s -o bin/$crate.o
+arm-none-eabi-gcc -c -march=armv8-m.base asm.S -o bin/$crate.o
ar crs bin/thumbv8m.base-none-eabi.a bin/$crate.o
-arm-none-eabi-as -march=armv8-m.main asm.s -o bin/$crate.o
+arm-none-eabi-gcc -c -march=armv8-m.main asm.S -o bin/$crate.o
ar crs bin/thumbv8m.main-none-eabi.a bin/$crate.o
+
+arm-none-eabi-gcc -c -march=armv8-m.main -DHAS_FPU asm.S -o bin/$crate.o
ar crs bin/thumbv8m.main-none-eabihf.a bin/$crate.o
rm bin/$crate.o
diff --git a/cortex-m-rt/bin/thumbv6m-none-eabi.a b/cortex-m-rt/bin/thumbv6m-none-eabi.a
index 65684da..3ac0777 100644
--- a/cortex-m-rt/bin/thumbv6m-none-eabi.a
+++ b/cortex-m-rt/bin/thumbv6m-none-eabi.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv7em-none-eabi.a b/cortex-m-rt/bin/thumbv7em-none-eabi.a
index c4e1f47..d38ee46 100644
--- a/cortex-m-rt/bin/thumbv7em-none-eabi.a
+++ b/cortex-m-rt/bin/thumbv7em-none-eabi.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv7em-none-eabihf.a b/cortex-m-rt/bin/thumbv7em-none-eabihf.a
index c4e1f47..a782dce 100644
--- a/cortex-m-rt/bin/thumbv7em-none-eabihf.a
+++ b/cortex-m-rt/bin/thumbv7em-none-eabihf.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv7m-none-eabi.a b/cortex-m-rt/bin/thumbv7m-none-eabi.a
index ed96942..038af9f 100644
--- a/cortex-m-rt/bin/thumbv7m-none-eabi.a
+++ b/cortex-m-rt/bin/thumbv7m-none-eabi.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv8m.base-none-eabi.a b/cortex-m-rt/bin/thumbv8m.base-none-eabi.a
index f1c7734..ad383aa 100644
--- a/cortex-m-rt/bin/thumbv8m.base-none-eabi.a
+++ b/cortex-m-rt/bin/thumbv8m.base-none-eabi.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv8m.main-none-eabi.a b/cortex-m-rt/bin/thumbv8m.main-none-eabi.a
index cb216dc..ef6e77a 100644
--- a/cortex-m-rt/bin/thumbv8m.main-none-eabi.a
+++ b/cortex-m-rt/bin/thumbv8m.main-none-eabi.a
Binary files differ
diff --git a/cortex-m-rt/bin/thumbv8m.main-none-eabihf.a b/cortex-m-rt/bin/thumbv8m.main-none-eabihf.a
index cb216dc..44380fb 100644
--- a/cortex-m-rt/bin/thumbv8m.main-none-eabihf.a
+++ b/cortex-m-rt/bin/thumbv8m.main-none-eabihf.a
Binary files differ
diff --git a/cortex-m-rt/build.rs b/cortex-m-rt/build.rs
index 20f32b8..6758d9e 100644
--- a/cortex-m-rt/build.rs
+++ b/cortex-m-rt/build.rs
@@ -18,8 +18,6 @@ fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
- has_fpu(&target);
-
if target.starts_with("thumbv") {
fs::copy(
format!("bin/{}.a", target),
@@ -92,9 +90,3 @@ handlers.");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=link.x.in");
}
-
-fn has_fpu(target: &str) {
- if target.ends_with("eabihf") {
- println!("cargo:rustc-cfg=has_fpu");
- }
-}
diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in
index f1a921d..78fa825 100644
--- a/cortex-m-rt/link.x.in
+++ b/cortex-m-rt/link.x.in
@@ -23,8 +23,9 @@
INCLUDE memory.x
/* # Entry point = reset vector */
+EXTERN(__RESET_VECTOR);
+EXTERN(Reset);
ENTRY(Reset);
-EXTERN(__RESET_VECTOR); /* depends on the `Reset` symbol */
/* # Exception vectors */
/* This is effectively weak aliasing at the linker level */
@@ -85,13 +86,15 @@ SECTIONS
/* ### .text */
.text _stext :
{
- /* place these 2 close to each other or the `b` instruction will fail to link */
- *(.PreResetTrampoline);
*(.Reset);
*(.text .text.*);
+
+ /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`,
+ so must be placed close to it. */
*(.HardFaultTrampoline);
*(.HardFault.*);
+
. = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */
} > FLASH
. = ALIGN(4); /* Ensure __etext is aligned if something unaligned is inserted after .text */
diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs
index ab4bc3f..e5e290d 100644
--- a/cortex-m-rt/src/lib.rs
+++ b/cortex-m-rt/src/lib.rs
@@ -192,11 +192,9 @@
//!
//! One will always find the following (unmangled) symbols in `cortex-m-rt` applications:
//!
-//! - `Reset`. This is the reset handler. The microcontroller will executed this function upon
+//! - `Reset`. This is the reset handler. The microcontroller will execute this function upon
//! booting. This function will call the user program entry point (cf. [`#[entry]`][attr-entry])
-//! using the `main` symbol so you may also find that symbol in your program; if you do, `main`
-//! will contain your application code. Some other times `main` gets inlined into `Reset` so you
-//! won't find it.
+//! using the `main` symbol so you will also find that symbol in your program.
//!
//! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn
//! DefaultHandler(..` this will be an infinite loop.
@@ -212,8 +210,8 @@
//! the initial value of the stack pointer; this is where the stack will be located -- the stack
//! grows downwards towards smaller addresses.
//!
-//! - `__RESET_VECTOR`. This is the reset vector, a pointer into the `Reset` handler. This vector is
-//! located in the `.vector_table` section after `__STACK_START`.
+//! - `__RESET_VECTOR`. This is the reset vector, a pointer to the `Reset` function. This vector
+//! is located in the `.vector_table` section after `__STACK_START`.
//!
//! - `__EXCEPTIONS`. This is the core exceptions portion of the vector table; it's an array of 14
//! exception vectors, which includes exceptions like `HardFault` and `SysTick`. This array is
@@ -226,19 +224,11 @@
//!
//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty
//! function. The function called can be changed by applying the [`#[pre_init]`][attr-pre_init]
-//! attribute to a function. The empty function is not optimized out by default, but if an empty
-//! function is passed to [`#[pre_init]`][attr-pre_init] the function call will be optimized out.
+//! attribute to a function.
//!
//! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or
//! `SVCall`, in the output of `objdump`,
//!
-//! If you are targeting the `thumbv7em-none-eabihf` target you'll also see a `ResetTrampoline`
-//! symbol in the output. To avoid the compiler placing FPU instructions before the FPU has been
-//! enabled (cf. `vpush`) `Reset` calls the function `ResetTrampoline` which is marked as
-//! `#[inline(never)]` and `ResetTrampoline` calls `main`. The compiler is free to inline `main`
-//! into `ResetTrampoline` but it can't inline `ResetTrampoline` into `Reset` -- the FPU is enabled
-//! in `Reset`.
-//!
//! # Advanced usage
//!
//! ## Setting the program entry point
@@ -248,9 +238,9 @@
//! guarantees.
//!
//! The `Reset` handler will call a symbol named `main` (unmangled) *after* initializing `.bss` and
-//! `.data`, and enabling the FPU (if the target is `thumbv7em-none-eabihf`). A function with the
-//! `entry` attribute will be set to have the export name "`main`"; in addition, its mutable
-//! statics are turned into safe mutable references (see [`#[entry]`][attr-entry] for details).
+//! `.data`, and enabling the FPU (if the target has an FPU). A function with the `entry` attribute
+//! will be set to have the export name "`main`"; in addition, its mutable statics are turned into
+//! safe mutable references (see [`#[entry]`][attr-entry] for details).
//!
//! The unmangled `main` symbol must have signature `extern "C" fn() -> !` or its invocation from
//! `Reset` will result in undefined behavior.
@@ -411,7 +401,7 @@
//! *(.ccmram .ccmram.*);
//! . = ALIGN(4);
//! } > CCMRAM
-//! } INSERT AFTER .bss;
+//! }
//! ```
//!
//! You can then use something like this to place a variable into this specific section of memory:
@@ -438,7 +428,6 @@
#![no_std]
extern crate cortex_m_rt_macros as macros;
-extern crate r0;
use core::fmt;
use core::sync::atomic::{self, Ordering};
@@ -701,8 +690,8 @@ pub use macros::exception;
///
/// # Safety
///
-/// The function will be called before static variables are initialized. Any access of static
-/// variables will result in undefined behavior.
+/// The function will be called before memory is initialized, as soon as possible after reset. Any
+/// access of memory, including any static variables, will result in undefined behavior.
///
/// **Warning**: Due to [rvalue static promotion][rfc1414] static variables may be accessed whenever
/// taking a reference to a constant. This means that even trivial expressions such as `&1` in the
@@ -919,66 +908,12 @@ pub fn heap_start() -> *mut u32 {
unsafe { &mut __sheap }
}
-/* Entry point */
+// Entry point is Reset.
#[doc(hidden)]
#[link_section = ".vector_table.reset_vector"]
#[no_mangle]
-#[cfg(not(armv6m))]
pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;
-#[doc(hidden)]
-#[link_section = ".vector_table.reset_vector"]
-#[no_mangle]
-#[cfg(armv6m)]
-pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = PreResetTrampoline;
-
-#[doc(hidden)]
-#[link_section = ".Reset"]
-#[no_mangle]
-pub unsafe extern "C" fn Reset() -> ! {
- extern "C" {
-
- // These symbols come from `link.x`
- static mut __sbss: u32;
- static mut __ebss: u32;
-
- static mut __sdata: u32;
- static mut __edata: u32;
- static __sidata: u32;
- }
-
- extern "Rust" {
- // This symbol will be provided by the user via `#[pre_init]`
- fn __pre_init();
- }
-
- __pre_init();
-
- // Initialize RAM
- r0::zero_bss(&mut __sbss, &mut __ebss);
- r0::init_data(&mut __sdata, &mut __edata, &__sidata);
-
- #[allow(clippy::match_single_binding)]
- match () {
- #[cfg(not(has_fpu))]
- () => {
- extern "C" {
- // This symbol will be provided by the user via `#[entry]`
- fn main() -> !;
- }
- main()
- }
- #[cfg(has_fpu)]
- () => {
- extern "C" {
- fn FpuTrampoline() -> !;
- }
-
- FpuTrampoline()
- }
- }
-}
-
#[allow(unused_variables)]
#[doc(hidden)]
#[link_section = ".HardFault.default"]
@@ -1038,8 +973,7 @@ pub enum Exception {
pub use self::Exception as exception;
extern "C" {
- #[cfg(armv6m)]
- fn PreResetTrampoline() -> !;
+ fn Reset() -> !;
fn NonMaskableInt();