Crate esp_alloc

Source
Expand description

A no_std heap allocator for RISC-V and Xtensa processors from Espressif. Supports all currently available ESP32 devices.

NOTE: using this as your global allocator requires using Rust 1.68 or greater, or the nightly release channel.

§Using this as your Global Allocator

use esp_alloc as _;

fn init_heap() {
    const HEAP_SIZE: usize = 32 * 1024;
    static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();

    unsafe {
        esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
            HEAP.as_mut_ptr() as *mut u8,
            HEAP_SIZE,
            esp_alloc::MemoryCapability::Internal.into(),
        ));
    }
}

Alternatively, you can use the heap_allocator! macro to configure the global allocator with a given size:

esp_alloc::heap_allocator!(size: 32 * 1024);

§Using this with the nightly allocator_api-feature

Sometimes you want to have more control over allocations.

For that, it’s convenient to use the nightly allocator_api-feature, which allows you to specify an allocator for single allocations.

NOTE: To use this, you have to enable the crate’s nightly feature flag.

Create and initialize an allocator to use in single allocations:

static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();

fn init_psram_heap() {
    unsafe {
        PSRAM_ALLOCATOR.add_region(esp_alloc::HeapRegion::new(
            psram::psram_vaddr_start() as *mut u8,
            psram::PSRAM_BYTES,
            esp_alloc::MemoryCapability::External.into(),
        ));
    }
}

And then use it in an allocation:

let large_buffer: Vec<u8, _> = Vec::with_capacity_in(1048576, &PSRAM_ALLOCATOR);

Alternatively, you can use the psram_allocator! macro to configure the global allocator to use PSRAM:

let p = esp_hal::init(esp_hal::Config::default());
esp_alloc::psram_allocator!(p.PSRAM, esp_hal::psram);

You can also use the ExternalMemory allocator to allocate PSRAM memory with the global allocator:

let p = esp_hal::init(esp_hal::Config::default());
esp_alloc::psram_allocator!(p.PSRAM, esp_hal::psram);

let mut vec = Vec::<u32>::new_in(esp_alloc::ExternalMemory);

§allocator_api feature on stable Rust

esp-alloc implements the allocator trait from allocator_api2, which provides the nightly-only allocator_api features in stable Rust. The crate contains implementations for Box and Vec.

To use the allocator_api2 features, you need to add the crate to your Cargo.toml. Note that we do not enable the alloc feature by default, but you will need it for the Box and Vec types.

allocator-api2 = { version = "0.3", default-features = false, features = ["alloc"] }

With this, you can use the Box and Vec types from allocator_api2, with esp-alloc allocators:

let p = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 64000);
esp_alloc::psram_allocator!(p.PSRAM, esp_hal::psram);

let mut vec: Vec<u32, _> = Vec::new_in(esp_alloc::InternalMemory);

vec.push(0xabcd1234);
assert_eq!(vec[0], 0xabcd1234);

Note that if you use the nightly allocator_api feature, you can use the Box and Vec types from alloc. allocator_api2 is still available as an option, but types from allocator_api2 are not compatible with the standard library types.

§Heap stats

You can also get stats about the heap usage at anytime with:

let stats: HeapStats = esp_alloc::HEAP.stats();
// HeapStats implements the Display and defmt::Format traits, so you can
// pretty-print the heap stats.
println!("{}", stats);

Example output:

HEAP INFO
Size: 131068
Current usage: 46148
Max usage: 46148
Total freed: 0
Total allocated: 46148
Memory Layout:
Internal | ████████████░░░░░░░░░░░░░░░░░░░░░░░ | Used: 35% (Used 46148 of 131068, free: 84920)

§Feature Flags

  • nightly — Enable nightly rustc-only features, like feature(allocator_api).

  • defmt — Implement defmt::Format on certain types.

  • internal-heap-stats — Enable this feature if you want to keep stats about the internal heap usage such as:

    • Max memory usage since initialization of the heap
    • Total allocated memory since initialization of the heap
    • Total freed memory since initialization of the heap

    ⚠️ Note: Enabling this feature will require extra computation every time alloc/dealloc is called.

Macros§

heap_allocator
Initialize a global heap allocator providing a heap of the given size in bytes. This supports attributes.
psram_allocator
Initialize a global heap allocator backed by PSRAM

Structs§

AnyMemory
An allocator that uses all configured, available memory.
EspHeap
A memory allocator
ExternalMemory
An allocator that uses external (PSRAM) memory only.
HeapRegion
A memory region to be used as heap memory
HeapStats
Stats for a heap allocator
InternalMemory
An allocator that uses internal memory only.
RegionStats
Stats for a heap region

Enums§

MemoryCapability
Describes the properties of a memory region

Statics§

HEAP
The global allocator instance