generated from sirlilpanda/kicad-project-template-actionless
Added the zig_main project to software for zig based implementation of code for robot
This commit is contained in:
326
software/zig_main/imports/heap.zig
Normal file
326
software/zig_main/imports/heap.zig
Normal file
@@ -0,0 +1,326 @@
|
||||
const sys = @import("sys");
|
||||
const std = @import("std");
|
||||
const errors = @import("error");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
// read: https://github.com/espressif/esp-idf/blob/97d95853572ab74f4769597496af9d5fe8b6bdea/components/heap/include/esp_heap_caps.h#L29-L53
|
||||
// ---------------------------------------------------------------------------
|
||||
// Caps — packed struct matching esp_heap_caps.h bit positions exactly.
|
||||
//
|
||||
// Bit layout (matches MALLOC_CAP_* defines):
|
||||
// 0 exec (only when CONFIG_HEAP_HAS_EXEC_HEAP)
|
||||
// 1 32bit
|
||||
// 2 8bit
|
||||
// 3 dma
|
||||
// 4- 9 pid2..pid7
|
||||
// 10 spiram
|
||||
// 11 internal
|
||||
// 12 default
|
||||
// 13 iram_8bit
|
||||
// 14 retention
|
||||
// 15 rtcram
|
||||
// 16 tcm
|
||||
// 17 dma_desc_ahb
|
||||
// 18 dma_desc_axi
|
||||
// 19 cache_aligned
|
||||
// 20 simd
|
||||
// 21-30 (reserved)
|
||||
// 31 invalid
|
||||
// ---------------------------------------------------------------------------
|
||||
pub const Caps = packed struct(u32) {
|
||||
exec: bool = false, // bit 0 — requires CONFIG_HEAP_HAS_EXEC_HEAP
|
||||
@"32bit": bool = false, // bit 1
|
||||
@"8bit": bool = false, // bit 2
|
||||
dma: bool = false, // bit 3
|
||||
pid2: bool = false, // bit 4
|
||||
pid3: bool = false, // bit 5
|
||||
pid4: bool = false, // bit 6
|
||||
pid5: bool = false, // bit 7
|
||||
pid6: bool = false, // bit 8
|
||||
pid7: bool = false, // bit 9
|
||||
spiram: bool = false, // bit 10
|
||||
internal: bool = false, // bit 11
|
||||
default: bool = false, // bit 12
|
||||
iram_8bit: bool = false, // bit 13
|
||||
retention: bool = false, // bit 14
|
||||
rtcram: bool = false, // bit 15
|
||||
tcm: bool = false, // bit 16
|
||||
dma_desc_ahb: bool = false, // bit 17
|
||||
dma_desc_axi: bool = false, // bit 18
|
||||
cache_aligned: bool = false, // bit 19
|
||||
simd: bool = false, // bit 20
|
||||
_reserved: u10 = 0, // bits 21-30
|
||||
invalid: bool = false, // bit 31
|
||||
|
||||
/// Cast to the raw u32 value the heap_caps_* C functions expect.
|
||||
pub fn toRaw(self: Caps) u32 {
|
||||
return @bitCast(self);
|
||||
}
|
||||
|
||||
/// Re-hydrate from a raw C bitmask (e.g. value returned by a C API).
|
||||
pub fn fromRaw(raw: u32) Caps {
|
||||
return @bitCast(raw);
|
||||
}
|
||||
|
||||
// -- Named presets matching common ESP-IDF usage patterns ---------------
|
||||
|
||||
/// General-purpose heap (equivalent to malloc/calloc).
|
||||
pub const default_caps: Caps = .{ .default = true };
|
||||
/// Internal RAM, byte-addressable.
|
||||
pub const internal_caps: Caps = .{ .internal = true, .@"8bit" = true };
|
||||
/// DMA-capable internal RAM.
|
||||
pub const dma_caps: Caps = .{ .dma = true, .@"8bit" = true, .internal = true };
|
||||
/// External SPI RAM, byte-addressable.
|
||||
pub const spiram_caps: Caps = .{ .spiram = true, .@"8bit" = true };
|
||||
/// RTC fast memory (survives deep sleep).
|
||||
pub const rtcram_caps: Caps = .{ .rtcram = true };
|
||||
/// Tightly-coupled memory.
|
||||
pub const tcm_caps: Caps = .{ .tcm = true };
|
||||
/// Executable memory (requires CONFIG_HEAP_HAS_EXEC_HEAP).
|
||||
pub const exec_caps: Caps = .{ .exec = true };
|
||||
/// Cache-line aligned memory.
|
||||
pub const cache_aligned_caps: Caps = .{ .cache_aligned = true, .default = true };
|
||||
};
|
||||
|
||||
// Verify the bit layout matches the C header at compile time.
|
||||
comptime {
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .exec = true })) == (1 << 0));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .@"32bit" = true })) == (1 << 1));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .@"8bit" = true })) == (1 << 2));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .dma = true })) == (1 << 3));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .spiram = true })) == (1 << 10));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .internal = true })) == (1 << 11));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .default = true })) == (1 << 12));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .simd = true })) == (1 << 20));
|
||||
std.debug.assert(@as(u32, @bitCast(Caps{ .invalid = true })) == (1 << 31));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// HeapCapsAllocator
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub const HeapCapsAllocator = struct {
|
||||
caps: Caps = Caps.default_caps,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(caps: ?Caps) Self {
|
||||
return .{ .caps = caps orelse Caps.default_caps };
|
||||
}
|
||||
|
||||
pub fn allocator(self: *Self) std.mem.Allocator {
|
||||
return .{
|
||||
.ptr = self,
|
||||
.vtable = &.{
|
||||
.alloc = alloc,
|
||||
.resize = resize,
|
||||
.remap = remap,
|
||||
.free = free,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn dump(self: Self) void {
|
||||
sys.heap_caps_dump(self.caps.toRaw());
|
||||
}
|
||||
pub fn allocatedSize(_: Self, ptr: ?*anyopaque) usize {
|
||||
return sys.heap_caps_get_allocated_size(ptr);
|
||||
}
|
||||
pub fn largestFreeBlock(self: Self) usize {
|
||||
return sys.heap_caps_get_largest_free_block(self.caps.toRaw());
|
||||
}
|
||||
pub fn totalSize(self: Self) usize {
|
||||
return sys.heap_caps_get_total_size(self.caps.toRaw());
|
||||
}
|
||||
pub fn freeSize(self: Self) usize {
|
||||
return sys.heap_caps_get_free_size(self.caps.toRaw());
|
||||
}
|
||||
pub fn minimumFreeSize(self: Self) usize {
|
||||
return sys.heap_caps_get_minimum_free_size(self.caps.toRaw());
|
||||
}
|
||||
pub fn internalFreeSize(_: Self) usize {
|
||||
return sys.esp_get_free_internal_heap_size();
|
||||
}
|
||||
|
||||
fn alloc(ctx: *anyopaque, len: usize, alignment: std.mem.Alignment, _: usize) ?[*]u8 {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
return @ptrCast(sys.heap_caps_aligned_alloc(
|
||||
alignment.toByteUnits(),
|
||||
len,
|
||||
self.caps.toRaw(),
|
||||
));
|
||||
}
|
||||
|
||||
fn resize(_: *anyopaque, buf: []u8, _: std.mem.Alignment, new_len: usize, _: usize) bool {
|
||||
if (new_len <= buf.len) return true;
|
||||
if (@TypeOf(sys.heap_caps_get_allocated_size) != void) {
|
||||
if (new_len <= sys.heap_caps_get_allocated_size(buf.ptr)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn remap(ctx: *anyopaque, memory: []u8, _: std.mem.Alignment, new_len: usize, _: usize) ?[*]u8 {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
return @ptrCast(sys.heap_caps_realloc(memory.ptr, new_len, self.caps.toRaw()));
|
||||
}
|
||||
|
||||
fn free(_: *anyopaque, buf: []u8, _: std.mem.Alignment, _: usize) void {
|
||||
sys.heap_caps_free(buf.ptr);
|
||||
if (builtin.mode == .Debug) {
|
||||
if (!sys.heap_caps_check_integrity_all(true))
|
||||
@panic("heap_caps: integrity check failed after free");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// MultiHeapAllocator
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub const MultiHeapAllocator = struct {
|
||||
handle: sys.multi_heap_handle_t = null,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(handle: sys.multi_heap_handle_t) Self {
|
||||
return .{ .handle = handle };
|
||||
}
|
||||
|
||||
pub fn allocator(self: *Self) std.mem.Allocator {
|
||||
return .{
|
||||
.ptr = self,
|
||||
.vtable = &.{
|
||||
.alloc = alloc,
|
||||
.resize = resize,
|
||||
.remap = remap,
|
||||
.free = free,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn allocatedSize(self: Self, p: ?*anyopaque) usize {
|
||||
return sys.multi_heap_get_allocated_size(self.handle, p);
|
||||
}
|
||||
pub fn freeSize(self: Self) usize {
|
||||
return sys.multi_heap_free_size(self.handle);
|
||||
}
|
||||
pub fn minimumFreeSize(self: Self) usize {
|
||||
return sys.multi_heap_minimum_free_size(self.handle);
|
||||
}
|
||||
|
||||
fn alloc(ctx: *anyopaque, len: usize, _: std.mem.Alignment, _: usize) ?[*]u8 {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
return @ptrCast(sys.multi_heap_malloc(self.handle, len));
|
||||
}
|
||||
|
||||
fn resize(ctx: *anyopaque, buf: []u8, _: std.mem.Alignment, new_len: usize, _: usize) bool {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
if (new_len <= buf.len) return true;
|
||||
if (@TypeOf(sys.multi_heap_get_allocated_size) != void) {
|
||||
if (new_len <= sys.multi_heap_get_allocated_size(self.handle, buf.ptr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn remap(ctx: *anyopaque, memory: []u8, _: std.mem.Alignment, new_len: usize, _: usize) ?[*]u8 {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
return @ptrCast(sys.multi_heap_realloc(self.handle, memory.ptr, new_len));
|
||||
}
|
||||
|
||||
fn free(ctx: *anyopaque, buf: []u8, _: std.mem.Alignment, _: usize) void {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
sys.multi_heap_free(self.handle, buf.ptr);
|
||||
if (builtin.mode == .Debug) {
|
||||
if (!sys.multi_heap_check(self.handle, true))
|
||||
@panic("multi_heap: integrity check failed after free");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// VPortAllocator
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub const VPortAllocator = struct {
|
||||
const Self = @This();
|
||||
|
||||
pub fn init() Self {
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn allocator(self: *Self) std.mem.Allocator {
|
||||
return .{
|
||||
.ptr = self,
|
||||
.vtable = &.{
|
||||
.alloc = alloc,
|
||||
.resize = resize,
|
||||
.remap = remap,
|
||||
.free = free,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn freeSize(_: Self) usize {
|
||||
return sys.xPortGetFreeHeapSize();
|
||||
}
|
||||
pub fn minimumFreeSize(_: Self) usize {
|
||||
return sys.xPortGetMinimumEverFreeHeapSize();
|
||||
}
|
||||
|
||||
fn alloc(_: *anyopaque, len: usize, _: std.mem.Alignment, _: usize) ?[*]u8 {
|
||||
return @ptrCast(sys.pvPortMalloc(len));
|
||||
}
|
||||
|
||||
fn resize(_: *anyopaque, buf: []u8, _: std.mem.Alignment, new_len: usize, _: usize) bool {
|
||||
return new_len <= buf.len;
|
||||
}
|
||||
|
||||
fn remap(_: *anyopaque, memory: []u8, _: std.mem.Alignment, new_len: usize, _: usize) ?[*]u8 {
|
||||
const new_ptr = sys.pvPortMalloc(new_len) orelse return null;
|
||||
@memcpy(@as([*]u8, @ptrCast(new_ptr))[0..@min(memory.len, new_len)], memory[0..@min(memory.len, new_len)]);
|
||||
sys.vPortFree(memory.ptr);
|
||||
return @ptrCast(new_ptr);
|
||||
}
|
||||
|
||||
fn free(_: *anyopaque, buf: []u8, _: std.mem.Alignment, _: usize) void {
|
||||
sys.vPortFree(buf.ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TRACE
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub const TRACE = struct {
|
||||
pub fn initStandalone(record_buffer: [*c]sys.heap_trace_record_t, num_records: usize) !void {
|
||||
try errors.espCheckError(sys.heap_trace_init_standalone(record_buffer, num_records));
|
||||
}
|
||||
pub fn initTohost() !void {
|
||||
try errors.espCheckError(sys.heap_trace_init_tohost());
|
||||
}
|
||||
pub fn start(mode: sys.heap_trace_mode_t) !void {
|
||||
try errors.espCheckError(sys.heap_trace_start(mode));
|
||||
}
|
||||
pub fn stop() !void {
|
||||
try errors.espCheckError(sys.heap_trace_stop());
|
||||
}
|
||||
pub fn @"resume"() !void {
|
||||
try errors.espCheckError(sys.heap_trace_resume());
|
||||
}
|
||||
pub fn getCount() usize {
|
||||
return sys.heap_trace_get_count();
|
||||
}
|
||||
pub fn get(index: usize, record: [*c]sys.heap_trace_record_t) !void {
|
||||
try errors.espCheckError(sys.heap_trace_get(index, record));
|
||||
}
|
||||
pub fn dump() void {
|
||||
sys.heap_trace_dump();
|
||||
}
|
||||
pub fn dumpCaps(caps: Caps) void {
|
||||
sys.heap_trace_dump_caps(caps.toRaw());
|
||||
}
|
||||
pub fn summary(sum: [*c]sys.heap_trace_summary_t) !void {
|
||||
try errors.espCheckError(sys.heap_trace_summary(sum));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user