Cortex-A75
Cortex-M7
  ____ _  _ ____ _ ____ ___ _ ____ _  _    ___  ____ ____ ____ _   _
  |    |__| |__/ | [__   |  | |__| |\ |    |__] |___ |__/ |__/  \_/ 
  |___ |  | |  \ | ___]  |  | |  | | \|    |__] |___ |  \ |  \   |  
                        

Embedded Systems Software Engineer | Systems & Kernel Specialist


About Me

I'm an embedded software engineer working on safety-critical, real-time systems. Most of my work focuses on Linux and Barebox OS bring-up and low-level I/O driver development, along with hardware-software co-design and optimizing memory pipelines under hard real-time scheduling constraints. I also write firmware for coprocessors, though that tends to sit alongside the driver and OS work rather than being the main thing.

This page is a small tribute to the old academic homepages. There's no telemetry here, no tracking cookies, and no bloated frameworks. Just clean text, some C code, and a few terminal-style controls.

Professional Background

Over the past 8+ years, I've built software and drivers across several safety-critical domains:

  • Aerospace & Defense Systems:
    • Linux & Barebox SoC Integration: Handled bootloader and OS bring-up for a custom Cortex-A75 SoC, taking the secure boot chain from BootROM through Barebox and into the Linux kernel.
    • ARM Architecture Optimization: Wrote assembly and C-level optimizations for ARMv8-A pipelines, leaning on cache-aware layouts, lock-free queues, and AArch64 tuning to push data ingestion on high-throughput DMA engines.
    • IRAD Rust Research: Ran an Internal Research and Design (IRAD) effort looking into Rust's memory-safety guarantees and compiler validation models for real-time safety-critical defense software.
  • Training & Simulation Engineering: Wrote C software for flight weapons simulators, keeping low-latency, multi-threaded subsystems on VxWorks inside hard real-time execution bounds.
  • Industrial Automation Systems: Built C++ backend components for distributed industrial control loop engines, managing cascade and PID scheduling deadlines.

My usual toolchain is GCC/Clang, Yocto, GDB/JTAG debuggers, and Vim. I mostly write C, C++, and ARM Assembly, with Rust for secondary utilities.


Research & Development Laboratory

Notes on HDL/FPGA hardware design, QEMU system emulation, and device modeling.


1. HDL & FPGA Core Prototyping

Co-designing software and custom hardware accelerators means modeling system buses and logical pipelines first. I use SystemVerilog and VHDL to prototype soft cores, register interfaces, and custom DMA logic on FPGA fabric. Pushing processing pipelines down into dedicated hardware logic gives you tight, predictable cycle bounds for the timing-critical loops.

2. QEMU Device Emulation & Virtual Prototyping

Building bootloaders like Barebox and low-level kernel drivers before the custom silicon is ready means you need cycle-accurate models to develop against. I write custom QEMU machine configurations and peripheral models in C to stand in for the real hardware.

Once the interrupt handlers (IRQs), DMA registers, and memory-mapped address tables are modeled in QEMU, the same driver code can be tested and verified inside automated virtual integration environments. That takes hardware availability off the critical path and lets you validate early architecture decisions before anything is taped out.

That same interest in full-system emulation is what drives the System Terminal playground below. Pressing BOOT RISC-V starts a genuine 64-bit RISC-V machine, CPU, MMU, and virtio block/network devices and all, running entirely in your browser as WebAssembly. The emulator core is TinyEMU, written by Fabrice Bellard (the original author of QEMU and FFmpeg). I pair it with a small Alpine Linux image I build and host myself, so you can boot real Linux and compile C right from the browser.

3. ARM Architecture-Specific Optimization

I have a soft spot for low-level performance tuning and architecture-specific optimization on modern ARM cores. A lot of that work centers on the ARMv8.2-A instruction set, using SIMD (Neon) vectors and the dot-product extensions to speed up compute-heavy math pipelines and DSP routines down at the bare-metal level.


System Terminal

A simulated shell, and a real RISC-V Linux machine, emulated in your browser.


The prompt below is a small simulated shell (type help to explore). Click BOOT RISC-V and it becomes the real thing: Fabrice Bellard's TinyEMU compiled to WebAssembly, booting a self-hosted 64-bit RISC-V Alpine Linux image off an on-demand virtual disk. Write C, compile it with tcc, and run it, or apk add more packages over the network. None of it is faked; it's a full CPU emulator running an actual Linux kernel and userland. Emulator © Fabrice Bellard (MIT).

cberry@virtual-home: ~
CBERRY::VIRTUAL_HOME v1.2.0 (Type 'help' for available commands)
 
cberry@virtual-home:~$

Development Log

Notes, articles, and research write-ups.


SYS_TIME: 2026-07-05 AUTHOR: root

Hardware Accelerated Decompression: Moving Beyond the Basys 3

I've recently been spending a lot of time diving into hardware-accelerated decompression pipelines using FPGAs. The theoretical throughput gains of unrolling Huffman trees and processing LZ77 back-references directly in hardware fabric are massive compared to doing it in software on a CPU, but I've started hitting a severe bottleneck in my testing environment.

Currently, I'm doing all this development and testing on a Digilent Basys 3 board. Don't get me wrong, the Basys 3 is an absolutely fantastic tool. It is perfect for educational labs, prototyping basic digital logic, and learning hardware description languages. It has a great set of built-in peripherals like switches, LEDs, seven-segment displays, and a VGA port that make it incredibly fun for learning. The Artix-7 chip on the board actually has plenty of LUTs and BRAM to synthesize and route my complex decompression designs, and I can compile the core just fine. The problem is that the Basys 3 simply lacks the high-speed I/O required to support real FPGA acceleration. With only basic UART and slow PMOD connectors, I just can't shovel data into and out of the board fast enough to actually saturate the decompression core I've built. I end up benchmarking the serial port, not the decompression logic.

To take this to the next level, I need to purchase a more robust FPGA SoC development board that provides real usable bandwidth. I'm currently eyeing the BeagleV-Fire. It features a Microchip PolarFire SoC, which tightly packs a 5-core RISC-V application processor directly alongside 23K logic elements of FPGA fabric. Most importantly for this project, it boasts serious capabilities like a high-speed SYZYGY connector, an M.2 key for NVMe storage, and BeagleBone cape compatibility. Having this level of I/O (and the ability to do direct DMA transfers between a Linux-capable processor and the FPGA fabric over AXI) is the only way to test this decompression accelerator in a realistic, high-throughput storage pipeline.

As a side note, working on this project has constantly reminded me what an absolute pain in the ass it is to use proprietary FPGA programming tools. Dealing with gigabytes of bloated, proprietary IDEs like Xilinx Vivado just to synthesize a basic design is exhausting. The hardware is incredible, but the software ecosystem gatekeeps it. If we had a truly robust, universally supported open-source toolchain for all major FPGAs (similar to what the Yosys project is building), it would make hardware acceleration so much more accessible for everyone.

SYS_TIME: 2026-07-05 AUTHOR: root

Initial Boot Log

This is the start of the system development log. I'll be posting updates on the RISC-V VM, Linux bring-up, and various other hardware/software side projects here. Consider this space a scratchpad for engineering thoughts and architectural deep dives.

The latest major integration is the self-hosted WebAssembly port of Doom and the CBSh-FM synthesizer radio, both of which are fully functional in the system terminal above.


The Anti-Agile Manifesto

Process should never eclipse the product.


Note: The core philosophy of this manifesto is heavily inspired by and completely aligns with Michael O. Church's excellent essay, "Why 'Agile' and especially Scrum are terrible". Church accurately identifies how Agile functions as a mechanism of control rather than engineering excellence. The following points expand on his ideas like terminal juniority, violent transparency, and the "Whisky Goggles" effect through the lens of my own visceral, real-world experiences in the trenches.

I. The Inversion of Priorities & Business-Driven Engineering

As Church points out, modern Agile methodologies have systematically inverted the fundamental priority of software development: the process has become more important than the product itself. Agile is fundamentally a form of "business-driven engineering" that places the power to dictate technical priorities into the hands of non-technical stakeholders. What began over two decades ago as a lightweight framework for rapid iteration and developer autonomy has ossified into a bureaucratic, heavy-handed machine that stifles the freedom of good engineers to do good engineering.

At its core, the corporate application of Agile caters exclusively to the lowest common denominator. It treats software engineering (a highly creative, mathematically complex, and deeply technical discipline) as an assembly line of fungible "story points." We have sacrificed architectural integrity, security, and long-term technical vision simply so that management layers can have an easy, predictable "line go down" metric on a burn-down chart. The metric has become the goal, and the actual software is merely a byproduct of moving Jira tickets from left to right.


II. "Terminal Juniority" and The Fatal Inertia of Sprints

Church expertly identifies a phenomenon he calls "terminal juniority." Because deep architectural work, R&D, and structural refactoring cannot be neatly estimated and packed into a two-week sprint, Agile forces developers into a permanent state of low-yield ticket fixing. True engineering requires the autonomy to pivot immediately when the realities of the system demand it. Software is inherently an act of discovery; very often, it isn't until you are deep in the middle of an implementation that you realize you are going down the wrong architectural path.

The Agile process, despite its name, adds a massive amount of inertia to these realizations. Because sprints are "locked," story points are committed, and timelines are broadcasted to stakeholders, it becomes politically and procedurally difficult to halt work. The overhead of dealing with the "ceremonies" of re-planning and explaining a pivot in a retrospective is such a giant pain that engineers are incentivized to just keep quiet.

Consider a routine bug ticket. You open the code and realize the bug is merely a symptom of a much deeper architectural flaw. You could write a terrible, brittle workaround to make the test pass, or you could take the time to fix the root cause. The Agile process almost always dictates the former: apply the shitty workaround now to close the ticket, and file a new ticket in the backlog to "fix it later". But in software, there is nothing more permanent than a temporary fix. The backlog ticket rots, and the system degrades, all because doing the right thing didn't fit neatly into the sprint. This is terminal juniority in action: sacrificing the long-term integrity of the codebase for the short-term optical win of closing a Jira ticket.


III. "Violent Transparency" and The Cost of Context Switching

A meeting does not just cost thirty minutes of an engineer's day. Just like a CPU processing a hardware interrupt, there are massive, invisible costs to context switching. An engineer's primary output is generated in states of deep, unbroken flow. This is a mental state that takes time to load into working memory and align perfectly. If I have two thirty-minute meetings scheduled in a morning, that entire morning is effectively destroyed. The continuous blocks of time needed to dig into real, consequential work are hopelessly fragmented.

Church calls the daily standup a state of "violent transparency." It is a surveillance state that breeds anxiety rather than productivity, especially for creative work. The demand for daily status updates creates an atmosphere that actively encourages dishonesty. Every engineer has days where they spend eight hours trying to figure out why a binary isn't compiling, only to realize they forgot to add a single line to the build infrastructure. It is embarrassing, but it happens to everyone. However, no one admits this under the violent transparency of a daily standup. Instead, the process incentivizes inventing fake updates to provide the illusion of steady, linear progress, breeding a culture of micromanagement and anxiety rather than genuine transparency.


IV. The "Whisky Goggles" Effect and Alienating Top Talent

Perhaps Church's most damning point is the "Whisky Goggles" effect. He argues that Agile might elevate a poor performer (a "3" out of 10) to a passable level (a "5"), but it actively repels and drives away the absolute best, senior engineers (the "7s and 9s") who require autonomy to thrive.

When a process caters entirely to the lowest common denominator, it inherently stifles the highest performers. I have seen instances where an engineer proactively found and fixed a critical issue while working in a related codebase, only to be reprimanded for not filing a ticket, waiting for the next planning cycle, and getting the work "approved." When a system penalizes initiative, the best engineers adapt by subverting it: they do the right thing quietly, and then write the Jira tickets after the work is already done, just to satisfy the bureaucracy. Once the bureaucracy becomes too exhausting to subvert, the top talent simply leaves.

The alternative to this relentless micromanagement isn't chaos; it is trust. You should not be staffing people (especially at senior levels) that you feel the need to extract daily status updates from. If an engineer requires a daily standup to stay on task, that is a hiring failure, not a process failure. The solution to complex engineering problems is simple: hire highly competent engineers, give them crystal-clear objectives, provide them with the uninterrupted time necessary to achieve those objectives, and then get out of their way. Let engineers engineer.