Skip to content

Commit 0f139c3

Browse files
committed
use published versions, doc up, update CHANGELOG
1 parent 3a4a5be commit 0f139c3

24 files changed

+546
-553
lines changed

.cargo/config

+23
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,48 @@ runner = 'arm-none-eabi-gdb'
33
rustflags = [
44
"-C", "link-arg=-Wl,-Tlink.x",
55
"-C", "link-arg=-nostartfiles",
6+
7+
# uncomment to use rustc LLD to link programs (a)
8+
# "-C", "link-arg=-Tlink.x",
9+
# "-C", "linker=lld",
10+
# "-Z", "linker-flavor=ld.lld",
611
]
712

813
[target.thumbv7m-none-eabi]
914
runner = 'arm-none-eabi-gdb'
1015
rustflags = [
1116
"-C", "link-arg=-Wl,-Tlink.x",
1217
"-C", "link-arg=-nostartfiles",
18+
19+
# uncomment to use rustc LLD to link programs (a)
20+
# "-C", "link-arg=-Tlink.x",
21+
# "-C", "linker=lld",
22+
# "-Z", "linker-flavor=ld.lld",
1323
]
1424

1525
[target.thumbv7em-none-eabi]
1626
runner = 'arm-none-eabi-gdb'
1727
rustflags = [
1828
"-C", "link-arg=-Wl,-Tlink.x",
1929
"-C", "link-arg=-nostartfiles",
30+
31+
# uncomment to use rustc LLD to link programs (a)
32+
# "-C", "link-arg=-Tlink.x",
33+
# "-C", "linker=lld",
34+
# "-Z", "linker-flavor=ld.lld",
2035
]
2136

2237
[target.thumbv7em-none-eabihf]
2338
runner = 'arm-none-eabi-gdb'
2439
rustflags = [
2540
"-C", "link-arg=-Wl,-Tlink.x",
2641
"-C", "link-arg=-nostartfiles",
42+
43+
# uncomment to use rustc LLD to link programs (a)
44+
# "-C", "link-arg=-Tlink.x",
45+
# "-C", "linker=lld",
46+
# "-Z", "linker-flavor=ld.lld",
2747
]
48+
49+
# (a) you also need to comment out the other two `link-arg` lines. But note that as of v0.6.0 LLD
50+
# has a bug where it mislinks FFI calls and they up crashing the program at runtime

CHANGELOG.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
77

8+
## [v0.3.0] - 2018-05-12
9+
10+
### Changed
11+
12+
- [breaking-change] `arm-none-eabi-gcc` is now a mandatory dependency as it's required by the
13+
`cortex-m-rt` dependency and also the default linker.
14+
15+
- Bumped the `cortex-m` and `cortex-m-rt` dependencies to v0.5.0. Updated all the examples to match
16+
the new `cortex-m-rt` API.
17+
18+
- Updated the `allocator` example to compile on a recent nightly.
19+
20+
- Removed `opt-level = "s"` from `profile.release`. This flag is still unstable.
21+
22+
- Set the number of codegen-units to 1 when compiling in release mode. This produces smaller and
23+
faster binaries.
24+
825
## [v0.2.7] - 2018-04-24
926

1027
### Changed
@@ -149,7 +166,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
149166

150167
- Initial release
151168

152-
[Unreleased]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.7...HEAD
169+
[Unreleased]: https://github.com/japaric/cortex-m-quickstart/compare/v0.3.0...HEAD
170+
[v0.3.0]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.7...v0.3.0
153171
[v0.2.7]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.6...v0.2.7
154172
[v0.2.6]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.5...v0.2.6
155173
[v0.2.5]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.4...v0.2.5

Cargo.toml

+11-20
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,24 @@ keywords = ["arm", "cortex-m", "template"]
66
license = "MIT OR Apache-2.0"
77
name = "cortex-m-quickstart"
88
repository = "https://github.com/japaric/cortex-m-quickstart"
9-
version = "0.2.7"
9+
version = "0.3.0"
1010

1111
[dependencies]
12-
# cortex-m-rt = "0.5.0"
13-
cortex-m-rt = { git = "https://github.com/japaric/cortex-m-rt", branch = "stable" }
14-
panic-abort = "0.1.1"
15-
# panic-semihosting = "0.1.1"
16-
panic-semihosting = { git = "https://github.com/japaric/panic-semihosting", branch = "stable" }
17-
# Uncomment for the allocator example.
18-
#alloc-cortex-m = "0.3.3"
19-
20-
[dependencies.cortex-m]
21-
branch = "stable"
22-
default-features = false
23-
git = "https://github.com/japaric/cortex-m"
24-
# version = "0.4.4"
12+
cortex-m = "0.5.0"
13+
cortex-m-rt = "0.5.0"
14+
cortex-m-semihosting = "0.3.0"
15+
panic-itm = "0.1.1"
16+
panic-semihosting = "0.2.0"
2517

26-
[dependencies.cortex-m-semihosting]
27-
default-features = false
28-
version = "0.2.1"
18+
# Uncomment for the allocator example.
19+
# alloc-cortex-m = "0.3.6"
2920

3021
# Uncomment for the device example.
3122
# [dependencies.stm32f103xx]
3223
# features = ["rt"]
33-
# version = "0.9.0"
24+
# version = "0.10.0"
3425

3526
[profile.release]
27+
codegen-units = 1 # better optimizations
3628
debug = true
37-
lto = true
38-
opt-level = "s" # TODO remove; this flag requires nightly
29+
lto = true

examples/allocator.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
1212
#![feature(alloc)]
1313
#![feature(global_allocator)]
14+
#![feature(lang_items)]
1415
#![no_main]
1516
#![no_std]
1617

@@ -22,7 +23,7 @@ extern crate cortex_m;
2223
#[macro_use]
2324
extern crate cortex_m_rt as rt;
2425
extern crate cortex_m_semihosting as sh;
25-
extern crate panic_abort;
26+
extern crate panic_semihosting;
2627

2728
use core::fmt::Write;
2829

@@ -31,15 +32,16 @@ use cortex_m::asm;
3132
use rt::ExceptionFrame;
3233
use sh::hio;
3334

35+
// this is the allocator the application will use
3436
#[global_allocator]
3537
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
3638

3739
const HEAP_SIZE: usize = 1024; // in bytes
3840

39-
main!(main);
41+
entry!(main);
4042

4143
fn main() -> ! {
42-
// Initialize the allocator
44+
// Initialize the allocator BEFORE you use it
4345
unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
4446

4547
// Growable array allocated on the heap
@@ -51,20 +53,23 @@ fn main() -> ! {
5153
loop {}
5254
}
5355

54-
exception!(DefaultHandler, dh);
55-
56-
#[inline(always)]
57-
fn dh(_nr: u8) {
56+
// define what happens in an Out Of Memory (OOM) condition
57+
#[lang = "oom"]
58+
#[no_mangle]
59+
pub fn rust_oom() -> ! {
5860
asm::bkpt();
59-
}
6061

61-
exception!(HardFault, hf);
62+
loop {}
63+
}
6264

63-
#[inline(always)]
64-
fn hf(_ef: &ExceptionFrame) -> ! {
65-
asm::bkpt();
65+
exception!(HardFault, hard_fault);
6666

67-
loop {}
67+
fn hard_fault(ef: &ExceptionFrame) -> ! {
68+
panic!("HardFault at {:#?}", ef);
6869
}
6970

70-
interrupts!(DefaultHandler);
71+
exception!(*, default_handler);
72+
73+
fn default_handler(irqn: i16) {
74+
panic!("Unhandled exception (IRQn = {})", irqn);
75+
}

examples/crash.rs

+65-62
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,79 @@
11
//! Debugging a crash (exception)
22
//!
3-
//! The `cortex-m-rt` crate provides functionality for this through a default exception handler.
4-
//! When an exception is hit, the default handler will trigger a breakpoint and in this debugging
5-
//! context the stacked registers are accessible.
3+
//! Most crash conditions trigger a hard fault exception, whose handler is defined via
4+
//! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a
5+
//! snapshot of the CPU registers at the moment of the exception.
66
//!
7-
//! In you run the example below, you'll be able to inspect the state of your program under the
8-
//! debugger using these commands:
7+
//! This program crashes and the `HardFault` handler prints to the console the contents of the
8+
//! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace
9+
//! that led to the exception.
910
//!
1011
//! ``` text
1112
//! (gdb) continue
1213
//! Program received signal SIGTRAP, Trace/breakpoint trap.
1314
//! __bkpt () at asm/bkpt.s:3
1415
//! 3 bkpt
1516
//!
16-
//! (gdb) finish
17-
//! Run till exit from #0 __bkpt () at asm/bkpt.s:3
18-
//! Note: automatically using hardware breakpoints for read-only addresses.
19-
//! crash::hf (_ef=0x20004fa0) at examples/crash.rs:102
20-
//! 99 asm::bkpt();
17+
//! (gdb) backtrace
18+
//! #0 __bkpt () at asm/bkpt.s:3
19+
//! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19
20+
//! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87
21+
//! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71
22+
//! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99
23+
//! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10
24+
//! #6 0x0800093a in HardFault () at asm.s:5
25+
//! Backtrace stopped: previous frame identical to this frame (corrupt stack?)
26+
//! ```
2127
//!
22-
//! (gdb) # Exception frame = program state during the crash
23-
//! (gdb) print/x *_ef
24-
//! $1 = cortex_m_rt::ExceptionFrame {
25-
//! r0: 0x2fffffff,
26-
//! r1: 0x2fffffff,
27-
//! r2: 0x80006b0,
28-
//! r3: 0x80006b0,
29-
//! r12: 0x20000000,
30-
//! lr: 0x800040f,
31-
//! pc: 0x800066a,
32-
//! xpsr: 0x61000000
33-
//! }
28+
//! In the console output one will find the state of the Program Counter (PC) register at the time
29+
//! of the exception.
3430
//!
35-
//! (gdb) # Where did we come from?
36-
//! (gdb) backtrace
37-
//! #0 crash::hf (_ef=0x20004fa0) at examples/crash.rs:102
38-
//! #1 0x080004ac in UserHardFault (ef=0x20004fa0) at <exception macros>:9
39-
//! #2 <signal handler called>
40-
//! #3 0x0800066a in core::ptr::read_volatile (src=0x2fffffff) at /checkout/src/libcore/ptr.rs:452
41-
//! #4 0x0800040e in crash::main () at examples/crash.rs:85
42-
//! #5 0x08000456 in main () at <main macros>:3
31+
//! ``` text
32+
//! panicked at 'HardFault at ExceptionFrame {
33+
//! r0: 0x2fffffff,
34+
//! r1: 0x2fffffff,
35+
//! r2: 0x080051d4,
36+
//! r3: 0x080051d4,
37+
//! r12: 0x20000000,
38+
//! lr: 0x08000435,
39+
//! pc: 0x08000ab6,
40+
//! xpsr: 0x61000000
41+
//! }', examples/crash.rs:106:5
42+
//! ```
43+
//!
44+
//! This register contains the address of the instruction that caused the exception. In GDB one can
45+
//! disassemble the program around this address to observe the instruction that caused the
46+
//! exception.
4347
//!
44-
//! (gdb) # Nail down the location of the crash
45-
//! (gdb) disassemble/m _ef.pc
48+
//! ``` text
49+
//! (gdb) disassemble/m 0x08000ab6
4650
//! Dump of assembler code for function core::ptr::read_volatile:
47-
//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {}
48-
//! 0x08000662 <+0>: sub sp, #16
49-
//! 0x08000664 <+2>: mov r1, r0
50-
//! 0x08000666 <+4>: str r0, [sp, #8]
51+
//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {
52+
//! 0x08000aae <+0>: sub sp, #16
53+
//! 0x08000ab0 <+2>: mov r1, r0
54+
//! 0x08000ab2 <+4>: str r0, [sp, #8]
5155
//!
5256
//! 452 intrinsics::volatile_load(src)
53-
//! 0x08000668 <+6>: ldr r0, [sp, #8]
54-
//! 0x0800066a <+8>: ldr r0, [r0, #0]
55-
//! 0x0800066c <+10>: str r0, [sp, #12]
56-
//! 0x0800066e <+12>: ldr r0, [sp, #12]
57-
//! 0x08000670 <+14>: str r1, [sp, #4]
58-
//! 0x08000672 <+16>: str r0, [sp, #0]
59-
//! 0x08000674 <+18>: b.n 0x8000676 <core::ptr::read_volatile+20>
57+
//! 0x08000ab4 <+6>: ldr r0, [sp, #8]
58+
//! -> 0x08000ab6 <+8>: ldr r0, [r0, #0]
59+
//! 0x08000ab8 <+10>: str r0, [sp, #12]
60+
//! 0x08000aba <+12>: ldr r0, [sp, #12]
61+
//! 0x08000abc <+14>: str r1, [sp, #4]
62+
//! 0x08000abe <+16>: str r0, [sp, #0]
63+
//! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20>
6064
//!
6165
//! 453 }
62-
//! 0x08000676 <+20>: ldr r0, [sp, #0]
63-
//! 0x08000678 <+22>: add sp, #16
64-
//! 0x0800067a <+24>: bx lr
66+
//! 0x08000ac2 <+20>: ldr r0, [sp, #0]
67+
//! 0x08000ac4 <+22>: add sp, #16
68+
//! 0x08000ac6 <+24>: bx lr
6569
//!
6670
//! End of assembler dump.
6771
//! ```
6872
//!
73+
//! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word
74+
//! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame`
75+
//! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed.
76+
//!
6977
//! ---
7078
7179
#![no_main]
@@ -74,38 +82,33 @@
7482
extern crate cortex_m;
7583
#[macro_use]
7684
extern crate cortex_m_rt as rt;
77-
extern crate panic_abort;
85+
extern crate panic_semihosting;
7886

7987
use core::ptr;
8088

81-
use cortex_m::asm;
8289
use rt::ExceptionFrame;
8390

84-
main!(main);
91+
entry!(main);
8592

86-
#[inline(always)]
8793
fn main() -> ! {
8894
unsafe {
95+
// read an address outside of the RAM region; causes a HardFault exception
8996
ptr::read_volatile(0x2FFF_FFFF as *const u32);
9097
}
9198

9299
loop {}
93100
}
94101

95-
exception!(DefaultHandler, dh);
102+
// define the hard fault handler
103+
exception!(HardFault, hard_fault);
96104

97-
#[inline(always)]
98-
fn dh(_nr: u8) {
99-
asm::bkpt();
105+
fn hard_fault(ef: &ExceptionFrame) -> ! {
106+
panic!("HardFault at {:#?}", ef);
100107
}
101108

102-
exception!(HardFault, hf);
103-
104-
#[inline(always)]
105-
fn hf(_ef: &ExceptionFrame) -> ! {
106-
asm::bkpt();
109+
// define the default exception handler
110+
exception!(*, default_handler);
107111

108-
loop {}
112+
fn default_handler(irqn: i16) {
113+
panic!("Unhandled exception (IRQn = {})", irqn);
109114
}
110-
111-
interrupts!(DefaultHandler);

0 commit comments

Comments
 (0)