### Heap::init(start_addr, size) Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Low-level initialization method that accepts an explicit start address and byte size. Useful when you need fine-grained control over the memory region used. Must be called exactly once; panics on double-init or size == 0. ```APIDOC ## Heap::init(start_addr, size) ### Description Low-level initialization method that accepts an explicit start address and byte size. Useful when you need fine-grained control over the memory region used — for example, placing the heap in a specific linker section or in external RAM. Must be called exactly once; panics on double-init or `size == 0`. ### Usage ```rust #![no_std] #![no_main] extern crate alloc; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { const HEAP_SIZE: usize = 2048; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; // Manually provide start address and size unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } let s = alloc::string::String::from("Hello, embedded world!"); // s contains "Hello, embedded world!" loop {} } ``` ``` -------------------------------- ### Initialize Heap with Heap::init() Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Use `Heap::init()` for low-level initialization, providing an explicit start address and byte size. This is useful for placing the heap in specific memory regions. It must be called exactly once and panics on double-initialization or zero size. ```rust #![no_std] #![no_main] extern crate alloc; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { const HEAP_SIZE: usize = 2048; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; // Manually provide start address and size unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } let s = alloc::string::String::from("Hello, embedded world!"); // s contains "Hello, embedded world!" loop {} } ``` -------------------------------- ### Heap::empty() Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Creates a new, uninitialized heap allocator instance as a const fn. This must be called to declare the static global allocator before the program starts; it does not allocate any memory itself. ```APIDOC ## Heap::empty() ### Description Creates a new, uninitialized heap allocator instance as a `const fn`. This must be called to declare the `static` global allocator before the program starts; it does not allocate any memory itself. ### Usage ```rust #![no_std] #![no_main] use embedded_alloc::LlffHeap as Heap; // Declare global allocator — zero cost, no memory used yet #[global_allocator] static HEAP: Heap = Heap::empty(); ``` ``` -------------------------------- ### init!(heap, size) Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Convenience macro that declares a static mut byte buffer of the given size and initializes the heap instance with it. Must be called exactly once before any allocation, and size must be greater than zero. Panics if called more than once or if size == 0. ```APIDOC ## init!(heap, size) ### Description Convenience macro that declares a `static mut` byte buffer of the given size and initializes the heap instance with it. Must be called exactly once before any allocation, and `size` must be greater than zero. Panics if called more than once or if `size == 0`. ### Usage ```rust #![no_std] #![no_main] extern crate alloc; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { // Initialize a 1 KiB heap — MUST happen before any alloc::* use unsafe { embedded_alloc::init!(HEAP, 1024); } // alloc types are now available let mut v: alloc::vec::Vec = alloc::vec![10, 20, 30]; v.push(40); // v == [10, 20, 30, 40] loop {} } ``` ``` -------------------------------- ### Initialize Heap with init! Macro Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt The `init!` macro declares a static mutable byte buffer and initializes the heap with it. This must be called exactly once before any allocations, and the size must be greater than zero. Panics if called more than once or if size is zero. ```rust #![no_std] #![no_main] extern crate alloc; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { // Initialize a 1 KiB heap — MUST happen before any alloc::* use unsafe { embedded_alloc::init!(HEAP, 1024); } // alloc types are now available let mut v: alloc::vec::Vec = alloc::vec![10, 20, 30]; v.push(40); // v == [10, 20, 30, 40] loop {} } ``` -------------------------------- ### Handle Heap Exhaustion with Panic Handler Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Demonstrates how to set up a panic handler to manage heap exhaustion. This is crucial for embedded systems where memory is limited and allocation failures can occur. ```rust #![no_std] #![no_main] extern crate alloc; use core::panic::PanicInfo; use cortex_m_rt::entry; use embedded_alloc::TlsfHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { // Very small heap — only 16 bytes unsafe { embedded_alloc::init!(HEAP, 16) } // Attempting to allocate 16 × u8 on a 16-byte TLSF heap // will fail because TLSF needs internal bookkeeping space. // This triggers a panic, caught by the handler below. let _vec = alloc::vec![0_u8; 16]; // panics: allocation failure loop {} } #[panic_handler] fn panic(info: &PanicInfo) -> ! { // Log the panic over a debug transport (e.g., RTT, semihosting) // defmt::error!("{}", info); // Halt or reset the device loop {} } ``` -------------------------------- ### Initialize LlffHeap Allocator Source: https://github.com/rust-embedded/embedded-alloc/blob/master/README.md Demonstrates the initialization of the LlffHeap global allocator. Ensure the allocator is initialized before use. The `embedded_alloc::init!` macro or manual initialization can be used. ```rust #![no_std] #![no_main] extern crate alloc; 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); } // Alternatively, you can write the code directly to meet specific requirements. { use core::mem::MaybeUninit; const HEAP_SIZE: usize = 1024; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } } // now the allocator is ready types like Box, Vec can be used. loop { /* .. */ } } ``` -------------------------------- ### Query Heap Usage with LlffHeap Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Demonstrates how to query the used bytes in the heap using `LlffHeap`. It verifies that `used()` reflects allocations and returns to zero after deallocation. ```rust #![no_std] #![no_main] extern crate alloc; use alloc::vec::Vec; use core::mem::size_of; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, 1024) } // Heap starts empty assert_eq!(HEAP.used(), 0); let mut xs: Vec = alloc::vec![1]; xs.push(2); xs.extend(&[3, 4]); // used() reflects the allocation: 4 × size_of::() = 16 bytes assert_eq!(HEAP.used(), size_of::() * xs.len()); drop(xs); // used() returns to 0 after deallocation assert_eq!(HEAP.used(), 0); loop {} } ``` -------------------------------- ### Basic LlffHeap Usage Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Demonstrates the basic usage of `LlffHeap` with standard Rust collection types like `Vec` and `String`. This is suitable for simple firmware with predictable memory lifetimes. ```rust #![no_std] #![no_main] extern crate alloc; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, 1024) } // Standard alloc types work out of the box let v = alloc::vec![1_u32, 2, 3, 4, 5]; let s = alloc::string::String::from("Hello, world!"); // v == [1, 2, 3, 4, 5] // s == "Hello, world!" loop {} } ``` -------------------------------- ### `LlffHeap` — Linked List First Fit allocator Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt `LlffHeap` uses a classic linked-list first-fit strategy backed by the `linked_list_allocator` crate. It has minimal code size overhead and is a good default choice for simple firmware with infrequent allocations and predictable lifetimes. ```APIDOC ## `LlffHeap` — Linked List First Fit allocator Enable with `features = ["llff"]` (included in the default feature set). `LlffHeap` uses a classic linked-list first-fit strategy backed by the `linked_list_allocator` crate. It has minimal code size overhead and is a good default choice for simple firmware with infrequent allocations and predictable lifetimes. ### Example ```rust #![no_std] #![no_main] extern crate alloc; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, 1024) } // Standard alloc types work out of the box let v = alloc::vec![1_u32, 2, 3, 4, 5]; let s = alloc::string::String::from("Hello, world!"); // v == [1, 2, 3, 4, 5] // s == "Hello, world!" loop {} } ``` ``` -------------------------------- ### Scoped Allocator with `allocator_api` Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Shows how to use the `allocator_api` feature (nightly Rust required) to back collections like `Vec` with a specific heap instance, enabling memory-isolated subsystems. ```rust #![feature(allocator_api)] #![no_std] #![no_main] extern crate alloc; use alloc::vec::Vec; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; // A dummy global allocator is required even when using allocator_api #[global_allocator] static GLOBAL_HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { // Global heap (1 KiB) unsafe { embedded_alloc::init!(GLOBAL_HEAP, 1024) } // Local, isolated 16-byte heap for a specific subsystem const LOCAL_SIZE: usize = 16; static mut LOCAL_MEM: [MaybeUninit; LOCAL_SIZE] = [MaybeUninit::uninit(); LOCAL_SIZE]; let local_heap = Heap::empty(); unsafe { local_heap.init(&raw mut LOCAL_MEM as usize, LOCAL_SIZE) } // Vec backed by the local heap — does NOT touch GLOBAL_HEAP let mut v: Vec = Vec::new_in(local_heap); v.push(0xCAFE); v.extend(&[0xDEAD, 0xFEED]); // v == [0xCAFE, 0xDEAD, 0xFEED] loop {} } ``` -------------------------------- ### Configure Cargo.toml for embedded-alloc Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Shows the necessary Cargo.toml configuration for using embedded-alloc with a Cortex-M target. It highlights the dependency on `critical-section` and how to enable a compatible implementation. ```toml # Cargo.toml [dependencies] # Heap allocator — both back-ends enabled by default embedded-alloc = "0.7.0" # Cortex-M runtime + critical-section implementation cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" # To use only one allocator back-end, disable default features: # embedded-alloc = { version = "0.7.0", default-features = false, features = ["tlsf"] } # To use the nightly allocator_api feature: # embedded-alloc = { version = "0.7.0", features = ["allocator_api"] } ``` -------------------------------- ### `TlsfHeap` — Two-Level Segregated Fit allocator Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt `TlsfHeap` provides O(1) allocation and deallocation with low fragmentation, making it well-suited for long-running firmware with many allocations and frees of varying sizes. It also implements `GlobalAlloc::realloc` natively for efficient resizing. ```APIDOC ## `TlsfHeap` — Two-Level Segregated Fit allocator Enable with `features = ["tlsf"]` (included in the default feature set). `TlsfHeap` provides O(1) allocation and deallocation with low fragmentation, making it well-suited for long-running firmware with many allocations and frees of varying sizes. It also implements `GlobalAlloc::realloc` natively for efficient resizing. ### Example ```rust #![no_std] #![no_main] extern crate alloc; use alloc::collections::LinkedList; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::TlsfHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); const HEAP_SIZE: usize = 30 * 1024; #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, HEAP_SIZE) } // TLSF invariant: used + free == total heap size assert_eq!(HEAP_SIZE, HEAP.free() + HEAP.used()); let initial_free = HEAP.free(); // Allocate 500 linked-list nodes let mut list: LinkedList = LinkedList::new(); for i in 0..250_i32 { list.push_back(i); } assert_eq!(list.len(), 250); // Drain the list and verify memory is recovered for _ in list.drain() {} assert_eq!(initial_free, HEAP.free()); // memory fully returned loop {} } ``` ``` -------------------------------- ### Declare Global Allocator with Heap::empty() Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Use `Heap::empty()` to declare an uninitialized static global allocator. This has zero cost and uses no memory until initialized. ```rust #![no_std] #![no_main] use embedded_alloc::LlffHeap as Heap; // Declare global allocator — zero cost, no memory used yet #[global_allocator] static HEAP: Heap = Heap::empty(); ``` -------------------------------- ### Query Free Heap Bytes with Heap::free() Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt The `free()` method returns an estimate of the remaining free bytes in the heap. This is thread-safe and relies on `critical-section`. For `LlffHeap`, it's computed from the linked-list allocator; for `TlsfHeap`, it sums unoccupied block sizes. ```rust #![no_std] #![no_main] extern crate alloc; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::TlsfHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { const HEAP_SIZE: usize = 4096; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } let mut vecs: alloc::vec::Vec> = alloc::vec::Vec::new(); // Allocate until less than 512 bytes remain while HEAP.free() > 512 { vecs.push(alloc::vec![1_u8; 64]); } // free < 512 here drop(vecs); // After drop, memory is returned to the heap // HEAP.free() rises back toward HEAP_SIZE loop {} } ``` -------------------------------- ### `allocator_api` feature — Use heap as a scoped `Allocator` Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Enabling the `allocator_api` feature (requires nightly Rust) implements the unstable `core::alloc::Allocator` trait for both heap types. This allows creating collection types (`Vec`, `LinkedList`, etc.) that are backed by a specific heap instance rather than the global allocator — useful for memory-isolated subsystems. ```APIDOC ## `allocator_api` feature — Use heap as a scoped `Allocator` Enabling the `allocator_api` feature (requires nightly Rust) implements the unstable `core::alloc::Allocator` trait for both heap types. This allows creating collection types (`Vec`, `LinkedList`, etc.) that are backed by a specific heap instance rather than the global allocator — useful for memory-isolated subsystems. ### Example ```rust #![feature(allocator_api)] #![no_std] #![no_main] extern crate alloc; use alloc::vec::Vec; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; // A dummy global allocator is required even when using allocator_api #[global_allocator] static GLOBAL_HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { // Global heap (1 KiB) unsafe { embedded_alloc::init!(GLOBAL_HEAP, 1024) } // Local, isolated 16-byte heap for a specific subsystem const LOCAL_SIZE: usize = 16; static mut LOCAL_MEM: [MaybeUninit; LOCAL_SIZE] = [MaybeUninit::uninit(); LOCAL_SIZE]; let local_heap = Heap::empty(); unsafe { local_heap.init(&raw mut LOCAL_MEM as usize, LOCAL_SIZE) } // Vec backed by the local heap — does NOT touch GLOBAL_HEAP let mut v: Vec = Vec::new_in(local_heap); v.push(0xCAFE); v.extend(&[0xDEAD, 0xFEED]); // v == [0xCAFE, 0xDEAD, 0xFEED] loop {} } ``` ``` -------------------------------- ### Heap::free() Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Returns an estimate of the number of free bytes remaining in the heap. Thread-safe via critical-section. ```APIDOC ## Heap::free() ### Description Returns an estimate of the number of free bytes remaining in the heap. For `LlffHeap` this is computed via the underlying linked-list allocator; for `TlsfHeap` it sums the `max_payload_size` of all unoccupied blocks. Thread-safe via `critical-section`. ### Usage ```rust #![no_std] #![no_main] extern crate alloc; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::TlsfHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { const HEAP_SIZE: usize = 4096; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } let mut vecs: alloc::vec::Vec> = alloc::vec::Vec::new(); // Allocate until less than 512 bytes remain while HEAP.free() > 512 { vecs.push(alloc::vec![1_u8; 64]); } // free < 512 here drop(vecs); // After drop, memory is returned to the heap // HEAP.free() rises back toward HEAP_SIZE loop {} } ``` ``` -------------------------------- ### `Heap::used()` — Query allocated heap bytes Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Returns an estimate of the bytes currently occupied in the heap. For `TlsfHeap`, computed as `raw_block_size - free()`. Together with `free()`, satisfies the invariant `used() + free() == heap_size` for `TlsfHeap`. Useful for firmware diagnostics and memory budget tracking. ```APIDOC ## `Heap::used()` — Query allocated heap bytes ### Description Returns an estimate of the bytes currently occupied in the heap. For `TlsfHeap`, computed as `raw_block_size - free()`. Together with `free()`, satisfies the invariant `used() + free() == heap_size` for `TlsfHeap`. Useful for firmware diagnostics and memory budget tracking. ### Example ```rust #![no_std] #![no_main] extern crate alloc; use alloc::vec::Vec; use core::mem::size_of; use cortex_m_rt::entry; use embedded_alloc::LlffHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, 1024) } // Heap starts empty assert_eq!(HEAP.used(), 0); let mut xs: Vec = alloc::vec![1]; xs.push(2); xs.extend(&[3, 4]); // used() reflects the allocation: 4 × size_of::() = 16 bytes assert_eq!(HEAP.used(), size_of::() * xs.len()); drop(xs); // used() returns to 0 after deallocation assert_eq!(HEAP.used(), 0); loop {} } ``` ``` -------------------------------- ### TlsfHeap Memory Invariant Check Source: https://context7.com/rust-embedded/embedded-alloc/llms.txt Verifies the memory invariant for `TlsfHeap` where `used + free == total heap size`. It allocates and deallocates memory to ensure it's fully recovered. ```rust #![no_std] #![no_main] extern crate alloc; use alloc::collections::LinkedList; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embedded_alloc::TlsfHeap as Heap; #[global_allocator] static HEAP: Heap = Heap::empty(); const HEAP_SIZE: usize = 30 * 1024; #[entry] fn main() -> ! { unsafe { embedded_alloc::init!(HEAP, HEAP_SIZE) } // TLSF invariant: used + free == total heap size assert_eq!(HEAP_SIZE, HEAP.free() + HEAP.used()); let initial_free = HEAP.free(); // Allocate 500 linked-list nodes let mut list: LinkedList = LinkedList::new(); for i in 0..250_i32 { list.push_back(i); } assert_eq!(list.len(), 250); // Drain the list and verify memory is recovered for _ in list.drain() {} assert_eq!(initial_free, HEAP.free()); // memory fully returned loop {} } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.