aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <jorge@japaric.io> 2018-04-09 23:28:31 +0200
committerGravatar GitHub <noreply@github.com> 2018-04-09 23:28:31 +0200
commit5452a8981292d792acacaf71c9547e60ddd0912e (patch)
tree2856209777d94460fd59c174147441754c6f7c74
parent718da40446e51ace1f3d6433203ecda6dfa4ec20 (diff)
parent7521c609b353a97cb0c7e6f8dc3a1b8833ea3b81 (diff)
downloadcortex-m-5452a8981292d792acacaf71c9547e60ddd0912e.tar.gz
cortex-m-5452a8981292d792acacaf71c9547e60ddd0912e.tar.zst
cortex-m-5452a8981292d792acacaf71c9547e60ddd0912e.zip
Merge pull request #64 from japaric/v4
v0.4.0: with LLD support
-rw-r--r--cortex-m-rt/CHANGELOG.md31
-rw-r--r--cortex-m-rt/Cargo.toml12
-rw-r--r--cortex-m-rt/build.rs19
-rw-r--r--cortex-m-rt/link.x48
-rw-r--r--cortex-m-rt/src/lang_items.rs18
-rw-r--r--cortex-m-rt/src/lib.rs228
6 files changed, 47 insertions, 309 deletions
diff --git a/cortex-m-rt/CHANGELOG.md b/cortex-m-rt/CHANGELOG.md
index f9e2abd..c2a7045 100644
--- a/cortex-m-rt/CHANGELOG.md
+++ b/cortex-m-rt/CHANGELOG.md
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
+## [v0.4.0] - 2018-04-09
+
+### Added
+
+- LLD support. The linker script provided by this crate has been tweaked to support both LLD and GNU
+ LD. To use LLD as a linker change `.cargo/config` to look like this:
+
+``` diff
+ [target.thumbv7m-none-eabi]
+ rustflags = [
+ "-C", "link-arg=-Tlink.x",
+- "-C", "linker=arm-none-eabi-ld",
+- "-Z", "linker-flavor=ld",
++ "-C", "linker=lld",
++ "-Z", "linker-flavor=ld.lld",
+ ]
+```
+
+### Removed
+
+- [breaking-change] Stack overflow protection has been removed. Unfortunately, supporting this
+ feature produces totally wrong `arm-none-eabi-size` reports when LLD is used to link the
+ program. If you need the stack overflow protection feature you can continue to use version
+ v0.3.13+.
+
+- [breaking-change] The "abort-on-panic" Cargo feature, which provided a `panic_fmt` implementation,
+ has been removed. If you were using this feature you can instead use a [panic implementation
+ crate][panic-impl].
+
+[panic-impl]: https://crates.io/keywords/panic-impl
+
## [v0.3.15] - 2018-04-08
### Fixed
diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml
index 1b61917..cd31b2d 100644
--- a/cortex-m-rt/Cargo.toml
+++ b/cortex-m-rt/Cargo.toml
@@ -7,16 +7,8 @@ keywords = ["arm", "cortex-m", "runtime", "startup"]
license = "MIT OR Apache-2.0"
name = "cortex-m-rt"
repository = "https://github.com/japaric/cortex-m-rt"
-version = "0.3.15"
+version = "0.4.0"
[dependencies]
cortex-m = "0.3.0"
-r0 = "0.2.1"
-
-[features]
-# provides a panic_fmt implementation that calls the abort instruction (`udf 0xfe`)
-abort-on-panic = []
-
-[build-dependencies]
-rustc_version = "0.2.1"
-chrono = "0.4.0"
+r0 = "0.2.1" \ No newline at end of file
diff --git a/cortex-m-rt/build.rs b/cortex-m-rt/build.rs
index c1028c4..1d0160c 100644
--- a/cortex-m-rt/build.rs
+++ b/cortex-m-rt/build.rs
@@ -1,28 +1,9 @@
-extern crate chrono;
-extern crate rustc_version;
-
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
-use chrono::NaiveDate;
-
fn main() {
- let meta = rustc_version::version_meta().unwrap();
- let commit_date = meta.commit_date.unwrap().parse::<NaiveDate>().unwrap();
- if meta.channel == rustc_version::Channel::Dev
- || commit_date > NaiveDate::from_ymd(2017, 12, 26)
- {
- println!("cargo:rustc-cfg=has_termination_lang")
- }
-
- // newest nightlies don't need 'extern crate compiler_builtins'
- if commit_date < NaiveDate::from_ymd(2018, 04, 07)
- {
- println!("cargo:rustc-cfg=needs_cb")
- }
-
let target = env::var("TARGET").unwrap();
has_fpu(&target);
diff --git a/cortex-m-rt/link.x b/cortex-m-rt/link.x
index 4eaa8be..7e398de 100644
--- a/cortex-m-rt/link.x
+++ b/cortex-m-rt/link.x
@@ -48,27 +48,16 @@ SECTIONS
. = ALIGN(4);
} > FLASH
- /* limits of the .stack region */
- _estack = _stack_start;
- /* HACK the `true` case indicates that two RAM regions are being used and
- /* that the stack was placed in the second region. In that case we don't know
- /* the size of the second RAM region, or its start address, so we just assume
- /* its zero sized */
- _sstack = _stack_start < ORIGIN(RAM)? _stack_start : ORIGIN(RAM);
-
- /* fictitious region that represents the memory available for the stack */
- .stack _sstack (INFO) : ALIGN(4)
- {
- . += (_estack - _sstack);
- }
-
PROVIDE(_sbss = ORIGIN(RAM));
.bss _sbss : ALIGN(4)
{
*(.bss .bss.*);
. = ALIGN(4);
_ebss = .;
- } > RAM
+ } > RAM AT > FLASH
+ /* NOTE(AT > FLASH) without this LLD v6 produces a binary that crashes OpenOCD whereas LLD v7
+ emits a ".rodata and .bss sections overlap" error ... This hacky workaround doesn't increase
+ the binary size AFAICT */
.data : ALIGN(4)
{
@@ -79,16 +68,8 @@ SECTIONS
_edata = .;
} > RAM AT > FLASH
- PROVIDE(_heap_size = 0);
-
+ /* The heap starts right after the .bss + .data section ends */
_sheap = _edata;
- _eheap = _sheap + _heap_size;
-
- /* fictitious region that represents the memory available for the heap */
- .heap _sheap (INFO) : ALIGN(4)
- {
- . += _heap_size;
- }
/* fake output .got section */
/* Dynamic relocations are unsupported. This section is only used to detect
@@ -101,26 +82,9 @@ SECTIONS
_egot = .;
} > RAM AT > FLASH
- /* The heap starts right after the .bss + .data section ends */
- _sheap = _edata;
-
- /* Due to an unfortunate combination of legacy concerns,
- toolchain drawbacks, and insufficient attention to detail,
- rustc has no choice but to mark .debug_gdb_scripts as allocatable.
- We really do not want to upload it to our target, so we
- remove the allocatable bit. Unfortunately, it appears
- that the only way to do this in a linker script is
- the extremely obscure "INFO" output section type specifier. */
- /* a rustc hack will force the program to read the first byte of this section,
- so we'll set the (fake) start address of this section to something we're
- sure can be read at runtime: the start of the .text section */
- .debug_gdb_scripts _stext (INFO) : {
- KEEP(*(.debug_gdb_scripts))
- }
-
/DISCARD/ :
{
- *(.ARM.exidx.*)
+ *(.ARM.exidx.*);
}
}
diff --git a/cortex-m-rt/src/lang_items.rs b/cortex-m-rt/src/lang_items.rs
index f3750a0..571a8a5 100644
--- a/cortex-m-rt/src/lang_items.rs
+++ b/cortex-m-rt/src/lang_items.rs
@@ -1,10 +1,3 @@
-/// Default panic handler
-#[cfg(feature = "abort-on-panic")]
-#[lang = "panic_fmt"]
-unsafe extern "C" fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u32, _: u32) -> ! {
- ::core::intrinsics::abort()
-}
-
// Lang item required to make the normal `main` work in applications
//
// This is how the `start` lang item works:
@@ -24,7 +17,6 @@ unsafe extern "C" fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u3
// The final piece is that the entry point of our program, the reset handler,
// has to call `rustc_main`. That's covered by the `reset_handler` function in
// root of this crate.
-#[cfg(has_termination_lang)]
#[lang = "start"]
extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
@@ -35,21 +27,11 @@ where
0
}
-#[cfg(not(has_termination_lang))]
-#[lang = "start"]
-extern "C" fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize {
- main();
-
- 0
-}
-
#[lang = "termination"]
-#[cfg(has_termination_lang)]
pub trait Termination {
fn report(self) -> i32;
}
-#[cfg(has_termination_lang)]
impl Termination for () {
fn report(self) -> i32 {
0
diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs
index 06ee551..7028cce 100644
--- a/cortex-m-rt/src/lib.rs
+++ b/cortex-m-rt/src/lib.rs
@@ -8,11 +8,6 @@
//!
//! - Before main initialization of the FPU (for targets that have a FPU).
//!
-//! - A `panic_fmt` implementation that just calls abort that you can opt into
-//! through the "abort-on-panic" Cargo feature. If you don't use this feature
-//! you'll have to provide the `panic_fmt` lang item yourself. Documentation
-//! [here](https://doc.rust-lang.org/unstable-book/language-features/lang-items.html)
-//!
//! - A minimal `start` lang item to support the standard `fn main()`
//! interface. (The processor goes to sleep (`loop { asm!("wfi") }`) after
//! returning from `main`)
@@ -31,8 +26,6 @@
//!
//! - A `_sheap` symbol at whose address you can locate a heap.
//!
-//! - Zero cost stack overflow protection when using the `cortex-m-rt-ld` linker.
-//!
//! # Example
//!
//! Creating a new bare metal project. (I recommend you use the
@@ -43,19 +36,10 @@
//! $ cargo new --bin app && cd $_
//!
//! $ # add this crate as a dependency
-//! $ $EDITOR Cargo.toml && tail $_
-//! [dependencies.cortex-m-rt]
-//! features = ["abort-on-panic"]
-//! version = "0.3.0"
+//! $ cargo add cortex-m-rt --vers 0.4.0
//!
-//! $ # tell Xargo which standard crates to build
-//! $ $EDITOR Xargo.toml && cat $_
-//! [dependencies.core]
-//! stage = 0
-//!
-//! [dependencies.compiler_builtins]
-//! features = ["mem"]
-//! stage = 1
+//! $ # select a panicking behavior (look for the panic-impl keyword on crates.io)
+//! $ cargo add panic-abort
//!
//! $ # memory layout of the device
//! $ $EDITOR memory.x && cat $_
@@ -74,6 +58,7 @@
//! #![no_std]
//!
//! extern crate cortex_m_rt;
+//! extern crate panic_abort; // panicking behavior
//!
//! fn main() {
//! // do something here
@@ -91,9 +76,9 @@
//! ```
//!
//! ``` text
-//! $ cargo install xargo
+//! $ rustup target add thumbv7m-none-eabi
//!
-//! $ xargo rustc --target thumbv7m-none-eabi -- \
+//! $ cargo rustc --target thumbv7m-none-eabi -- \
//! -C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld
//!
//! $ arm-none-eabi-objdump -Cd $(find target -name app) | head
@@ -112,195 +97,10 @@
//! .vector_table 0x400 0x8000000
//! .text 0x24a 0x8000400
//! .rodata 0x0 0x800064c
-//! .stack 0x2000 0x20000000
//! .bss 0x0 0x20000000
//! .data 0x0 0x20000000
//! ```
//!
-//! ## Zero cost stack overflow protection
-//!
-//! Consider the following variation of the previous program:
-//!
-//! ``` ignore
-//! extern crate cortex_m_rt;
-//!
-//! const N: usize = 256;
-//! static mut XS: [u32; N] = [0; N];
-//!
-//! fn main() {
-//! #[inline(never)]
-//! fn fib(n: u32) -> u32 {
-//! unsafe { assert!(XS.iter().all(|x| *x == 0)) }
-//!
-//! if n < 2 {
-//! 1
-//! } else {
-//! fib(n - 1) + fib(n - 2)
-//! }
-//! }
-//!
-//! let x = fib(400);
-//! unsafe { *XS.iter_mut().first().unwrap() = x }
-//! }
-//! ```
-//!
-//! This program allocates a 1KB array in `.bss`, recursively computes the 400th fibonacci number
-//! and stores the result in the head of the array. This program will hit a stack overflow at
-//! runtime because there's not enough memory to recursively call the `fib` function so many times.
-//!
-//! If you inspect the program using GDB you'll see that the assertion failed after `fib` was nested
-//! around 300 times.
-//!
-//! ``` console
-//! > continue
-//! Program received signal SIGTRAP, Trace/breakpoint trap.
-//!
-//! > backtrace
-//! #0 0x08000516 in cortex_m_rt::default_handler ()
-//! #1 <signal handler called>
-//! #2 0x0800050a in rust_begin_unwind ()
-//! #3 0x08000586 in core::panicking::panic_fmt ()
-//! #4 0x0800055c in core::panicking::panic ()
-//! #5 0x080004f6 in app::main::fib ()
-//! #6 0x080004a0 in app::main::fib ()
-//! (..)
-//! #301 0x080004a0 in app::main::fib ()
-//! #302 0x080004a0 in app::main::fib ()
-//! #303 0x08000472 in app::main ()
-//! #304 0x08000512 in cortex_m_rt::lang_items::start ()
-//! #305 0x08000460 in cortex_m_rt::reset_handler ()
-//! ```
-//!
-//! What this means is that the stack grew so much that it crashed into the `.bss` section and
-//! overwrote the memory in there. Continuing the GDB session you can confirm that the `XS` variable
-//! has been modified:
-//!
-//! ``` console
-//! > x/4 0x20000000 # start of .bss
-//! 0x20000000 <app::XS>: 0x00000000 0x00000000 0x00000000 0x00000000
-//!
-//! > x/4 0x200003f0 # end of .bss
-//! 0x200003f0 <app::XS+1008>: 0x20000400 0x080004f5 0x00000000 0x00000001
-//! ```
-//!
-//! The problem is that the stack is growing towards the `.bss` section and both sections overlap as
-//! shown below:
-//!
-//! ``` console
-//! $ arm-none-eabi-size -Ax $(find target -name app)
-//! section size addr
-//! .vector_table 0x400 0x8000000
-//! .text 0x186 0x8000400
-//! .rodata 0x50 0x8000590
-//! .stack 0x2000 0x20000000
-//! .bss 0x400 0x20000000
-//! .data 0x0 0x20000400
-//! ```
-//!
-//! Graphically the RAM sections look like this:
-//!
-//! <p align="center">
-//! <img alt="Stack overflow" src="https://i.imgur.com/haJKXr4.png">
-//! </p>
-//!
-//! To prevent memory corruption due to stack overflows in this scenario it suffices to switch the
-//! sections so that the `.bss` section is near the end of the RAM region and the `.stack` comes
-//! *before* `.bss`, at a lower address.
-//!
-//! To swap the sections you can use the [`cortex-m-rt-ld`] linker to link the program.
-//!
-//! ``` console
-//! $ cargo install cortex-m-rt-ld
-//!
-//! $ xargo rustc --target thumbv7m-none-eabi -- \
-//! -C link-arg=-Tlink.x -C linker=cortex-m-rt-ld -Z linker-flavor=ld
-//! ```
-//!
-//! Now you get non overlapping linker sections:
-//!
-//! ``` console
-//! section size addr
-//! .vector_table 0x400 0x8000000
-//! .text 0x186 0x8000400
-//! .rodata 0x50 0x8000590
-//! .stack 0x1c00 0x20000000
-//! .bss 0x400 0x20001c00
-//! .data 0x0 0x20002000
-//! ```
-//!
-//! Note that the `.stack` section is smaller now. Graphically, the memory layout now looks like
-//! this:
-//!
-//! <p align="center">
-//! <img alt="Swapped sections" src="https://i.imgur.com/waOKpHw.png">
-//! </p>
-//!
-//! On stack overflows `.stack` will hit the lower boundary of the RAM region raising a hard fault
-//! exception, instead of silently corrupting the `.bss` section.
-//!
-//! You can confirm this by inspecting the program in GDB.
-//!
-//! ``` console
-//! > continue
-//! Program received signal SIGTRAP, Trace/breakpoint trap.
-//!
-//! > p $sp
-//! $1 = (void *) 0x1ffffff0
-//! ```
-//!
-//! The failure mode this time was the `.stack` crashing into the RAM boundary. The variable `XS` is
-//! unaffected this time:
-//!
-//! ``` console
-//! > x/4x app::XS
-//! 0x20001c00 <app::XS>: 0x00000000 0x00000000 0x00000000 0x00000000
-//!
-//! > x/4x app::XS+252
-//! 0x20001ff0 <app::XS+1008>: 0x00000000 0x00000000 0x00000000 0x00000000
-//! ```
-//!
-//! ## `.heap`
-//!
-//! If your program makes use of a `.heap` section a similar problem can occur:
-//!
-//! <p align="center">
-//! <img alt="Memory layout when `.heap` exists" src="https://i.imgur.com/kFHRGiF.png">
-//! </p>
-//!
-//! The `.stack` can crash into the `.heap`, or vice versa, and you'll also get memory corruption.
-//!
-//! `cortex-m-rt-ld` can also be used in this case but the size of the `.heap` section must be
-//! specified via the `_heap_size` symbol in `memory.x`, or in any other linker script.
-//!
-//! ``` console
-//! $ $EDITOR memory.x && tail -n1 $_
-//! _heap_size = 0x400;
-//! ```
-//!
-//! ``` console
-//! $ xargo rustc --target thumbv7m-none-eabi -- \
-//! -C link-arg=-Tlink.x -C linker=cortex-m-rt-ld -Z linker-flavor=ld
-//!
-//! $ arm-none-eabi-size -Ax $(find target -name app) | head
-//! section size addr
-//! .vector_table 0x400 0x8000000
-//! .text 0x1a8 0x8000400
-//! .rodata 0x50 0x80005b0
-//! .stack 0x1800 0x20000000
-//! .bss 0x400 0x20001800
-//! .data 0x0 0x20001c00
-//! .heap 0x400 0x20001c00
-//! ```
-//!
-//! Graphically the memory layout looks like this:
-//!
-//! <p align="center">
-//! <img alt="Swapped sections when `.heap` exists" src="https://i.imgur.com/6Y5DaBp.png">
-//! </p>
-//!
-//! Now both stack overflows and dynamic memory over-allocations (OOM) will generate hard fault
-//! exceptions, instead of running into each other.
-//!
//! # Symbol interfaces
//!
//! This crate makes heavy use of symbols, linker sections and linker scripts to
@@ -351,7 +151,7 @@
//! #[linkage = "weak"]
//! #[naked]
//! #[no_mangle]
-//! extern "C" fn WWDG() {
+//! extern "C" fn PVD() {
//! unsafe {
//! asm!("b DEFAULT_HANDLER" :::: "volatile");
//! core::intrinsics::unreachable();
@@ -423,10 +223,6 @@
//! _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM);
//! ```
//!
-//! ### `_heap_size`
-//!
-//! The size of the `.heap` section. Only meaningful when using `cortex-m-rt-ld`.
-//!
//! ### `_stext`
//!
//! This symbol indicates where the `.text` section will be located. If not
@@ -472,20 +268,14 @@
//! }
//! ```
//!
-//! *NOTE* if you are using `cortex-m-rt-ld` and/or have defined the `_heap_size` symbol then you should
-//! use the address of the `_eheap` to compute the size of the `.heap` section, instead of
-//! duplicating the value that you wrote in `memory.x`.
-//!
//! [1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html
//! [qs]: https://docs.rs/cortex-m-quickstart/0.2.0/cortex_m_quickstart/
-//! [`cortex-m-rt-ld`]: https://crates.io/crates/cortex-m-rt-ld
//! [2]: https://sourceware.org/binutils/docs/ld/MEMORY.html
-#![cfg_attr(any(target_arch = "arm", feature = "abort-on-panic"), feature(core_intrinsics))]
#![deny(missing_docs)]
#![deny(warnings)]
#![feature(asm)]
-#![cfg_attr(needs_cb, feature(compiler_builtins_lib))]
+#![feature(core_intrinsics)]
#![feature(global_asm)]
#![feature(lang_items)]
#![feature(linkage)]
@@ -493,8 +283,6 @@
#![feature(used)]
#![no_std]
-#[cfg(needs_cb)]
-extern crate compiler_builtins;
#[cfg(target_arch = "arm")]
extern crate cortex_m;
#[cfg(target_arch = "arm")]