TinyComputers.io

Sponsors

More Articles

Two Addresses, One Page: Finding the Firmware Bug Behind NetBSD Corruption on the Milk-V Mars

NetBSD booted on my Milk-V Mars, joined the network, and then overwrote its own kernel with pkgsrc file data under sustained write load. The evidence first pointed at a double allocation inside UVM. That diagnosis was wrong. A custom PGAUDIT kernel, a Mars-shaped QEMU target, 256 permanent canary pages, and a controlled cache-flush experiment in DDB eventually showed two physical addresses exactly 4 GiB apart reaching the same DDR backing. The unsafe 8 GiB map came from a blank EEPROM and U-Boot SPL's private memory default. This is the sequel to my original bring-up article: the wrong theories, the two device trees hiding in one boot chain, the one-line firmware correction, and the 600-second hardware A/B that contained the corruption.

The Same Bad Luck, Quietly: Why a Fleet of Cheap Boards Feels Flakier Than One Old Xeon

My single-board computers hang, drop USB, and eat SD cards in ways my old Xeon server never does, and "you get what you pay for" is a shrug, not an explanation. So this is an attempt at the actual explanation: where the money goes in a server-class machine, why none of it shows up on a spec sheet, and why the same bit flip that increments a counter on the Xeon becomes an unwitnessed mystery hang on a NanoPi. Power delivery, SD card physics, tablet silicon versus mainframe silicon, Google's DRAM study, one Heidegger digression, and the parts of the missing margin you can buy back with a real power supply, a watchdog timer, and three idle boards' worth of Kubernetes.

FreeBSD on a 2011 MacBook Pro: Fifteen Years of Progress, and Per Core It's a Tie

I put a 2011 MacBook Pro running FreeBSD 15.1 through the same Rust compile benchmark as my single-board computer fleet. It lands sixth of nine at 131.00s - behind a Raspberry Pi 5, ahead of a Banana Pi CM5-Pro. But normalized per core and per gigahertz, a 2011 Sandy Bridge core and a 2023 Cortex-A76 do the same amount of work to within 0.3%. Also: why SHA-256 is 5.7x slower here, how the ZFS ARC nearly sold me a 2.86 GB/s hard drive, and two benchmark results I threw out.

The Config Language That Was Already There: A Ballistics REPL Written in Lattice

Every serious calculator eventually grows a configuration language — YAML, TOML, a bespoke parser — and then grows the loop of frustration that comes with it. This is what happened when I refused to write that layer, and instead made an existing programming language do the job: a stateful ballistics laboratory written entirely in Lattice, driving a Rust solver over a process boundary, with no native extension and no C ABI. A case study in what you get when the scripting language and the config language are the same language.

The Bullet Doesn't Go Where You Point It

A bullet fired at a target a thousand yards away does not travel in the direction you aimed it. It falls thirty feet, drifts a foot sideways from its own spin, and gets nudged by the rotation of the Earth. This is a piece about the Rust engine I wrote to predict all of that — how you test physics when you have no oracle, why the hard bugs were never in the equations, and the one problem worth charging for: solving ballistics backwards.

FriendlyElec NanoPC-T6N Review: The Fastest Board on My Bench, and the Benchmark That Outgrew Itself

Hands-on review of the FriendlyElec NanoPC-T6N, a Rockchip RK3588 SBC with 16 GB RAM, dual 2.5GbE, and a 6 TOPS NPU running Debian 13 on FriendlyELEC's BSP. It posts the fastest ARM compile time on my bench (52.55s), pushes 2.19 GB/s of AES-128-GCM, and never throttles - peaking at 56.4C under sustained eight-core load. Also the story of why my standard benchmark stopped being comparable to its own history, and what the microSD it shipped booting from is costing it.

Topics

Reading Series

Written by Alex Jokela Software engineer by trade, tinkerer by nature, single-board computer hoarder by choice. More about me →