Skip to content

Commit 0b991c1

Browse files
committed
Merge branch 'master' into release
2 parents 3b25e71 + 1089ef3 commit 0b991c1

File tree

6 files changed

+146
-7
lines changed

6 files changed

+146
-7
lines changed

cortex-m-rt/ci/script.sh

+24
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ main() {
1010
minimal
1111
main
1212
override-exception
13+
pre_init
1314
state
1415
)
16+
local fail_examples=(
17+
data_overflow
18+
)
1519
if [ $TRAVIS_RUST_VERSION = nightly ]; then
1620
# linking with GNU LD
1721
for ex in "${examples[@]}"; do
@@ -23,6 +27,15 @@ main() {
2327
-C link-arg=-nostartfiles \
2428
-C link-arg=-Wl,-Tlink.x
2529
done
30+
for ex in "${fail_examples[@]}"; do
31+
! cargo rustc --target $TARGET --example $ex -- \
32+
-C link-arg=-nostartfiles \
33+
-C link-arg=-Wl,-Tlink.x
34+
35+
! cargo rustc --target $TARGET --example $ex --release -- \
36+
-C link-arg=-nostartfiles \
37+
-C link-arg=-Wl,-Tlink.x
38+
done
2639

2740
cargo rustc --target $TARGET --example device --features device -- \
2841
-C link-arg=-nostartfiles \
@@ -44,6 +57,17 @@ main() {
4457
-Z linker-flavor=ld.lld \
4558
-C link-arg=-Tlink.x
4659
done
60+
for ex in "${fail_examples[@]}"; do
61+
! cargo rustc --target $TARGET --example $ex -- \
62+
-C linker=rust-lld \
63+
-Z linker-flavor=ld.lld \
64+
-C link-arg=-Tlink.x
65+
66+
! cargo rustc --target $TARGET --example $ex --release -- \
67+
-C linker=rust-lld \
68+
-Z linker-flavor=ld.lld \
69+
-C link-arg=-Tlink.x
70+
done
4771

4872
cargo rustc --target $TARGET --example device --features device -- \
4973
-C linker=rust-lld \

cortex-m-rt/examples/data_overflow.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//! This is not an example; this is a linker overflow detection test
2+
//! which should fail to link due to .data overflowing FLASH.
3+
4+
#![deny(warnings)]
5+
#![no_main]
6+
#![no_std]
7+
8+
#[macro_use(entry)]
9+
extern crate cortex_m_rt as rt;
10+
extern crate panic_abort;
11+
12+
use core::ptr;
13+
14+
entry!(main);
15+
16+
// This large static array uses most of .rodata
17+
static RODATA: [u8; 48*1024] = [1u8; 48*1024];
18+
19+
// This large mutable array causes .data to use the rest of FLASH
20+
// without also overflowing RAM.
21+
static mut DATA: [u8; 16*1024] = [1u8; 16*1024];
22+
23+
fn main() -> ! {
24+
unsafe {
25+
let _bigdata = ptr::read_volatile(&RODATA as *const u8);
26+
let _bigdata = ptr::read_volatile(&DATA as *const u8);
27+
}
28+
29+
loop {}
30+
}

cortex-m-rt/examples/pre_init.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! `cortex-m-rt` based program with a function run before RAM is initialized.
2+
3+
#![deny(warnings)]
4+
#![no_main]
5+
#![no_std]
6+
7+
#[macro_use(entry, pre_init)]
8+
extern crate cortex_m_rt as rt;
9+
extern crate panic_semihosting;
10+
11+
pre_init!(disable_watchdog);
12+
13+
unsafe fn disable_watchdog() {
14+
// Do what you need to disable the watchdog.
15+
}
16+
17+
// the program entry point
18+
entry!(main);
19+
20+
fn main() -> ! {
21+
loop {}
22+
}

cortex-m-rt/link.x.in

+12-7
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ PROVIDE(UserHardFault = DefaultUserHardFault);
5151
/* # Interrupt vectors */
5252
EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */
5353

54+
/* # Pre-initialization function */
55+
/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function,
56+
then the function this points to will be called before the RAM is initialized. */
57+
PROVIDE(__pre_init = DefaultPreInit);
58+
5459
/* # Sections */
5560
SECTIONS
5661
{
@@ -84,24 +89,24 @@ SECTIONS
8489
} > FLASH
8590

8691
/* ### .rodata */
87-
.rodata :
92+
.rodata : ALIGN(4)
8893
{
8994
*(.rodata .rodata.*);
9095

91-
/* 4-byte align the end (VMA) of this section */
92-
/* WHY? To my knowledge there's no way to indicate the alignment of *LMA* so we align *this*
93-
section with the goal of using its end address as the LMA of .data */
96+
/* 4-byte align the end (VMA) of this section.
97+
This is required by LLD to ensure the LMA of the following .data
98+
section will have the correct alignment. */
9499
. = ALIGN(4);
95100
} > FLASH
96101

97102
/* ## Sections in RAM */
98103
/* ### .data */
99-
.data : AT(ADDR(.rodata) + SIZEOF(.rodata)) /* LMA */
104+
.data : ALIGN(4)
100105
{
101106
*(.data .data.*);
102107

103108
. = ALIGN(4); /* 4-byte align the end (VMA) of this section */
104-
} > RAM
109+
} > RAM AT > FLASH
105110

106111
/* VMA of .data */
107112
__sdata = ADDR(.data);
@@ -111,7 +116,7 @@ SECTIONS
111116
__sidata = LOADADDR(.data);
112117

113118
/* ### .bss */
114-
.bss :
119+
.bss : ALIGN(4)
115120
{
116121
*(.bss .bss.*);
117122

cortex-m-rt/memory.x

+4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
/* Device specific memory layout */
22

3+
/* This file is used to build the cortex-m-rt examples,
4+
but not other applications using cortex-m-rt. */
5+
36
MEMORY
47
{
58
/* FLASH and RAM are mandatory memory regions */
9+
/* Update examples/data_overflow.rs if you change these sizes. */
610
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
711
RAM : ORIGIN = 0x20000000, LENGTH = 20K
812

cortex-m-rt/src/lib.rs

+54
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@
237237
//! have a size of 32 vectors (on ARMv6-M) or 240 vectors (on ARMv7-M). This array is located after
238238
//! `__EXCEPTIONS` in the `.vector_table` section.
239239
//!
240+
//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty
241+
//! function. The function called can be changed by calling the `pre_init!` macro. The empty
242+
//! function is not optimized out by default, but if an empty function is passed to `pre_init!` the
243+
//! function call will be optimized out.
244+
//!
240245
//! If you override any exception handler you'll find it as an unmangled symbol, e.g. `SysTick` or
241246
//! `SVCall`, in the output of `objdump`,
242247
//!
@@ -378,6 +383,14 @@
378383
//! println!("cargo:rustc-link-search={}", out.display());
379384
//! }
380385
//! ```
386+
//!
387+
//! ## `pre_init!`
388+
//!
389+
//! A user-defined function can be run at the start of the reset handler, before RAM is
390+
//! initialized. The macro `pre_init!` can be called to set the function to be run. The function is
391+
//! intended to perform actions that cannot wait the time it takes for RAM to be initialized, such
392+
//! as disabling a watchdog. As the function is called before RAM is initialized, any access of
393+
//! static variables will result in undefined behavior.
381394
382395
// # Developer notes
383396
//
@@ -474,8 +487,13 @@ pub unsafe extern "C" fn Reset() -> ! {
474487
static mut __sdata: u32;
475488
static mut __edata: u32;
476489
static __sidata: u32;
490+
491+
fn __pre_init();
477492
}
478493

494+
let pre_init: unsafe extern "C" fn() = __pre_init;
495+
pre_init();
496+
479497
// Initialize RAM
480498
r0::zero_bss(&mut __sbss, &mut __ebss);
481499
r0::init_data(&mut __sdata, &mut __edata, &__sidata);
@@ -531,6 +549,10 @@ pub unsafe extern "C" fn DefaultUserHardFault() {
531549
}
532550
}
533551

552+
#[doc(hidden)]
553+
#[no_mangle]
554+
pub unsafe extern "C" fn DefaultPreInit() {}
555+
534556
/// Macro to define the entry point of the program
535557
///
536558
/// **NOTE** This macro must be invoked once and must be invoked from an accessible module, ideally
@@ -872,3 +894,35 @@ macro_rules! exception {
872894
}
873895
};
874896
}
897+
898+
/// Macro to set the function to be called at the beginning of the reset handler.
899+
///
900+
/// The function must have the signature of `unsafe fn()`.
901+
///
902+
/// The function passed will be called before static variables are initialized. Any access of static
903+
/// variables will result in undefined behavior.
904+
///
905+
/// # Examples
906+
///
907+
/// ``` ignore
908+
/// pre_init!(foo::bar);
909+
///
910+
/// mod foo {
911+
/// pub unsafe fn bar() {
912+
/// // do something here
913+
/// }
914+
/// }
915+
/// ```
916+
#[macro_export]
917+
macro_rules! pre_init {
918+
($handler:path) => {
919+
#[allow(unsafe_code)]
920+
#[deny(private_no_mangle_fns)] // raise an error if this item is not accessible
921+
#[no_mangle]
922+
pub unsafe extern "C" fn __pre_init() {
923+
// validate user handler
924+
let f: unsafe fn() = $handler;
925+
f();
926+
}
927+
}
928+
}

0 commit comments

Comments
 (0)