diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/board_memory.zig | 34 | ||||
| -rw-r--r-- | src/pardes.zig | 72 |
2 files changed, 54 insertions, 52 deletions
diff --git a/src/board_memory.zig b/src/board_memory.zig index f99fc106..702b130d 100644 --- a/src/board_memory.zig +++ b/src/board_memory.zig @@ -296,11 +296,22 @@ pub fn poke(p: *Pardes, id: usize, argument: []const u8) !void { ) catch unreachable); } -/// `Hexdump <addr> [len]` — len bytes, 16 to a row, hex columns and an ASCII -/// gutter, in `hexdump -C`'s layout because that is the one everyone can -/// already read. BYTE reads, so a partial row at the end of the space is a -/// short row rather than a refusal, and no alignment is required: this is the -/// word you reach for when you do not yet know what is there. +/// Bytes per dumped row, and it is a different number on the board. +/// +/// `hexdump -C`'s sixteen is the layout everyone can already read, and it needs 79 columns: ten for +/// the address, forty-eight for the hex, a gap, and the eighteen-column ASCII gutter. The P4 drives +/// a 56-column grid of which seven go to the line-number gutter, so a sixteen-byte row wraps onto a +/// second display line and the columns stop lining up - which is the entire value of the layout. +/// +/// Eight fits in 46 and keeps every property that matters: address on the left, fixed-width hex +/// columns, ASCII on the right, and a gap at the halfway mark because the eye counts in fours and +/// eights rather than in sixteens. +const row_bytes: u32 = if (pardes.platform == .p4) 8 else 16; + +/// `Hexdump <addr> [len]` — len bytes, `row_bytes` to a row, hex columns and an ASCII gutter, in +/// `hexdump -C`'s layout because that is the one everyone can already read. BYTE reads, so a partial +/// row at the end of the space is a short row rather than a refusal, and no alignment is required: +/// this is the word you reach for when you do not yet know what is there. pub fn hexdump(p: *Pardes, id: usize, argument: []const u8) !void { var it = std.mem.tokenizeAny(u8, argument, " \t\r\n"); const addr = try parseAddr(it.next() orelse return Error.MissingAddress); @@ -312,15 +323,14 @@ pub fn hexdump(p: *Pardes, id: usize, argument: []const u8) !void { errdefer out.deinit(); try writeNote(&out.writer, e, requested, "bytes"); var row: u32 = 0; - while (row < e.count) : (row += 16) { - const n = @min(@as(u32, 16), e.count - row); - var bytes: [16]u8 = undefined; + while (row < e.count) : (row += row_bytes) { + const n = @min(row_bytes, e.count - row); + var bytes: [row_bytes]u8 = undefined; for (0..n) |i| bytes[i] = readByte(addr + row + @as(u32, @intCast(i))); try out.writer.print("0x{x:0>8} ", .{addr + row}); - for (0..16) |i| { - // hexdump -C's gap after the eighth column: the eye counts to - // eight, not to sixteen - if (i == 8) try out.writer.writeByte(' '); + for (0..row_bytes) |i| { + // The gap at the halfway mark: the eye counts to four or eight, not to sixteen. + if (i == row_bytes / 2) try out.writer.writeByte(' '); if (i < n) try out.writer.print(" {x:0>2}", .{bytes[i]}) else diff --git a/src/pardes.zig b/src/pardes.zig index 8d68cf22..691ee345 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -5747,50 +5747,42 @@ pub const Pardes = struct { // the honest description of a buffer on a board with no filesystem. // AND IT BOOTS WITH SOMETHING IN IT. An empty buffer is honest and useless: the three // words that make this board interesting take an address, and a board's address space is - // precisely the thing you cannot guess. So the boot buffer is a tour of it - every - // address below comes from this repository rather than from memory, which is why they are - // worth trusting: the two flash figures and the two RAM ones are the linker script's own - // ORIGINs (`05-zig-p4/build.zig`'s MEMORY block), and the peripheral bases are - // `DR_REG_*` from ESP-IDF's headers as `05-zig-p4/src/hal` uses them. + // precisely the thing you cannot guess. // - // Each command sits alone on its line because an argument list ends at the last argument: - // a trailing comment would be `ExtraArgument`, so the notes go above the lines they - // describe. Run one by putting the cursor on it, `x` to select the line, Tab to execute - - // the same two keystrokes as any other selection, because an output buffer is a file pane - // and these are ordinary words. + // SHORT, because the window is fourteen rows. The first draft opened with four lines of + // prose about there being no operating system, which is true, unhelpful, and cost a + // third of the screen before the first command. One header line earns its place; the + // rest of the screen is addresses. + // + // Each command sits alone on its line because an argument list ends at the last argument + // - a trailing comment would be `ExtraArgument` - so the labels go above. Every address + // is from this repository or from a session that read it on this die: the flash and RAM + // figures are the linker script's own ORIGINs (`05-zig-p4/build.zig`), the peripheral + // bases are the `DR_REG_*` values `05-zig-p4/src/hal` uses, and the two LP addresses at + // the end are named in ESP-IDF's own headers: 0x5011002c is LP_SYSTEM_REG_LP_STORE0, a + // general-purpose retention register that holds what you put in it, and 0x501101a4 is + // LP_SYSTEM_REG_RNG_DATA, the hardware random generator. Between them they demonstrate + // the whole point of a volatile read: one address gives back what was written and the + // other never gives the same answer twice. Both verified on this die. const content = try p.gpa.dupe(u8, - \\pardes on an ESP32-P4. No OS, no filesystem: - \\this buffer is text with nothing behind it. - \\Peek, Poke and Hexdump read the bus itself. - \\Numbers are hex, with or without 0x. - \\ - \\Select a line with x, then Tab to run it. - \\ - \\-- this image in flash: rodata, then code - \\Hexdump 40000020 60 - \\Hexdump 40050000 60 - \\ - \\-- L2MEM: firmware data, then editor heap - \\Hexdump 4ff00000 60 - \\Hexdump 4ff40000 60 + \\x selects a line, Tab runs it. Hex, 0x optional. \\ - \\-- the mask ROM, where ets_printf lives - \\Hexdump 4fc00000 40 - \\ - \\-- UART0: the console you are reading on + \\-- flash: this image's rodata, then its code + \\Hexdump 40000020 40 + \\Hexdump 40050000 40 + \\-- L2MEM: firmware data, then the editor's heap + \\Hexdump 4ff00000 40 + \\Hexdump 4ff40000 40 + \\-- the mask ROM + \\Hexdump 4fc00000 20 + \\-- UART0, the console you are reading this on \\Peek 500ca000 4 - \\ - \\-- systimer. Run twice: a register is not - \\-- memory, and the two reads differ. - \\Peek 500e2000 4 - \\ - \\-- GPIO_OUT, and pad 0's IO_MUX entry - \\Peek 500e0004 - \\Peek 500e1004 - \\ - \\-- Poke needs a value. Harmless: a W1TC - \\-- register clears nothing given no bits. - \\Poke 500e000c 0 + \\-- LP_STORE0: write a word, then read it back + \\Poke 5011002c deadbeef + \\Peek 5011002c + \\-- RNG_DATA: a register is not memory. Run twice. + \\Peek 501101a4 + \\Peek 501101a4 ); errdefer p.gpa.free(content); _ = try output_pane.open(p, 0, "", .{ .cmd = .New }, "", content); |
