Skip to content

Commit f64556e

Browse files
author
Jorge Aparicio
authored
Merge pull request #2 from japaric/moar-docs
add init function
2 parents 4e4d483 + c49327c commit f64556e

File tree

3 files changed

+59
-33
lines changed

3 files changed

+59
-33
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- [breaking] Hid the HEAP variable. We now only expose an `init` function to
13+
initialize the allocator.
14+
1015
## [v0.1.0] - 2016-11-19
1116

1217
### Added

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
authors = ["Jorge Aparicio <[email protected]>"]
2+
authors = ["Jorge Aparicio <[email protected]>", "Jonathan Pallant <[email protected]>"]
33
description = "A heap allocator for Cortex-M processors"
44
documentation = "https://docs.rs/alloc-cortex-m"
55
keywords = ["arm", "cortex-m", "allocator"]

src/lib.rs

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,39 @@
33
//! # Example
44
//!
55
//! ```
6-
//! // Plug in the allocator
6+
//! // Plug in the allocator crate
77
//! extern crate alloc_cortex_m;
88
//! extern crate collections;
99
//!
10-
//! use alloc_cortex_m::HEAP;
1110
//! use collections::Vec;
1211
//!
12+
//! // These symbols come from a linker script
13+
//! extern "C" {
14+
//! static mut _heap_start: usize;
15+
//! static mut _heap_end: usize;
16+
//! }
17+
//!
1318
//! #[no_mangle]
1419
//! pub fn main() -> ! {
1520
//! // Initialize the heap BEFORE you use the allocator
16-
//! unsafe { HEAP.init(0x2000_0000, 1024) }
21+
//! unsafe { alloc_cortex_m::init(&mut _heap_start, &mut _heap_end) }
1722
//!
1823
//! let mut xs = Vec::new();
1924
//! xs.push(1);
2025
//! // ...
2126
//! }
2227
//! ```
28+
//!
29+
//! And in your linker script, you might have something like:
30+
//!
31+
//! ``` text
32+
//! /* space reserved for the stack */
33+
//! _stack_size = 0x1000;
34+
//!
35+
//! /* `.` is right after the .bss and .data sections */
36+
//! _heap_start = .;
37+
//! _heap_end = ORIGIN(SRAM) + LENGTH(SRAM) - _stack_size;
38+
//! ```
2339
2440
#![allocator]
2541
#![feature(allocator)]
@@ -29,41 +45,46 @@
2945
extern crate cortex_m;
3046
extern crate linked_list_allocator;
3147

32-
use core::{ptr, cmp};
48+
use core::{cmp, ptr};
3349

50+
use linked_list_allocator::Heap;
3451
use cortex_m::interrupt::Mutex;
3552

3653
/// A global UNINITIALIZED heap allocator
3754
///
3855
/// You must initialize this heap using the
3956
/// [`init`](struct.Heap.html#method.init) method before using the allocator.
40-
pub static HEAP: Mutex<Heap> = Mutex::new(Heap::empty());
41-
42-
/// A heap allocator
43-
// NOTE newtype to hide all the other Heap methods
44-
pub struct Heap {
45-
inner: linked_list_allocator::Heap,
46-
}
47-
48-
impl Heap {
49-
const fn empty() -> Self {
50-
Heap { inner: linked_list_allocator::Heap::empty() }
51-
}
57+
static HEAP: Mutex<Heap> = Mutex::new(Heap::empty());
5258

53-
/// Initializes the heap
54-
///
55-
/// This method must be called before you run any code that makes use of the
56-
/// allocator.
57-
///
58-
/// This method must be called exactly ONCE.
59-
///
60-
/// `heap_bottom` is the address where the heap will be located. Note that
61-
/// heap grows "upwards", towards larger addresses.
62-
///
63-
/// `heap_size` is the size of the heap in bytes
64-
pub unsafe fn init(&mut self, heap_bottom: usize, heap_size: usize) {
65-
self.inner.init(heap_bottom, heap_size);
66-
}
59+
/// Initializes the heap
60+
///
61+
/// This function must be called BEFORE you run any code that makes use of the
62+
/// allocator.
63+
///
64+
/// `start_addr` is the address where the heap will be located.
65+
///
66+
/// `end_addr` points to the end of the heap.
67+
///
68+
/// Note that:
69+
///
70+
/// - The heap grows "upwards", towards larger addresses. Thus `end_addr` must
71+
/// be larger than `start_addr`
72+
///
73+
/// - The size of the heap will actually be
74+
/// `(end_addr as usize) - (start_addr as usize) + 1` because the allocator
75+
/// won't use the byte at `end_addr`.
76+
///
77+
/// # Unsafety
78+
///
79+
/// Obey these or Bad Stuff will happen.
80+
///
81+
/// - This function must be called exactly ONCE.
82+
/// - `end_addr` > `start_addr`
83+
pub unsafe fn init(start_addr: *mut usize, end_addr: *mut usize) {
84+
let start = start_addr as usize;
85+
let end = end_addr as usize;
86+
let size = (end - start) - 1;
87+
HEAP.lock(|heap| heap.init(start, size));
6788
}
6889

6990
// Rust allocator interface
@@ -73,15 +94,15 @@ impl Heap {
7394
/// Rust allocation function (c.f. malloc)
7495
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
7596
HEAP.lock(|heap| {
76-
heap.inner.allocate_first_fit(size, align).expect("out of memory")
97+
heap.allocate_first_fit(size, align).expect("out of memory")
7798
})
7899
}
79100

80101
/// Rust de-allocation function (c.f. free)
81102
#[doc(hidden)]
82103
#[no_mangle]
83104
pub extern "C" fn __rust_deallocate(ptr: *mut u8, size: usize, align: usize) {
84-
HEAP.lock(|heap| unsafe { heap.inner.deallocate(ptr, size, align) });
105+
HEAP.lock(|heap| unsafe { heap.deallocate(ptr, size, align) });
85106
}
86107

87108
/// Rust re-allocation function (c.f. realloc)

0 commit comments

Comments
 (0)