alloc_cortex_m/lib.rs
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
//! A heap allocator for Cortex-M processors.
//!
//! Note that using this as your global allocator requires nightly Rust.
//!
//! # Example
//!
//! For a usage example, see `examples/global_alloc.rs`.
#![no_std]
use core::alloc::{GlobalAlloc, Layout};
use core::cell::RefCell;
use core::ptr::{self, NonNull};
use cortex_m::interrupt::Mutex;
use linked_list_allocator::Heap;
pub struct CortexMHeap {
heap: Mutex<RefCell<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(RefCell::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`.
///
/// # Safety
///
/// 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) {
cortex_m::interrupt::free(|cs| {
self.heap
.borrow(cs)
.borrow_mut()
.init(start_addr as *mut u8, size);
});
}
/// Returns an estimate of the amount of bytes in use.
pub fn used(&self) -> usize {
cortex_m::interrupt::free(|cs| self.heap.borrow(cs).borrow_mut().used())
}
/// Returns an estimate of the amount of bytes available.
pub fn free(&self) -> usize {
cortex_m::interrupt::free(|cs| self.heap.borrow(cs).borrow_mut().free())
}
}
unsafe impl GlobalAlloc for CortexMHeap {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
cortex_m::interrupt::free(|cs| {
self.heap
.borrow(cs)
.borrow_mut()
.allocate_first_fit(layout)
.ok()
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
})
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
cortex_m::interrupt::free(|cs| {
self.heap
.borrow(cs)
.borrow_mut()
.deallocate(NonNull::new_unchecked(ptr), layout)
});
}
}