summaryrefslogtreecommitdiff
path: root/src/hal.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-25 12:40:53 -0300
committerGabriel Schneider <[email protected]>2026-08-25 12:46:51 -0300
commitf5f8068fac59b4f16046c2022c2fc7c7e447ef4c (patch)
tree2731a3ed4e51cae09e184e25778eded5fc37d1f5 /src/hal.zig
downloadesp32p4-f5f8068fac59b4f16046c2022c2fc7c7e447ef4c.tar.gz
esp32p4-f5f8068fac59b4f16046c2022c2fc7c7e447ef4c.zip
zig-p4: pure-Zig ESP32-P4 toolchain
build.zig generates the linker script and drives Zig's own LLD; tools/image.zig turns the ELF into a flashable image and tools/{rom,serial}.zig speak the mask ROM loader over the UART. No CMake, ninja, idf.py, esptool, or external linker. src/soc.zig is a comptime register model over ESP-IDF's own *_reg.h headers; src/hal/ adds peripheral sequences; src/io/ implements std.Io for the chip; src/oracle/ diffs this HAL against ESP-IDF's on the die.
Diffstat (limited to 'src/hal.zig')
-rw-r--r--src/hal.zig55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/hal.zig b/src/hal.zig
new file mode 100644
index 0000000..c62ea2b
--- /dev/null
+++ b/src/hal.zig
@@ -0,0 +1,55 @@
+//! ESP32-P4 hardware abstraction, on top of ESP-IDF's register macros and nothing else.
+//!
+//! The register *numbers* come from `@import("regs")`, which is `zig translate-c` over ESP-IDF's
+//! own `*_reg.h` headers, so no address, shift or mask in this file is a re-derivation of IDF's -
+//! they are IDF's, as evaluated by clang. What this file adds is the part macros cannot express:
+//! the sequences. Clock-gate before reset, reset before configure, configure before enable; divider
+//! arithmetic; which bits must move together in one store.
+//!
+//! Scope is low-level hardware. Video encode, image signal processing, 2D blitting and the display
+//! and camera serial interfaces are deliberately absent; so is anything needing an OS.
+//!
+//! Every peripheral here is checked against ESP-IDF's own `*_ll.h` implementation of the same
+//! operation, in one image, on the die - see `examples/differ.zig` and `tools/differ.zig`.
+
+const std = @import("std");
+const regs = @import("regs");
+const mmio = @import("mmio");
+
+pub const Reg = mmio.Reg;
+pub const Field = mmio.Field;
+
+comptime {
+ // The register set is per-silicon-revision, and the two sets share macro *names* while
+ // disagreeing on 61 values: AHB_DMA_INFIFO_CNT_CH0 is bits [7:2] under hw_ver1 and [14:8] under
+ // hw_ver3. A module built from the wrong set is therefore silently wrong rather than absent, so
+ // the build stamps which one it used and this refuses to compile against anything else. This
+ // board is a rev v1.3 die, which is what hw_ver1 describes.
+ if (regs.ZIG_P4_HW_VER != 1) @compileError(
+ "this HAL targets the pre-v3 ESP32-P4 register set (hw_ver1); rebuild with -Didf-hw-ver=1",
+ );
+}
+
+pub const gpio = @import("hal/gpio.zig");
+pub const rwdt = @import("hal/rwdt.zig");
+pub const clkrst = @import("hal/clkrst.zig");
+pub const intr = @import("hal/intr.zig");
+pub const systimer = @import("hal/systimer.zig");
+pub const timg = @import("hal/timg.zig");
+pub const ledc = @import("hal/ledc.zig");
+pub const uart = @import("hal/uart.zig");
+pub const i2c = @import("hal/i2c.zig");
+pub const sdmmc = @import("hal/sdmmc.zig");
+
+// Force semantic analysis of every peripheral's decls, not just the ones a test happens to call:
+// a wrong `Field.of` pair is a compile error, and an unanalysed function never raises it.
+//
+// `std.testing.refAllDeclsRecursive` was what this said, and Zig 0.16 does not have it - only
+// `refAllDecls` survives (`/usr/lib/zig/std/testing.zig:1213`). Nothing noticed, because no test
+// step in build.zig uses this file as a root: `zig build test` roots are tools/image_test.zig,
+// src/mmio.zig and the five src/net + src/io files, and `hal` reaches them only as an imported
+// *module*, whose tests a test binary does not run. So every `test` in src/hal/*.zig is currently
+// compiled by nothing. One line in build.zig's root list fixes that; see this slice's report.
+test {
+ std.testing.refAllDecls(@This());
+}