3
3
//! # Example
4
4
//!
5
5
//! ```
6
- //! // Plug in the allocator
6
+ //! // Plug in the allocator crate
7
7
//! extern crate alloc_cortex_m;
8
8
//! extern crate collections;
9
9
//!
10
- //! use alloc_cortex_m;
11
10
//! use collections::Vec;
12
11
//!
13
- //! pub unsafe extern "C" fn reset_vector() {
14
- //! let heap_start: *mut usize = &mut _heap_start;
15
- //! let heap_end: *mut usize = &mut _heap_end;
12
+ //! // These symbols come from a linker script
13
+ //! extern "C" {
14
+ //! static mut _heap_start: usize;
15
+ //! static mut _heap_end: usize;
16
16
//! }
17
17
//!
18
18
//! #[no_mangle]
19
19
//! pub fn main() -> ! {
20
20
//! // Initialize the heap BEFORE you use the allocator
21
- //! unsafe { alloc_cortex_m::init(heap_start, heap_end ) }
21
+ //! unsafe { alloc_cortex_m::init(&mut _heap_start, &mut _heap_end ) }
22
22
//!
23
23
//! let mut xs = Vec::new();
24
24
//! xs.push(1);
25
25
//! // ...
26
26
//! }
27
27
//! ```
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
+ //! ```
28
39
29
40
#![ allocator]
30
41
#![ feature( allocator) ]
34
45
extern crate cortex_m;
35
46
extern crate linked_list_allocator;
36
47
37
- use core:: { ptr , cmp } ;
48
+ use core:: { cmp , ptr } ;
38
49
39
50
use linked_list_allocator:: Heap ;
40
51
use cortex_m:: interrupt:: Mutex ;
@@ -43,26 +54,32 @@ use cortex_m::interrupt::Mutex;
43
54
///
44
55
/// You must initialize this heap using the
45
56
/// [`init`](struct.Heap.html#method.init) method before using the allocator.
46
- pub static HEAP : Mutex < Heap > = Mutex :: new ( Heap :: empty ( ) ) ;
57
+ static HEAP : Mutex < Heap > = Mutex :: new ( Heap :: empty ( ) ) ;
47
58
48
59
/// Initializes the heap
49
60
///
50
- /// This method must be called before you run any code that makes use of the
61
+ /// This function must be called BEFORE you run any code that makes use of the
51
62
/// allocator.
52
63
///
53
- /// This method must be called exactly ONCE.
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`
54
72
///
55
- /// `start_addr` is the address where the heap will be located. Note that
56
- /// heap grows "upwards", towards larger addresses.
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`.
57
76
///
58
- /// `end_addr` is the address just part the end of the heap.
77
+ /// # Unsafety
59
78
///
60
- /// In your linker script, you might have something like:
79
+ /// Obey these or Bad Stuff will happen.
61
80
///
62
- /// ```
63
- /// _heap_start = .;
64
- /// _heap_end = ORIGIN(SRAM) + LENGTH(SRAM) - _stack_size;
65
- /// ```
81
+ /// - This function must be called exactly ONCE.
82
+ /// - `end_addr` > `start_addr`
66
83
pub unsafe fn init ( start_addr : * mut usize , end_addr : * mut usize ) {
67
84
let start = start_addr as usize ;
68
85
let end = end_addr as usize ;
@@ -76,7 +93,9 @@ pub unsafe fn init(start_addr: *mut usize, end_addr: *mut usize) {
76
93
#[ no_mangle]
77
94
/// Rust allocation function (c.f. malloc)
78
95
pub extern "C" fn __rust_allocate ( size : usize , align : usize ) -> * mut u8 {
79
- HEAP . lock ( |heap| heap. allocate_first_fit ( size, align) . expect ( "out of memory" ) )
96
+ HEAP . lock ( |heap| {
97
+ heap. allocate_first_fit ( size, align) . expect ( "out of memory" )
98
+ } )
80
99
}
81
100
82
101
/// Rust de-allocation function (c.f. free)
0 commit comments