RSSAmplifier

Blog

Uros Popovic

Personal site of Uros Popovic - tech blogging on systems and software.

popovicu.comRSS feed ↗39 posts

Latest posts

Writing your first compiler

Build your first compiler with minimal, high-level, modern code. With only a few files of Go and C code, we can set up a workflow that dynamically fetches everything needed, including the LLVM library itself, and builds a portable compiler. This is a modern stack, it's reproducible, and you do not need to read dozens of pages to get started.

How to use Linux vsock for fast VM communication

Discover how to bypass the network stack for Host-to-VM communication using Linux Virtual Sockets (AF_VSOCK). This article details how to use these sockets to build a high-performance gRPC service in C++ that communicates directly over the hypervisor bus, avoiding TCP/IP overhead entirely.

How to reverse engineer USB HID on Linux

Discover how Linux exposes raw USB device data, even without a driver. This article details how to use /dev/hidraw and the HID report descriptor to reverse-engineer and read real-time data from a UPS.

How KVM and QEMU run VMs in Linux

Learn the distinct roles of QEMU and KVM in Linux virtualization. This article explains how they complement each other to run virtual machines at near-native speed.

PC cooler control with a $2 microcontroller, no development board

Walkthrough for a small embedded system based on ATmega328p which controls a PC cooler fan. The focus of this experiment is on using only open-source CLI software tooling for the solution. Additionally, no development boards were used, just the bare microcontroller, which should be helpful in transitioning to building your own boards.

Writing an operating system kernel from scratch

Exploring a minimal implementation of a time-sharing kernel on RISC-V, implemented in Zig, on top of OpenSBI.

Custom CPU simulation and testing

Walkthrough for how the Mrav CPU project handles RTL simulation and other testing aspects.

Running Go tools in a browser

Quick overview of how Go tools for the Mrav custom CPU are run inside a browser by leveraging WASM. The project is built with Bazel using Go rules.

RTL generation for custom CPU Mrav

Overview of how SystemVerilog RTL code is generated in the build flow for the Mrav custom CPU core.

Mrav custom CPU software tooling

Deep-dive into software tooling for a custom CPU platform Mrav.

Embedded bare-metal C with Bazel and AVR

Practical example of using Bazel to build an embedded C program, bare-metal. Concrete example with AVR ATmega328p.

Creating an assembler for a custom CPU

Explainer for how Mrav CPU assembler was created. Shortest path towards a small, working assembler for a custom ISA.

Making a custom CPU

First part of the series explaining the development of a custom CPU called Mrav and the tooling for it. Lessons learned from working on Google TPU chips.

Simple Lua integration in Go

Learn how to use Bazel to easily integrate (with a single command) mainline Lua in Go and potentially other languages (e.g. embedded C programs).

Cross-compiling C and Go via cgo with Bazel

Walkthrough for cross compiling a mixed C and Go binary for another platform using cgo and Bazel. Example is done with x86_64/Linux compiling for RISC-V/Linux.

Linux VM without VM software - User Mode Linux

Quick demonstration of using User Mode Linux (UML) to run a Linux VM inside Linux's userspace, without additional VM software or even root permissions

Machines build machines - AI creates a bootable VM

See how AI is pushing the boundaries of computer engineering. I'm sharing my journey driving AI to build a functional RISC-V 32-bit VM simulation, reaching the milestone of booting OpenSBI. Discover the process behind this AI-assisted journey and what's next on the path to a fully bootable Linux kernel and potentially an FPGA implementation.

Bare metal JavaScript on RISC-V

Explore how to run JavaScript directly on bare metal, like microcontrollers. This post shows you how to get JavaScript code executing on embedded hardware without an operating system, opening up new ways to program these chips. The example is done on a RISC-V VM.

Bare metal printf - C standard library without OS

Guide to implementing a C standard library for bare metal hardware using Newlib, enabling powerful functions like printf and malloc without relying on an operating system. This step-by-step guide demonstrates how to configure and integrate Newlib on RISC-V architecture, showing you how to redirect standard I/O through UART for embedded systems development.

Making my first embedded Linux system

End-to-end documentation of a journey from no PCB experience to fabricating my own Linux-ready system that can boot the latest mainline kernel. This article is the recommended reading for someone building their first embedded Linux board. F1C100s SoC is used for this sample board.

Make your own USB storage device using embedded Linux

A guide on using embedded Linux to implement common USB devices, in this case, mass storage device. We'll use mainline Linux on Raspberry Pi Zero, and with 10-15 lines of shell scripting, we'll turn a Raspberry Pi into a flash drive.

Making USB devices - end to end guide to your first gadget

Introduction to implementing USB devices. Minimal overview of hardware and software with an example with STM32 microcontroller. Also contains an index to very detailed guides for more information.

OCI containers with Bazel in one command

Guide on building and running OCI containers using Bazel with one command. Bazel builds your software, packages the layers and builds the tarballs that can be imported by something like Docker to run your workloads.

Go gRPC servers with Bazel in one command

In-depth guide on building gRPC servers in Go programming language using Bazel. The end result is a single command that builds the proto definitions and links them into the server business logic. Includes the modern Bazel module mechanism for dependencies.

Easy to build and deploy Go servers with no tooling and external dependencies

Quick introduction to building HTTP servers in Go without having any tooling set up and requiring no external dependencies. Bazel is the preferred build system for this exercise. Cross compiling to other platforms is also briefly covered.

How files in Linux work

Learn the high-level concepts behind files and filesystems in Linux. This article explains both disk-based filesystems and filesystem as an API to the kernel.

Run mainline Linux on $5 dollar hardware

Learn how to make a Linux-capable embedded system for less than $5 dollars. Includes an in-depth analysis of how to build and deploy U-boot, with emphasis on the modern U-boot FIT images.

<50 lines of code for a custom generative AI flow in Google Slides with Google Gemini

Learn how to add custom AI flows to your Google Slides work through Gemini API. Also applicable to other Google apps.

Making a mini computer from scratch with Raspberry Pi and Linux

Learn how to utilize Raspberry Pi and Linux kernel to make your own custom mini computer from scratch, capable of interacting with the user through a keyboard and a screen.

Cross compiling C and C++ with Bazel

Learn how to utilize Bazel's toolchains and platforms to cross-compile C and C++ for another architecture and OS. The example used is cross-compiling for a bare-metal RISC-V machine.

Take full control of Raspberry Pi! 10 MB mainline Linux image for embedded

A guide on building a Raspberry Pi image from scratch using the latest mainline kernel for embedded purposes. Only a few manually built files are involved along with the Linux GPIO drivers to achieve LED flashing.

Building multiplatform Linux initramfs with one command in Bazel

A guide on building working initramfs images for Linux for any platform with minimal effort. The build is hermetic and assumes no tooling installed on the developer's machine (even Bazel doesn't have to be installed)

Build all software in one command with Bazel

An in-depth guide on how to use Bazel, including writing custom rules to automate any build/run software flow. The example combines fetching remote tools, running a multi-language build and building complex binaries.

RISC-V interrupts with a timer example

A detailed example of RISC-V interrupts in C through OpenSBI timer infrastructure.

Bare Metal Rust on RISC-V With Dynamic Memory

A bare metal example of Rust programming on RISC-V. Includes a proof of concept for dynamic memory allocation.

789 KB Linux Without MMU on RISC-V

A guide on building a tiny Linux (only 789 KB) that requires no MMU and deploying it on a RISC-V system, with custom userspace code.

Making a micro Linux distro

A guide on building a simple Linux distribution from scratch. Detailed guide on building the kernel and the init process. Finally, a little distribution is built with u-root that is capable of connecting to the Internet.

RISC-V SBI and the full boot process

Detailed explanation on how RISC-V boot process works and what role SBI has in the RISC-V software stack. Concrete example with OpenSBI.

Bare metal programming with RISC-V guide

Guide on coding a bare metal program with UART output for RISC-V and running the emulation with QEMU. Brief overview of the RISC-V boot process.