Skip to content

Add a macro to make initialization easier #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added

- Added a `init` macro to make initialization easier.

## [v0.6.0] - 2024-09-01

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ allocator_api = []

# Use the Two-Level Segregated Fit allocator
tlsf = ["rlsf", "const-default"]
# Use the LinkedList first-fit allocator
# Use the LinkedList first-fit allocator
llff = ["linked_list_allocator"]

[dependencies]
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ static HEAP: Heap = Heap::empty();
#[entry]
fn main() -> ! {
// Initialize the allocator BEFORE you use it
unsafe {
embedded_alloc::init!(HEAP, 1024);
}
// Alternatively, you can write the code directly to meet specific requirements.
{
use core::mem::MaybeUninit;
const HEAP_SIZE: usize = 1024;
Expand Down
7 changes: 2 additions & 5 deletions examples/global_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ static HEAP: Heap = Heap::empty();
#[entry]
fn main() -> ! {
// Initialize the allocator BEFORE you use it
{
use core::mem::MaybeUninit;
const HEAP_SIZE: usize = 1024;
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
unsafe {
embedded_alloc::init!(HEAP, 1024);
}

let mut xs = Vec::new();
Expand Down
6 changes: 2 additions & 4 deletions examples/llff_integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,8 @@ fn test_allocator_api() {

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

#[allow(clippy::type_complexity)]
Expand Down
5 changes: 2 additions & 3 deletions examples/tlsf_integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,8 @@ fn test_allocator_api() {

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

#[allow(clippy::type_complexity)]
Expand Down
45 changes: 45 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,48 @@ mod tlsf;
pub use llff::Heap as LlffHeap;
#[cfg(feature = "tlsf")]
pub use tlsf::Heap as TlsfHeap;

/// Initialize the global heap.
///
/// This macro creates a static, uninitialized memory buffer of the specified size and
/// initializes the heap instance with that buffer.
///
/// # Parameters
///
/// - `$heap:ident`: The identifier of the global heap instance to initialize.
/// - `$size:expr`: An expression evaluating to a `usize` that specifies the size of the
/// static memory buffer in bytes. It must be **greater than zero**.
///
/// # Safety
///
/// This macro must be called first, before any operations on the heap, and **only once**.
/// It internally calls `Heap::init(...)` on the heap,
/// so `Heap::init(...)` should not be called directly if this macro is used.
///
/// # Example
///
/// ```rust
/// use cortex_m_rt::entry;
/// use embedded_alloc::LlffHeap as Heap;
///
/// #[global_allocator]
/// static HEAP: Heap = Heap::empty();
///
/// #[entry]
/// fn main() -> ! {
/// // Initialize the allocator BEFORE you use it
/// unsafe {
/// embedded_alloc::init!(HEAP, 1024);
/// }
/// let mut xs = Vec::new();
/// // ...
/// }
/// ```
#[macro_export]
macro_rules! init {
($heap:ident, $size:expr) => {
static mut HEAP_MEM: [::core::mem::MaybeUninit<u8>; $size] =
[::core::mem::MaybeUninit::uninit(); $size];
$heap.init(&raw mut HEAP_MEM as usize, $size)
};
}
9 changes: 8 additions & 1 deletion src/llff.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::alloc::{GlobalAlloc, Layout};
use core::cell::RefCell;
use core::cell::{Cell, RefCell};
use core::ptr::{self, NonNull};

use critical_section::Mutex;
Expand All @@ -8,6 +8,7 @@ use linked_list_allocator::Heap as LLHeap;
/// A linked list first fit heap.
pub struct Heap {
heap: Mutex<RefCell<LLHeap>>,
once_flag: Mutex<Cell<bool>>,
}

impl Heap {
Expand All @@ -18,6 +19,7 @@ impl Heap {
pub const fn empty() -> Heap {
Heap {
heap: Mutex::new(RefCell::new(LLHeap::empty())),
once_flag: Mutex::new(Cell::new(false)),
}
}

Expand Down Expand Up @@ -46,7 +48,12 @@ impl Heap {
/// - This function must be called exactly ONCE.
/// - `size > 0`
pub unsafe fn init(&self, start_addr: usize, size: usize) {
assert!(size > 0);
critical_section::with(|cs| {
let once_flag = self.once_flag.borrow(cs);
assert!(!once_flag.get());
once_flag.set(true);

self.heap
.borrow(cs)
.borrow_mut()
Expand Down
9 changes: 8 additions & 1 deletion src/tlsf.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::alloc::{GlobalAlloc, Layout};
use core::cell::RefCell;
use core::cell::{Cell, RefCell};
use core::ptr::{self, NonNull};

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

impl Heap {
Expand All @@ -21,6 +22,7 @@ impl Heap {
pub const fn empty() -> Heap {
Heap {
heap: Mutex::new(RefCell::new(ConstDefault::DEFAULT)),
once_flag: Mutex::new(Cell::new(false)),
}
}

Expand Down Expand Up @@ -49,7 +51,12 @@ impl Heap {
/// - This function must be called exactly ONCE.
/// - `size > 0`
pub unsafe fn init(&self, start_addr: usize, size: usize) {
assert!(size > 0);
critical_section::with(|cs| {
let once_flag = self.once_flag.borrow(cs);
assert!(!once_flag.get());
once_flag.set(true);

let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size);
self.heap
.borrow(cs)
Expand Down