esp_wifi/compat/
malloc.rs

1#[unsafe(no_mangle)]
2pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
3    trace!("alloc {}", size);
4
5    unsafe extern "C" {
6        fn esp_wifi_allocate_from_internal_ram(size: usize) -> *mut u8;
7    }
8
9    let ptr = unsafe { esp_wifi_allocate_from_internal_ram(size) };
10
11    if ptr.is_null() {
12        warn!("Unable to allocate {} bytes", size);
13    }
14
15    ptr
16}
17
18#[unsafe(no_mangle)]
19pub unsafe extern "C" fn free(ptr: *mut u8) {
20    trace!("free {:?}", ptr);
21
22    if ptr.is_null() {
23        warn!("Attempt to free null pointer");
24        return;
25    }
26
27    unsafe extern "C" {
28        fn esp_wifi_deallocate_internal_ram(ptr: *mut u8);
29    }
30
31    unsafe {
32        esp_wifi_deallocate_internal_ram(ptr);
33    }
34}
35
36#[unsafe(no_mangle)]
37pub unsafe extern "C" fn calloc(number: u32, size: usize) -> *mut u8 {
38    trace!("calloc {} {}", number, size);
39
40    let total_size = number as usize * size;
41    unsafe {
42        let ptr = malloc(total_size);
43
44        if !ptr.is_null() {
45            for i in 0..total_size as isize {
46                ptr.offset(i).write_volatile(0);
47            }
48        }
49
50        ptr
51    }
52}
53
54#[unsafe(no_mangle)]
55unsafe extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
56    trace!("realloc {:?} {}", ptr, new_size);
57
58    unsafe extern "C" {
59        fn memcpy(d: *mut u8, s: *const u8, l: usize);
60    }
61
62    unsafe {
63        let p = malloc(new_size);
64        if !p.is_null() && !ptr.is_null() {
65            let len = usize::min(
66                (ptr as *const u32).sub(1).read_volatile() as usize,
67                new_size,
68            );
69            memcpy(p, ptr, len);
70            free(ptr);
71        }
72        p
73    }
74}
75
76#[cfg(feature = "esp-alloc")]
77#[doc(hidden)]
78#[unsafe(no_mangle)]
79pub extern "C" fn esp_wifi_free_internal_heap() -> usize {
80    esp_alloc::HEAP.free_caps(esp_alloc::MemoryCapability::Internal.into())
81}
82
83#[cfg(feature = "esp-alloc")]
84#[doc(hidden)]
85#[unsafe(no_mangle)]
86pub extern "C" fn esp_wifi_allocate_from_internal_ram(size: usize) -> *mut u8 {
87    let total_size = size + 4;
88    unsafe {
89        let ptr = esp_alloc::HEAP.alloc_caps(
90            esp_alloc::MemoryCapability::Internal.into(),
91            core::alloc::Layout::from_size_align_unchecked(total_size, 4),
92        );
93
94        if ptr.is_null() {
95            return ptr;
96        }
97
98        *(ptr as *mut usize) = total_size;
99        ptr.offset(4)
100    }
101}
102
103#[cfg(feature = "esp-alloc")]
104#[doc(hidden)]
105#[unsafe(no_mangle)]
106pub extern "C" fn esp_wifi_deallocate_internal_ram(ptr: *mut u8) {
107    use core::alloc::GlobalAlloc;
108
109    unsafe {
110        let ptr = ptr.offset(-4);
111        let total_size = *(ptr as *const usize);
112
113        esp_alloc::HEAP.dealloc(
114            ptr,
115            core::alloc::Layout::from_size_align_unchecked(total_size, 4),
116        )
117    }
118}
119
120// Polyfill the InternalMemory allocator
121#[cfg(not(feature = "esp-alloc"))]
122mod esp_alloc {
123    use core::{alloc::Layout, ptr::NonNull};
124
125    use allocator_api2::alloc::{AllocError, Allocator};
126
127    /// An allocator that uses internal memory only.
128    pub struct InternalMemory;
129
130    unsafe impl Allocator for InternalMemory {
131        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
132            unsafe extern "C" {
133                fn esp_wifi_allocate_from_internal_ram(size: usize) -> *mut u8;
134            }
135            let raw_ptr = unsafe { esp_wifi_allocate_from_internal_ram(layout.size()) };
136            let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
137            Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
138        }
139
140        unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
141            unsafe extern "C" {
142                fn esp_wifi_deallocate_internal_ram(ptr: *mut u8);
143            }
144            unsafe {
145                esp_wifi_deallocate_internal_ram(ptr.as_ptr());
146            }
147        }
148    }
149}
150
151pub(crate) use esp_alloc::InternalMemory;