1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
//! A heap allocator for Cortex-M processors //! //! # Example //! //! ``` //! // Plug in the allocator crate //! extern crate alloc_cortex_m; //! extern crate collections; //! //! use collections::Vec; //! use alloc_cortex_m::CortexMHeap; //! //! #[global_allocator] //! static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); //! //! // These symbols come from a linker script //! extern "C" { //! static mut _sheap: u32; //! static mut _eheap: u32; //! } //! //! #[no_mangle] //! pub fn main() -> ! { //! // Initialize the heap BEFORE you use the allocator //! let start = unsafe { &mut _sheap as *mut u32 as usize }; //! let end = unsafe { &mut _sheap as *mut u32 as usize }; //! unsafe { ALLOCATOR.init(start, end - start) } //! //! let mut xs = Vec::new(); //! xs.push(1); //! // ... //! } //! ``` //! //! And in your linker script, you might have something like: //! //! ``` text //! /* space reserved for the stack */ //! _stack_size = 0x1000; //! //! /* `.` is right after the .bss and .data sections */ //! _heap_start = .; //! _heap_end = ORIGIN(SRAM) + LENGTH(SRAM) - _stack_size; //! ``` #![feature(const_fn)] #![no_std] #![feature(alloc, allocator_api)] extern crate cortex_m; extern crate linked_list_allocator; extern crate alloc; use alloc::allocator::{Alloc, Layout, AllocErr}; use linked_list_allocator::Heap; use cortex_m::interrupt::Mutex; pub struct CortexMHeap { heap: Mutex<Heap>, } impl CortexMHeap { /// Crate a new UNINITIALIZED heap allocator /// /// You must initialize this heap using the /// [`init`](struct.CortexMHeap.html#method.init) method before using the allocator. pub const fn empty() -> CortexMHeap { CortexMHeap { heap: Mutex::new(Heap::empty()), } } /// Initializes the heap /// /// This function must be called BEFORE you run any code that makes use of the /// allocator. /// /// `start_addr` is the address where the heap will be located. /// /// `size` is the size of the heap in bytes. /// /// Note that: /// /// - The heap grows "upwards", towards larger addresses. Thus `end_addr` must /// be larger than `start_addr` /// /// - The size of the heap is `(end_addr as usize) - (start_addr as usize)`. The /// allocator won't use the byte at `end_addr`. /// /// # Unsafety /// /// Obey these or Bad Stuff will happen. /// /// - This function must be called exactly ONCE. /// - `size > 0` pub unsafe fn init(&self, start_addr: usize, size: usize){ self.heap.lock(|heap| heap.init(start_addr, size)); } } unsafe impl<'a> Alloc for &'a CortexMHeap { unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { self.heap.lock(|heap| { heap.allocate_first_fit(layout) }) } unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { self.heap.lock(|heap| heap.deallocate(ptr, layout)); } }