diff --git a/CHANGELOG.md b/CHANGELOG.md index 0abb3d7..ac35c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- Documentation and an example about how to use the heap and a dynamic memory + allocator. + +### Changed + +- Bumped the `cortex-m-rt` dependency to v0.2.2 + ## [v0.1.6] - 2017-05-26 ### Added diff --git a/Cargo.toml b/Cargo.toml index 4e9dd86..b6fcb27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ version = "0.1.6" [dependencies] cortex-m = "0.2.6" -cortex-m-rt = "0.2.0" +cortex-m-rt = "0.2.2" [profile.release] lto = true diff --git a/examples/allocator.rs b/examples/allocator.rs new file mode 100644 index 0000000..6b2ad85 --- /dev/null +++ b/examples/allocator.rs @@ -0,0 +1,71 @@ +//! How to use the heap and a dynamic memory allocator +//! +//! To compile this example you'll need to build the collections crate as part +//! of the Xargo sysroot. To do that change the Xargo.toml file to look like +//! this: +//! +//! ``` text +//! [dependencies.core] +//! [dependencies.collections] # new +//! +//! [dependencies.compiler_builtins] +//! features = ["mem"] +//! git = "https://github.com/rust-lang-nursery/compiler-builtins" +//! stage = 1 +//! ``` +//! +//! This example depends on the alloc-cortex-m crate so you'll have to add it +//! to your Cargo.toml: +//! +//! ``` text +//! # or edit the Cargo.toml file manually +//! $ cargo add alloc-cortex-m +//! ``` + +#![feature(collections)] +#![feature(used)] +#![no_std] + +// This is the allocator crate; you can use a different one +extern crate alloc_cortex_m; +#[macro_use] +extern crate collections; +#[macro_use] +extern crate cortex_m; +extern crate cortex_m_rt; + +use cortex_m::asm; + +fn main() { + // Initialize the allocator + unsafe { + extern "C" { + // Start of the heap + static mut _sheap: usize; + } + + // Size of the heap in words (1 word = 4 bytes) + // WARNING: The bigger the heap the greater the chance to run into a + // stack overflow (collision between the stack and the heap) + const SIZE: isize = 256; + + // End of the heap + let _eheap = (&mut _sheap as *mut _).offset(SIZE); + + alloc_cortex_m::init(&mut _sheap as *mut _, _eheap); + } + + // Growable array allocated on the heap + let xs = vec![0, 1, 2]; + hprintln!("{:?}", xs); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[allow(dead_code)] +#[used] +#[link_section = ".rodata.interrupts"] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/gen-examples.sh b/gen-examples.sh index f1f7e5e..1f3af68 100644 --- a/gen-examples.sh +++ b/gen-examples.sh @@ -11,6 +11,7 @@ main() { crash register-interrupt-handler override-exception-handler + allocator ) rm -rf src/examples diff --git a/src/examples/_3_crash.rs b/src/examples/_3_crash.rs index 29b1fbd..dd8f871 100644 --- a/src/examples/_3_crash.rs +++ b/src/examples/_3_crash.rs @@ -27,7 +27,7 @@ //! $2 = cortex_m::exception::Exception::HardFault //! //! (gdb) # Where did we come from? -//! (gdb) print _e +//! (gdb) backtrace //! ``` //! //! ``` diff --git a/src/examples/_6_allocator.rs b/src/examples/_6_allocator.rs new file mode 100644 index 0000000..5170dda --- /dev/null +++ b/src/examples/_6_allocator.rs @@ -0,0 +1,75 @@ +//! How to use the heap and a dynamic memory allocator +//! +//! To compile this example you'll need to build the collections crate as part +//! of the Xargo sysroot. To do that change the Xargo.toml file to look like +//! this: +//! +//! ``` text +//! [dependencies.core] +//! [dependencies.collections] # new +//! +//! [dependencies.compiler_builtins] +//! features = ["mem"] +//! git = "https://github.com/rust-lang-nursery/compiler-builtins" +//! stage = 1 +//! ``` +//! +//! This example depends on the alloc-cortex-m crate so you'll have to add it +//! to your Cargo.toml: +//! +//! ``` text +//! # or edit the Cargo.toml file manually +//! $ cargo add alloc-cortex-m +//! ``` +//! +//! ``` +//! +//! #![feature(collections)] +//! #![feature(used)] +//! #![no_std] +//! +//! // This is the allocator crate; you can use a different one +//! extern crate alloc_cortex_m; +//! #[macro_use] +//! extern crate collections; +//! #[macro_use] +//! extern crate cortex_m; +//! extern crate cortex_m_rt; +//! +//! use cortex_m::asm; +//! +//! fn main() { +//! // Initialize the allocator +//! unsafe { +//! extern "C" { +//! // Start of the heap +//! static mut _sheap: usize; +//! } +//! +//! // Size of the heap in words (1 word = 4 bytes) +//! // WARNING: The bigger the heap the greater the chance to run into a +//! // stack overflow (collision between the stack and the heap) +//! const SIZE: isize = 256; +//! +//! // End of the heap +//! let _eheap = (&mut _sheap as *mut _).offset(SIZE); +//! +//! alloc_cortex_m::init(&mut _sheap as *mut _, _eheap); +//! } +//! +//! // Growable array allocated on the heap +//! let xs = vec![0, 1, 2]; +//! hprintln!("{:?}", xs); +//! } +//! +//! // As we are not using interrupts, we just register a dummy catch all handler +//! #[allow(dead_code)] +//! #[used] +//! #[link_section = ".rodata.interrupts"] +//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; +//! +//! extern "C" fn default_handler() { +//! asm::bkpt(); +//! } +//! ``` +// Auto-generated. Do not modify. diff --git a/src/examples/mod.rs b/src/examples/mod.rs index 463bc03..5e0dad7 100644 --- a/src/examples/mod.rs +++ b/src/examples/mod.rs @@ -6,3 +6,4 @@ pub mod _2_panic; pub mod _3_crash; pub mod _4_register_interrupt_handler; pub mod _5_override_exception_handler; +pub mod _6_allocator; diff --git a/src/lib.rs b/src/lib.rs index c81a403..ff33878 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,24 +111,24 @@ //! //! - Flash the program //! -//! ``` +//! ``` text //! # Launch OpenOCD on a terminal //! $ openocd -f (..) //! ``` //! -//! ``` +//! ``` text //! # Start debug session //! $ arm-none-eabi-gdb target/.. //! ``` //! //! **NOTE** As of nightly-2017-05-14 or so and cortex-m-quickstart v0.1.6 you -//! can simply run `cargo run` or `cargo run --example $ex` to build and flash -//! the program, and immediately start a debug session. IOW, it lets you omit +//! can simply run `cargo run` or `cargo run --example $example` to build the +//! program, and immediately start a debug session. IOW, it lets you omit the //! `arm-none-eabi-gdb` command. //! -//! ``` +//! ``` text //! $ cargo run --example hello -//! > # drop you into GDB session +//! > # drops you into a GDB session //! ``` //! //! # Examples @@ -242,7 +242,7 @@ //! //! Error message: //! -//! ``` +//! ``` text //! $ xargo build //! error: linking with `arm-none-eabi-ld` failed: exit code: 1 //! |