esp_alloc/
allocators.rs

1#[cfg(feature = "nightly")]
2use core::alloc::{AllocError as CoreAllocError, Allocator as CoreAllocator};
3use core::{
4    alloc::{GlobalAlloc, Layout},
5    ptr::NonNull,
6};
7
8use allocator_api2::alloc::{AllocError, Allocator};
9use enumset::EnumSet;
10
11use crate::MemoryCapability;
12
13fn allocate_caps(
14    capabilities: EnumSet<MemoryCapability>,
15    layout: Layout,
16) -> Result<NonNull<[u8]>, AllocError> {
17    let raw_ptr = unsafe { crate::HEAP.alloc_caps(capabilities, layout) };
18    let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
19    Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
20}
21
22use crate::EspHeap;
23
24unsafe impl Allocator for EspHeap {
25    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
26        let raw_ptr = unsafe { self.alloc(layout) };
27        let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
28        Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
29    }
30
31    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
32        unsafe {
33            crate::HEAP.dealloc(ptr.as_ptr(), layout);
34        }
35    }
36}
37
38#[cfg(feature = "nightly")]
39unsafe impl CoreAllocator for EspHeap {
40    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CoreAllocError> {
41        let raw_ptr = unsafe { self.alloc(layout) };
42        let ptr = NonNull::new(raw_ptr).ok_or(CoreAllocError)?;
43        Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
44    }
45
46    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
47        unsafe {
48            crate::HEAP.dealloc(ptr.as_ptr(), layout);
49        }
50    }
51}
52
53/// An allocator that uses all configured, available memory.
54pub struct AnyMemory;
55
56unsafe impl Allocator for AnyMemory {
57    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
58        allocate_caps(EnumSet::empty(), layout)
59    }
60
61    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
62        unsafe {
63            crate::HEAP.dealloc(ptr.as_ptr(), layout);
64        }
65    }
66}
67
68#[cfg(feature = "nightly")]
69unsafe impl CoreAllocator for AnyMemory {
70    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CoreAllocError> {
71        allocate_caps(EnumSet::empty(), layout).map_err(|_| CoreAllocError)
72    }
73
74    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
75        unsafe {
76            crate::HEAP.dealloc(ptr.as_ptr(), layout);
77        }
78    }
79}
80
81/// An allocator that uses internal memory only.
82pub struct InternalMemory;
83
84unsafe impl Allocator for InternalMemory {
85    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
86        allocate_caps(EnumSet::from(MemoryCapability::Internal), layout)
87    }
88
89    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
90        unsafe {
91            crate::HEAP.dealloc(ptr.as_ptr(), layout);
92        }
93    }
94}
95
96#[cfg(feature = "nightly")]
97unsafe impl CoreAllocator for InternalMemory {
98    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CoreAllocError> {
99        allocate_caps(EnumSet::from(MemoryCapability::Internal), layout).map_err(|_| CoreAllocError)
100    }
101
102    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
103        unsafe {
104            crate::HEAP.dealloc(ptr.as_ptr(), layout);
105        }
106    }
107}
108
109/// An allocator that uses external (PSRAM) memory only.
110pub struct ExternalMemory;
111
112unsafe impl Allocator for ExternalMemory {
113    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
114        allocate_caps(EnumSet::from(MemoryCapability::External), layout)
115    }
116
117    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
118        unsafe {
119            crate::HEAP.dealloc(ptr.as_ptr(), layout);
120        }
121    }
122}
123
124#[cfg(feature = "nightly")]
125unsafe impl CoreAllocator for ExternalMemory {
126    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CoreAllocError> {
127        allocate_caps(EnumSet::from(MemoryCapability::External), layout).map_err(|_| CoreAllocError)
128    }
129
130    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
131        unsafe {
132            crate::HEAP.dealloc(ptr.as_ptr(), layout);
133        }
134    }
135}