summaryrefslogtreecommitdiff
path: root/src/hal.zig
diff options
context:
space:
mode:
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());
+}