@@ -12,3 +12,68 @@ mod tlsf;
12
12
pub use llff:: Heap as LlffHeap ;
13
13
#[ cfg( feature = "tlsf" ) ]
14
14
pub 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