nx_robot_hal.nx
buildroot/runtime/nx_robot_hal.nx
about
nx_robot_hal.nx -- SOVEREIGN fail-safe hardware-write DRIVER (the HAL the generated firmware binds
to). This is the never-brick-critical rung (#26): the layer that actually writes actuator outputs
and reads sensors. NEVER-BRICK BY CONSTRUCTION + proven MECHANICALLY by the gate (not promised):
* every actuator write is CLAMPED to a safe envelope [HW_SAFE_MIN, HW_SAFE_MAX] before it lands
-- no command, however large/negative/malicious, can escape it (defense-in-depth even if the
firmware's own clamp were wrong);
* pins default to SAFE (0 / disabled) on init;
* a WATCHDOG forces an e-stop (all outputs safe) if not kicked;
* E-STOP is latched and zeroes every output;
* sensor readings are range-checked (out-of-range => invalid => firmware goes safe).
Backend here is a MOCK device (an i64 register array) so the whole chain is gate-provable WITHOUT
real hardware. HONEST: binding these to a real board's MMIO addresses (the actual GPIO/PWM/step
registers) is the final step and needs the bench -- but the fail-safe LOGIC is real + proven now.
State layout (i64 array hw): hw[0..HW_NP) = actual pin outputs; hw[HW_NP+p] = sensor[p];
hw[2*HW_NP] = watchdog counter; hw[2*HW_NP+1] = estop latch.
license_tier: ORIGINAL expect_exit: 0
dependencies 1 imports · 1 importers
imports: nx_syscalls.nx
imported by: nx_robot_hal_gate.nx
structs
| none |
consts
| 19 | const HW_NP: i64 = 32 |
| 20 | const HW_SAFE_MAX: i64 = 400 // actuator output ceiling (e.g. step-rate / current cap) |
| 21 | const HW_SAFE_MIN: i64 = 0 - 400 |
| 22 | const HW_SENSOR_MIN: i64 = 0 |
| 23 | const HW_SENSOR_MAX: i64 = 4095 // 12-bit ADC |
| 24 | const HW_WD_LIMIT: i64 = 100 // watchdog ticks before auto e-stop |
functions
| 27 | func hwd_new() -> *i64 |
| 34 | func hwd_init_pin(hw: *i64, pin: i64) -> i64 { hw[pin] = 0; return 0 } // safe default |
| 37 | func hwd_estop(hw: *i64) -> i64 |
| 46 | func hwd_drive(hw: *i64, pin: i64, u: i64) -> i64 called by 1: main |
| 56 | func hwd_drive_raw(hw: *i64, pin: i64, u: i64) -> i64 { hw[pin] = u; return u } called by 1: main |
| 59 | func hwd_out(hw: *i64, pin: i64) -> i64 { return hw[pin] } called by 1: main |
| 61 | func hwd_set_sensor(hw: *i64, pin: i64, val: i64) -> i64 { hw[HW_NP + pin] = val; return 0 } |
| 62 | func hwd_read_sensor(hw: *i64, pin: i64) -> i64 { return hw[HW_NP + pin] } |
| 65 | func hwd_sensor_invalid(s: i64) -> i64 called by 1: main |
| 72 | func hwd_wd_kick(hw: *i64) -> i64 { hw[2 * HW_NP] = 0; return 0 } |
| 73 | func hwd_wd_tick(hw: *i64) -> i64 |
| 78 | func hwd_estopped(hw: *i64) -> i64 { return hw[2 * HW_NP + 1] } called by 1: main |