Skip to content

Commit f447854

Browse files
committed
Add a macro to make initialization easier
1 parent 8437c09 commit f447854

File tree

6 files changed

+76
-15
lines changed

6 files changed

+76
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Added a `init` macro to make initialization easier.
13+
814
## [v0.6.0] - 2024-09-01
915

1016
### Added

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static HEAP: Heap = Heap::empty();
3131
#[entry]
3232
fn main() -> ! {
3333
// Initialize the allocator BEFORE you use it
34+
embedded_alloc::init!(HEAP, 1024);
35+
// Alternatively, you can write the code directly to meet specific requirements.
3436
{
3537
use core::mem::MaybeUninit;
3638
const HEAP_SIZE: usize = 1024;

examples/global_alloc.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ static HEAP: Heap = Heap::empty();
1717
#[entry]
1818
fn main() -> ! {
1919
// Initialize the allocator BEFORE you use it
20-
{
21-
use core::mem::MaybeUninit;
22-
const HEAP_SIZE: usize = 1024;
23-
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
24-
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
25-
}
20+
embedded_alloc::init!(HEAP, 1024);
2621

2722
let mut xs = Vec::new();
2823
xs.push(1);

examples/llff_integration_test.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,7 @@ fn test_allocator_api() {
6363

6464
#[entry]
6565
fn main() -> ! {
66-
{
67-
const HEAP_SIZE: usize = 1024;
68-
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
69-
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
70-
}
66+
embedded_alloc::init!(HEAP, 1024);
7167

7268
#[allow(clippy::type_complexity)]
7369
let tests: &[(fn() -> (), &'static str)] = &[

examples/tlsf_integration_test.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,7 @@ fn test_allocator_api() {
8181

8282
#[entry]
8383
fn main() -> ! {
84-
{
85-
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
86-
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
87-
}
84+
embedded_alloc::init!(HEAP, HEAP_SIZE);
8885

8986
#[allow(clippy::type_complexity)]
9087
let tests: &[(fn() -> (), &'static str)] = &[

src/lib.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,68 @@ mod tlsf;
1212
pub use llff::Heap as LlffHeap;
1313
#[cfg(feature = "tlsf")]
1414
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

Comments
 (0)