#[repr(C)]
pub struct HeapStats_t {
pub xAvailableHeapSpaceInBytes: usize,
pub xSizeOfLargestFreeBlockInBytes: usize,
pub xSizeOfSmallestFreeBlockInBytes: usize,
pub xNumberOfFreeBlocks: usize,
pub xMinimumEverFreeBytesRemaining: usize,
pub xNumberOfSuccessfulAllocations: usize,
pub xNumberOfSuccessfulFrees: usize,
}
#[repr(C)]
pub struct HeapRegion_t {
pub pucStartAddress: *mut u8,
pub xSizeInBytes: usize,
}
#[cfg(feature = "heap-4")]
mod heap_4;
#[cfg(feature = "heap-4")]
pub use heap_4::*;
#[cfg(feature = "heap-4")]
pub use heap_4::FreeRtosAllocator;
#[cfg(all(feature = "heap-5", not(feature = "heap-4")))]
mod heap_5;
#[cfg(all(feature = "heap-5", not(feature = "heap-4")))]
pub use heap_5::*;
#[cfg(all(feature = "heap-5", not(feature = "heap-4")))]
pub use heap_5::FreeRtosAllocator;
#[cfg(all(feature = "heap-5", not(feature = "heap-4")))]
pub use heap_5::HeapRegion;
#[cfg(all(feature = "alloc", not(any(feature = "heap-4", feature = "heap-5"))))]
mod alloc_impl {
use alloc::alloc::{alloc, dealloc, Layout};
use core::ffi::c_void;
use core::ptr;
static mut ALLOCATED_BYTES: usize = 0;
const ALLOCATION_ALIGNMENT: usize = {
let port_alignment = crate::port::portBYTE_ALIGNMENT;
let metadata_alignment = core::mem::align_of::<usize>();
if port_alignment > metadata_alignment {
port_alignment
} else {
metadata_alignment
}
};
const ALLOCATION_HEADER_SIZE: usize = {
let mask = ALLOCATION_ALIGNMENT - 1;
(core::mem::size_of::<usize>() + mask) & !mask
};
#[inline(always)]
unsafe fn add_allocated_bytes(size: usize) {
crate::port::portENTER_CRITICAL();
ALLOCATED_BYTES += size;
crate::port::portEXIT_CRITICAL();
}
#[inline(always)]
unsafe fn subtract_allocated_bytes(size: usize) {
crate::port::portENTER_CRITICAL();
ALLOCATED_BYTES -= size;
crate::port::portEXIT_CRITICAL();
}
#[inline(always)]
fn allocated_bytes() -> usize {
crate::port::portENTER_CRITICAL();
let allocated = unsafe { ALLOCATED_BYTES };
crate::port::portEXIT_CRITICAL();
allocated
}
pub unsafe fn pvPortMalloc(xWantedSize: usize) -> *mut c_void {
if xWantedSize == 0 {
return ptr::null_mut();
}
let total_size = match xWantedSize.checked_add(ALLOCATION_HEADER_SIZE) {
Some(size) => size,
None => return ptr::null_mut(),
};
let layout = match Layout::from_size_align(total_size, ALLOCATION_ALIGNMENT) {
Ok(l) => l,
Err(_) => return ptr::null_mut(),
};
let ptr = alloc(layout);
if ptr.is_null() {
return ptr::null_mut();
}
*(ptr as *mut usize) = total_size;
add_allocated_bytes(total_size);
ptr.add(ALLOCATION_HEADER_SIZE) as *mut c_void
}
pub unsafe fn vPortFree(pv: *mut c_void) {
if pv.is_null() {
return;
}
let size_ptr = (pv as *mut u8).sub(ALLOCATION_HEADER_SIZE) as *mut usize;
let total_size = *size_ptr;
let layout = Layout::from_size_align_unchecked(total_size, ALLOCATION_ALIGNMENT);
subtract_allocated_bytes(total_size);
dealloc(size_ptr as *mut u8, layout);
}
pub fn xPortGetFreeHeapSize() -> usize {
usize::MAX - allocated_bytes()
}
pub fn xPortGetMinimumEverFreeHeapSize() -> usize {
xPortGetFreeHeapSize()
}
pub unsafe fn pvPortCalloc(xNum: usize, xSize: usize) -> *mut c_void {
let total = match xNum.checked_mul(xSize) {
Some(t) => t,
None => return ptr::null_mut(),
};
let ptr = pvPortMalloc(total);
if !ptr.is_null() {
ptr::write_bytes(ptr as *mut u8, 0, total);
}
ptr
}
pub fn vPortInitialiseBlocks() {}
pub unsafe fn vPortHeapResetState() {}
pub fn xPortResetHeapMinimumEverFreeHeapSize() {}
pub unsafe fn vPortGetHeapStats(pxHeapStats: *mut super::HeapStats_t) {
if pxHeapStats.is_null() {
return;
}
unsafe {
(*pxHeapStats).xAvailableHeapSpaceInBytes = xPortGetFreeHeapSize();
(*pxHeapStats).xSizeOfLargestFreeBlockInBytes = xPortGetFreeHeapSize();
(*pxHeapStats).xSizeOfSmallestFreeBlockInBytes = 0;
(*pxHeapStats).xNumberOfFreeBlocks = 1;
(*pxHeapStats).xMinimumEverFreeBytesRemaining = xPortGetMinimumEverFreeHeapSize();
(*pxHeapStats).xNumberOfSuccessfulAllocations = 0;
(*pxHeapStats).xNumberOfSuccessfulFrees = 0;
}
}
}
#[cfg(all(feature = "alloc", not(any(feature = "heap-4", feature = "heap-5"))))]
pub use alloc_impl::*;
#[cfg(not(any(feature = "heap-4", feature = "heap-5", feature = "alloc")))]
mod stub_impl {
use core::ffi::c_void;
pub unsafe fn pvPortMalloc(_xWantedSize: usize) -> *mut c_void {
panic!("pvPortMalloc called but no heap feature is enabled (use `heap-4` or `alloc`)");
}
pub unsafe fn vPortFree(_pv: *mut c_void) {
panic!("vPortFree called but no heap feature is enabled");
}
pub fn xPortGetFreeHeapSize() -> usize {
0
}
pub fn xPortGetMinimumEverFreeHeapSize() -> usize {
0
}
pub unsafe fn pvPortCalloc(_xNum: usize, _xSize: usize) -> *mut c_void {
panic!("pvPortCalloc called but no heap feature is enabled");
}
pub fn vPortInitialiseBlocks() {}
pub unsafe fn vPortHeapResetState() {}
pub fn xPortResetHeapMinimumEverFreeHeapSize() {}
pub unsafe fn vPortGetHeapStats(pxHeapStats: *mut super::HeapStats_t) {
if pxHeapStats.is_null() {
return;
}
unsafe {
(*pxHeapStats).xAvailableHeapSpaceInBytes = 0;
(*pxHeapStats).xSizeOfLargestFreeBlockInBytes = 0;
(*pxHeapStats).xSizeOfSmallestFreeBlockInBytes = 0;
(*pxHeapStats).xNumberOfFreeBlocks = 0;
(*pxHeapStats).xMinimumEverFreeBytesRemaining = 0;
(*pxHeapStats).xNumberOfSuccessfulAllocations = 0;
(*pxHeapStats).xNumberOfSuccessfulFrees = 0;
}
}
}
#[cfg(not(any(feature = "heap-4", feature = "heap-5", feature = "alloc")))]
pub use stub_impl::*;