The Crash You Haven't Had Yet
What Kode Dot Developers Need to Know About the SPI Bus Before They Hit the Wall
By Eric Becker — Fluid Fortune — April 2026
🤝 A Nod to the Ecosystem: Why We Love Kode Dot
If you have spent any time building for the ESP32-S3, you know exactly how fragmented the hardware space is. It is a Wild West of random development boards, mismatched screens, undocumented pinouts, and spaghetti-wire prototypes where half the community documentation is a three-year-old forum post that ends with "I figured it out, never mind."
That is exactly why what Quero, Luismi, and the Kode team have built is truly remarkable.
They did not just build another dev board. They built a consistent, beautifully designed, and well-documented pocket computer for makers. They took the friction out of the hardware. They proved there is massive demand for a cohesive, grab-and-go ESP32-S3 device with a real UI, integrated audio, a 9-axis IMU, modular expansion via a magnetic rear connector, and an app-based OS that treats your code like real software instead of one-time firmware flashes. Then they raised over $2 million on Kickstarter to prove the world agreed.
Their work pushing the boundaries of what this silicon can do was a direct inspiration while developing the architectural backbone of Pisces Moon OS. We are tackling the exact same limits of the S3 — just from different angles, on different hardware, toward different ends.
If you have not seen what they are building yet, you need to check them out and support the ecosystem:
- 🌐 Kode Dot website: https://kode.diy
- 🚀 Kode Dot Kickstarter: https://www.kickstarter.com/projects/kode/kode-dot
This post is not a criticism of that platform. It is a contribution to it — from someone who spent a month building on the same silicon, hitting a wall that the Kode Dot community will eventually hit too, and documenting exactly where the wall is and how to go around it.
I am the Court Jester of Vibe Coding. I built a different OS on a different device with the same ESP32-S3 chip. And I found something the Kode Dot team is going to need.
The Silicon Is a Match
The Kode Dot runs an ESP32-S3 dual-core Xtensa LX7 at 240MHz. My device — a LilyGO T-Deck Plus — runs the same chip. Same memory architecture. Same dual-core task allocation. Same FreeRTOS underneath. Same PSRAM. Same SPI bus behavior.
This matters more than it might seem. Because the problem I am going to describe is not a bug in the Kode Dot. It is a property of the ESP32-S3 hardware class. It does not matter which board you are on. If you push this chip hard enough — if you run multiple subsystems concurrently while they share hardware resources — you will find the wall.
The Kode Dot is going to push it hard enough. Intentionally and correctly. That is the whole point of the platform.
What Luismi's Team Just Did to the Problem Space
The recent hardware update deserves specific attention from an engineering perspective.
The Kode Dot now has a secondary ESP32-C5 chip handling WiFi 6 and 5GHz network scanning, alongside a Sub-GHz transceiver and NRF24 radio for proprietary 2.4GHz protocol analysis. Luismi called it the Holy Trinity of connectivity. From a capability standpoint, that is exactly right. This is one of the things that makes the Kode Dot genuinely different from everything else in this space — not just another ESP32 board, but a device with a coherent vision for what multi-radio connectivity should look like in a maker platform.
From a bus contention standpoint, they just made the problem I am about to describe significantly more complex — and significantly more important to solve.
The original T-Deck Plus configuration — the one I spent a month engineering around — had the MicroSD card and a LoRa radio sharing the SPI bus. That was enough to cause the crashes I am going to describe.
The Kode Dot now has to manage high-speed data between the main S3 processor, the high-resolution AMOLED display, MicroSD app loading, the secondary C5 chip handling WiFi 6 scanning, and multiple radio modules arriving via magnetic expansion connector. All of this happens on hardware that shares bus lines.
The problem did not get easier. It got more interesting. And the solution I am about to document is more relevant to the Kode Dot now than it would have been before that hardware update.
What the SPI Bus Is
The SPI bus is the communication highway connecting the ESP32-S3 to its peripherals. Multiple devices share this bus. They use separate chip-select signals — each device has its own enable line — but they share the underlying MOSI, MISO, and CLK lines.
Only one device may transmit at any given moment.
In KodeOS's current sequential app model, this constraint is invisible. One app runs. It uses whatever peripherals it needs. It exits. The next app runs. No conflict. This is correct and elegant architecture for the maker use case — and it is one of the things KodeOS gets genuinely right that most other ESP32 OS attempts do not.
The constraint becomes visible — violently visible — the moment you run persistent background processes concurrently with foreground applications while both need access to shared hardware. A logger writing to MicroSD while a radio scanner is actively transmitting. An app loading assets from SD card while a background process is communicating with the secondary C5 chip over shared lines.
When the constraint triggers, the result is a Guru Meditation error. The ESP32-S3's equivalent of a kernel panic. Immediate device reboot. No warning. No data recovery.
The Crash That Changes Addresses
Here is what makes this problem genuinely difficult to diagnose: the crash address changes every time.
The timing collision is non-deterministic. Two subsystems racing for the same hardware resource will collide at a slightly different moment on each run. The crash dump points to a different memory address each time, which means a developer reading the output sees what appears to be a random memory fault in an unrelated module. The display driver crashes on one run. The audio buffer crashes on the next. The SD card library crashes after that.
Every crash looks like a different bug. They are all the same bug.
I spent days on this before I understood what was happening. The diagnosis required correlating crash frequency across multiple field sessions in high-density RF environments — the crash becomes near-certain when the background process is writing to SD card multiple times per second, which only happens when there are enough networks nearby. On a bench with five devices in range, the collision window is narrow enough that it rarely triggers. In downtown Los Angeles with 80 WiFi access points in range, it becomes near-certain during any concurrent SD operation.
You cannot find this bug in a lab. You find it in the field. The Kode Dot community will find it when their apps get ambitious enough to run background processes. That is the right kind of ambitious. It just needs the Treaty first.
The SPI Bus Treaty
After diagnosing the problem, I designed a formal behavioral protocol to govern how every component in the OS interacts with the shared bus. I named it the SPI Bus Treaty — because that is what it is: a named agreement between competing subsystems about how to share a hardware resource without destroying each other.
The Treaty has four rules. They are not suggestions. Every component that touches the bus must follow all four.
Rule 1: Hit and Run. All bus operations follow a strict pattern: acquire the bus, complete the operation, release immediately. No component may hold the bus open across multiple operations or across a time delay. Complete the work. Release. The bus belongs to the next operation the moment you are done.
Rule 2: No Extended Holds. No operation may hold the SPI bus for an extended period. This prohibits patterns that seem reasonable in isolation — writing large files in a single sustained operation, performing in-place encryption during a write, formatting storage media while the system is running. All of these hold the bus long enough to cause collisions with concurrent operations.
Rule 3: Radio Traffic Management. When a radio or wireless operation is in progress, a shared boolean flag signals this state to every other subsystem. Background processes check this flag before initiating operations that would compete. The subsystems cannot both operate simultaneously. The flag is the software equivalent of a traffic signal on a shared road.
Rule 4: Metadata-Only Destructive Operations. Any operation that destroys or clears data must operate only on index files and metadata — never via a sustained write or format operation. A metadata delete takes milliseconds, well within Treaty timing budget. A format takes seconds and holds the bus long enough to guarantee collisions with concurrent subsystems.
The Historical Lineage
This is not a new class of problem. It has appeared throughout computing history every time competing subsystems share a hardware resource and someone has to decide the rules.
Unix filesystem locking conventions in the 1970s. The Apollo Guidance Computer's priority scheduling protocol in 1969. Nintendo's N64 RSP time budget in 1996. In every case, the solution was not hardware redesign. It was a formal behavioral protocol — a named standard that every component in the system was required to follow.
The SPI Bus Treaty is that standard for the ESP32-S3 hardware class. It did not exist before Pisces Moon OS. It exists now, and it belongs to the public technical literature.
The Proof
Ghost Engine is a persistent Core 0 process that wardrives, scans Bluetooth LE, and logs GPS coordinates continuously — regardless of what the operator is doing on Core 1. It was always running during the field tests. Without the Treaty, crashes were near-certain in downtown Los Angeles with 80 access points in range.
Treaty implemented. Zero crashes across sustained field operation in the same environment.
That is the proof. Not a lab benchmark. A field result, in a real urban environment, against real-world RF density.
The Ghost Engine never stops. The SPI Bus Treaty is why.
What This Means for Kode Dot Developers
KodeOS currently runs apps sequentially. This is correct. The Treaty problem does not currently arise — only one app touches the bus at a time.
The Treaty becomes relevant the moment a Kode Dot developer does any of the following:
- Runs a background logger or sensor monitor while a foreground app is active
- Snaps on a radio module via the magnetic expansion connector while loading app assets from MicroSD
- Runs WiFi 6 scanning via the C5 while the S3 is simultaneously writing to storage
- Builds anything with persistent state that needs to survive app switches
Every one of those use cases is exactly what Pablo is building the ecosystem to encourage. The developer tools Pablo is designing, the app store architecture the community is discussing, the ambitious apps this community will build — all of them push toward concurrent operations.
The Treaty is the protocol that makes concurrent operations safe on this hardware.
The Architecture Is Portable
The ESP32-S3 silicon is identical. The Ghost Engine dual-core architecture maps over. The Treaty logic maps over. The ELF module runtime — apps deploying from MicroSD without reflashing — maps over.
There are real divergences that deserve honest acknowledgment. Luismi built a different display system — AMOLED with different drivers and refresh characteristics than the T-Deck's LCD. The input mapping differs — Kode Dot's D-pad and face buttons versus the T-Deck's QWERTY keyboard and trackball. Any app ported between the two platforms needs a Hardware Abstraction Layer shim for display and input. That work is real and expected.
The memory architecture, the dual-core task allocation, the bus arbitration logic, and the Treaty itself — none of that changes. The math is the same. The silicon is the same. The problem is the same. The solution is the same.
The Offer
I am Eric Becker. I have been answering technical questions in the KodeDot Discord because the questions are interesting and I know the answers.
The SPI Bus Treaty is documented in full in the Pisces Moon OS Sovereignty White Paper: https://fluidfortune.com/sovereignty.html
The source code is in the public repository: https://github.com/FluidFortune/pisces-moon-os
The license is AGPL-3.0. If you want to implement the Treaty in KodeOS or in your own Kode Dot applications, the documentation is public. The reference implementation is public. The field validation is documented.
If Luismi or Pablo want to talk through the architecture — the bus arbitration protocol, the dual-core task allocation, the ELF runtime, the memory management approach — I am available. The goal is not competition. The goal is that Kode Dot ships with software as capable as its hardware deserves.
Build the ambitious thing. Just know where the wall is before you drive into it.
Eric Becker is the author of Pisces Moon OS — the first known documented implementation of persistent dual-core background tasking for field intelligence collection on the ESP32-S3 hardware class. The Ghost Engine and the SPI Bus Treaty are its two primary inventions. The SPI Bus Treaty is now part of the public technical literature.
Fluid Fortune — fluidfortune.com — forge@fluidfortune.com
The Ghost Engine never stops. The SPI Bus Treaty is why.