Skip to content

Commit 8842c58

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

File tree

8 files changed

+77
-14
lines changed

8 files changed

+77
-14
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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ static HEAP: Heap = Heap::empty();
3131
#[entry]
3232
fn main() -> ! {
3333
// Initialize the allocator BEFORE you use it
34+
unsafe {
35+
embedded_alloc::init!(HEAP, 1024);
36+
}
37+
// Alternatively, you can write the code directly to meet specific requirements.
3438
{
3539
use core::mem::MaybeUninit;
3640
const HEAP_SIZE: usize = 1024;

examples/global_alloc.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@ 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) }
20+
unsafe {
21+
embedded_alloc::init!(HEAP, 1024);
2522
}
2623

2724
let mut xs = Vec::new();

examples/llff_integration_test.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,8 @@ 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) }
66+
unsafe {
67+
embedded_alloc::init!(HEAP, 1024);
7068
}
7169

7270
#[allow(clippy::type_complexity)]

examples/tlsf_integration_test.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,8 @@ 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) }
84+
unsafe {
85+
embedded_alloc::init!(HEAP, HEAP_SIZE);
8786
}
8887

8988
#[allow(clippy::type_complexity)]

src/lib.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,48 @@ mod tlsf;
1212
pub use llff::Heap as LlffHeap;
1313
#[cfg(feature = "tlsf")]
1414
pub 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+
/// It internally calls `Heap::init(...)` on the heap,
31+
/// so `Heap::init(...)` should not be called directly if this macro is used.
32+
///
33+
/// # Example
34+
///
35+
/// ```rust
36+
/// use cortex_m_rt::entry;
37+
/// use embedded_alloc::LlffHeap as Heap;
38+
///
39+
/// #[global_allocator]
40+
/// static HEAP: Heap = Heap::empty();
41+
///
42+
/// #[entry]
43+
/// fn main() -> ! {
44+
/// // Initialize the allocator BEFORE you use it
45+
/// unsafe {
46+
/// embedded_alloc::init!(HEAP, 1024);
47+
/// }
48+
/// let mut xs = Vec::new();
49+
/// // ...
50+
/// }
51+
/// ```
52+
#[macro_export]
53+
macro_rules! init {
54+
($heap:ident, $size:expr) => {
55+
static mut HEAP_MEM: [::core::mem::MaybeUninit<u8>; $size] =
56+
[::core::mem::MaybeUninit::uninit(); $size];
57+
$heap.init(&raw mut HEAP_MEM as usize, $size)
58+
};
59+
}

src/llff.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::alloc::{GlobalAlloc, Layout};
2-
use core::cell::RefCell;
2+
use core::cell::{Cell, RefCell};
33
use core::ptr::{self, NonNull};
44

55
use critical_section::Mutex;
@@ -8,6 +8,7 @@ use linked_list_allocator::Heap as LLHeap;
88
/// A linked list first fit heap.
99
pub struct Heap {
1010
heap: Mutex<RefCell<LLHeap>>,
11+
once_flag: Mutex<Cell<bool>>,
1112
}
1213

1314
impl Heap {
@@ -18,6 +19,7 @@ impl Heap {
1819
pub const fn empty() -> Heap {
1920
Heap {
2021
heap: Mutex::new(RefCell::new(LLHeap::empty())),
22+
once_flag: Mutex::new(Cell::new(false)),
2123
}
2224
}
2325

@@ -46,7 +48,12 @@ impl Heap {
4648
/// - This function must be called exactly ONCE.
4749
/// - `size > 0`
4850
pub unsafe fn init(&self, start_addr: usize, size: usize) {
51+
assert!(size > 0);
4952
critical_section::with(|cs| {
53+
let once_flag = self.once_flag.borrow(cs);
54+
assert!(!once_flag.get());
55+
once_flag.set(true);
56+
5057
self.heap
5158
.borrow(cs)
5259
.borrow_mut()

src/tlsf.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::alloc::{GlobalAlloc, Layout};
2-
use core::cell::RefCell;
2+
use core::cell::{Cell, RefCell};
33
use core::ptr::{self, NonNull};
44

55
use const_default::ConstDefault;
@@ -11,6 +11,7 @@ type TlsfHeap = Tlsf<'static, usize, usize, { usize::BITS as usize }, { usize::B
1111
/// A two-Level segregated fit heap.
1212
pub struct Heap {
1313
heap: Mutex<RefCell<TlsfHeap>>,
14+
once_flag: Mutex<Cell<bool>>,
1415
}
1516

1617
impl Heap {
@@ -21,6 +22,7 @@ impl Heap {
2122
pub const fn empty() -> Heap {
2223
Heap {
2324
heap: Mutex::new(RefCell::new(ConstDefault::DEFAULT)),
25+
once_flag: Mutex::new(Cell::new(false)),
2426
}
2527
}
2628

@@ -49,7 +51,12 @@ impl Heap {
4951
/// - This function must be called exactly ONCE.
5052
/// - `size > 0`
5153
pub unsafe fn init(&self, start_addr: usize, size: usize) {
54+
assert!(size > 0);
5255
critical_section::with(|cs| {
56+
let once_flag = self.once_flag.borrow(cs);
57+
assert!(!once_flag.get());
58+
once_flag.set(true);
59+
5360
let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size);
5461
self.heap
5562
.borrow(cs)

0 commit comments

Comments
 (0)