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