@@ -12,3 +12,58 @@ mod tlsf;
1212pub use llff:: Heap as LlffHeap ;
1313#[ cfg( feature = "tlsf" ) ]
1414pub use tlsf:: Heap as TlsfHeap ;
15+
16+ /// Initialize the global heap.
17+ ///
18+ /// This macro creates a static, uninitialized memory buffer of the specified size and
19+ /// initializes the heap instance with that buffer.
20+ ///
21+ /// # Parameters
22+ ///
23+ /// - `$heap:ident`: The identifier of the global heap instance to initialize.
24+ /// - `$size:expr`: An expression evaluating to a `usize` that specifies the size of the
25+ /// static memory buffer in bytes. It must be **greater than zero**.
26+ ///
27+ /// # Safety
28+ ///
29+ /// This macro must be called first, before any operations on the heap, and **only once**.
30+ ///
31+ /// # Example
32+ ///
33+ /// ```rust
34+ /// use cortex_m_rt::entry;
35+ /// use embedded_alloc::LlffHeap as Heap;
36+ ///
37+ /// #[global_allocator]
38+ /// static HEAP: Heap = Heap::empty();
39+ ///
40+ /// #[entry]
41+ /// fn main() -> ! {
42+ /// // Initialize the allocator BEFORE you use it
43+ /// embedded_alloc::init!(HEAP, 1024);
44+ /// let mut xs = Vec::new();
45+ /// // ...
46+ /// }
47+ /// ```
48+ #[ macro_export]
49+ macro_rules! init {
50+ ( $heap: ident, $size: expr) => {
51+ assert!( $size > 0 ) ;
52+ // Ensure the heap is static.
53+ let static_heap: & ' static Heap = & $heap;
54+
55+ use core:: sync:: atomic:: AtomicBool ;
56+ use core:: sync:: atomic:: Ordering ;
57+ // Ensure it is called only once.
58+ static CALL_ONCE : AtomicBool = AtomicBool :: new( false ) ;
59+ assert_eq!( CALL_ONCE . load( Ordering :: Acquire ) , false ) ;
60+ CALL_ONCE . store( true , Ordering :: Release ) ;
61+
62+ static mut HEAP_MEM : [ core:: mem:: MaybeUninit <u8 >; $size] =
63+ [ core:: mem:: MaybeUninit :: uninit( ) ; $size] ;
64+ unsafe {
65+ #[ allow( static_mut_refs) ]
66+ $heap. init( & raw mut HEAP_MEM as usize , $size)
67+ }
68+ } ;
69+ }
0 commit comments