code wiki / (root) / nx_robot_firmware_gate.nx

nx_robot_firmware_gate.nx source

↩ module page · 126 lines · 6172 B

1// nx_robot_firmware_gate.nx -- R-ROBO-4 GATE: MCU firmware generation + fail-safe behaviour. 2// Generates NishiLang firmware for a control board, writes the real .nx artifact, and VERIFIES: 3// (1) the emitted firmware contains the never-brick STRUCTURE (clamp + watchdog + safe-state + loop); 4// (2) it embeds the board SPEC (setpoint/umax/pins) verbatim; 5// (3) host-sim NORMAL run converges to setpoint (the generated control law works); 6// (4) NEVER-BRICK clamp: command never exceeds UMAX; 7// (5) FAULT -> SAFE-STATE: with a sensor-loss fault injected, the generated firmware does NOT run 8// away (commands safe, position stays bounded); 9// (6) NEGATIVE CONTROL: a NAIVE firmware (no safe-state) with the SAME fault DOES run away -- 10// proving the generated safe-state is doing real work. 11// 100% sovereign, integer-only. license_tier: ORIGINAL expect_exit: 0 12import "nx_syscalls.nx" 13import "nx_robot_firmware.nx" 14 15func sw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 16func sn(v: i64) -> i64 { 17 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 18 var m: i64 = v 19 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 20 let d: *u8 = sys_mmap(24); var k: i64 = 0 21 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 let o: *u8 = sys_mmap(24); var i: i64 = 0 23 while i < k { o[i] = d[k - 1 - i]; i = i + 1 } 24 sys_write(1, o, k); return 0 25} 26func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 27func contains(hay: *u8, haylen: i64, needle: *u8) -> i64 { 28 let nl: i64 = slen(needle) 29 if nl == 0 { return 1 } 30 var i: i64 = 0 31 while i + nl <= haylen { 32 var j: i64 = 0 33 var ok: i64 = 1 34 while j < nl { if hay[i + j] != needle[j] { ok = 0; j = nl } else { j = j + 1 } } 35 if ok == 1 { return 1 } 36 i = i + 1 37 } 38 return 0 39} 40func check(name: *u8, cond: i64, tot: *i64) -> i64 { 41 if cond == 1 { sw(" ok " as *u8); tot[0] = tot[0] + 1 } 42 else { sw(" FAIL " as *u8); tot[1] = tot[1] + 1 } 43 sw(name); sw("\n" as *u8) 44 return 0 45} 46func abs_i(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 47 48func main() -> i64 { 49 let tot: *i64 = sys_mmap(16) as *i64 50 tot[0] = 0; tot[1] = 0 51 sw("=== nx_robot_firmware_gate R-ROBO-4 -- MCU firmware generation + fail-safe (never-brick) ===\n" as *u8) 52 53 let setpoint: i64 = 1000 54 let kp: i64 = 200 55 let umax: i64 = 300 56 let wd: i64 = 1000 57 let pin_step: i64 = 17 58 let pin_sensor: i64 = 34 59 60 let cap: i64 = 65536 61 let out: *u8 = sys_mmap(cap) 62 let flen: i64 = firmware_emit(setpoint, kp, umax, wd, pin_step, pin_sensor, out) 63 sw(" generated firmware bytes=" as *u8); sn(flen); sw("\n" as *u8) 64 let fd: i64 = sys_openat_wr("knowledge/nx_fw_demo_robot.nx" as *u8, 0x1a4) 65 if fd >= 0 { sys_write(fd, out, flen); sys_close(fd); sw(" wrote knowledge/nx_fw_demo_robot.nx (generated Nishi firmware)\n" as *u8) } 66 else { sw(" (artifact write skipped)\n" as *u8) } 67 68 // (1) never-brick structure present 69 var okstruct: i64 = 1 70 if contains(out, flen, "func fw_clamp(" as *u8) == 0 { okstruct = 0 } 71 if contains(out, flen, "func fw_safe_state(" as *u8) == 0 { okstruct = 0 } 72 if contains(out, flen, "FW_WATCHDOG_TICKS" as *u8) == 0 { okstruct = 0 } 73 if contains(out, flen, "while 1 == 1" as *u8) == 0 { okstruct = 0 } 74 if contains(out, flen, "hw_drive_step(FW_PIN_STEP, 0)" as *u8) == 0 { okstruct = 0 } 75 if contains(out, flen, "import \"nx_syscalls.nx\"" as *u8) == 0 { okstruct = 0 } 76 check("emitted firmware has never-brick STRUCTURE (clamp+watchdog+safe-state+loop)" as *u8, okstruct, tot) 77 78 // (2) board spec embedded verbatim 79 var okspec: i64 = 1 80 if contains(out, flen, "FW_SETPOINT: i64 = 1000" as *u8) == 0 { okspec = 0 } 81 if contains(out, flen, "FW_UMAX: i64 = 300" as *u8) == 0 { okspec = 0 } 82 if contains(out, flen, "FW_PIN_STEP: i64 = 17" as *u8) == 0 { okspec = 0 } 83 if contains(out, flen, "FW_PIN_SENSOR: i64 = 34" as *u8) == 0 { okspec = 0 } 84 check("emitted firmware embeds the board SPEC (setpoint/umax/pins) verbatim" as *u8, okspec, tot) 85 86 let load: i64 = 3 87 let inertia: i64 = 4 88 let ticks: i64 = 200 89 let mc: *i64 = sys_mmap(8) as *i64 90 let ra: *i64 = sys_mmap(8) as *i64 91 92 // (3) normal run converges (no fault: fault_at = ticks) 93 let pn: i64 = fw_run(setpoint, kp, umax, load, inertia, ticks, ticks, 1, mc, ra) 94 sw(" NORMAL: final pos=" as *u8); sn(pn); sw(" maxcmd=" as *u8); sn(mc[0]); sw(" runaway=" as *u8); sn(ra[0]); sw("\n" as *u8) 95 var ok3: i64 = 0 96 if abs_i(setpoint - pn) <= 30 { ok3 = 1 } 97 check("generated control law CONVERGES to setpoint (normal operation)" as *u8, ok3, tot) 98 99 // (4) never-brick clamp 100 var ok4: i64 = 0 101 if mc[0] <= umax { ok4 = 1 } 102 check("NEVER-BRICK: command never exceeds UMAX" as *u8, ok4, tot) 103 104 // (5) fault -> safe-state: inject sensor loss at t=50; generated firmware must NOT run away 105 let mc2: *i64 = sys_mmap(8) as *i64 106 let ra2: *i64 = sys_mmap(8) as *i64 107 let pf: i64 = fw_run(setpoint, kp, umax, load, inertia, ticks, 50, 1, mc2, ra2) 108 sw(" FAULT+SAFE: final pos=" as *u8); sn(pf); sw(" runaway=" as *u8); sn(ra2[0]); sw(" (safe-state holds)\n" as *u8) 109 var ok5: i64 = 0 110 if ra2[0] == 0 { ok5 = 1 } 111 check("FAULT -> SAFE-STATE: generated firmware does NOT run away on sensor loss" as *u8, ok5, tot) 112 113 // (6) negative control: naive firmware (no safe-state) with the same fault runs away 114 let mc3: *i64 = sys_mmap(8) as *i64 115 let ra3: *i64 = sys_mmap(8) as *i64 116 let pb: i64 = fw_run(setpoint, kp, umax, load, inertia, ticks, 50, 0, mc3, ra3) 117 sw(" NAIVE+FAULT: final pos=" as *u8); sn(pb); sw(" runaway=" as *u8); sn(ra3[0]); sw(" (unsafe)\n" as *u8) 118 var ok6: i64 = 0 119 if ra3[0] == 1 { ok6 = 1 } 120 check("NEG-CONTROL: naive firmware (no safe-state) DOES run away (safe-state earns its keep)" as *u8, ok6, tot) 121 122 sw("=== VERDICT pass=" as *u8); sn(tot[0]); sw(" fail=" as *u8); sn(tot[1]); sw(" ===\n" as *u8) 123 if tot[1] == 0 { sys_exit(0) } 124 sys_exit(1) 125 return 1 126}