Recent Articles

Ethernet: Fundamentals

Much of recent professional development has focused on Ethernet, making it a convenient target for technical essays. Unlike much of the Internet, this series of essays will focus on practical implementation of Ethernet from an FPGA or ASIC perspective. This means the necessary waveforms and encodings to generate ethernet packets when directly connected to a PHY or medium.

The essays will be making extensive references to IEEE 802.3-2022 and every effort will be made to specify the exact clauses for further research by the reader. I will not be using the amendment names (e.g. 802.3z for Gigabit Ethernet) because they are not not useful for finding content within the actual standard and any given clause may have been modified by multiple amendments.

In this first essay, the focus will be on the fundamentals of Ethernet. Much of the information will be conceptual but referenced repeatedly when discussing specific protocols.

Read More

Xilinx JTAG Support on FTDI

For many industrial embedded projects, embedding debugging support (e.g. JTAG) into the design can be immensely useful. This can be for the convenience of integrated debugging or specialized needs, such as galvanic isolation. The FTDI family of High-Speed USB-Serial transceivers are commonly used for this purpose. FTDI’s Multi-Protocol Synchronous Serial Engine (MPSSE) can offload the JTAG state machine and achieve clock speeds as high as 30 MHz. Software like OpenOCD provides a solid basis for manipulating microcontrollers but the situation is very different when it comes to FPGAs.

Classically, FTDI was not supported by Xilinx development software (e.g. Vivado, Vitis) unless using one of the modules from Digilent. However, in 2018, Xilinx released the VCU128 Evaluation Board, which sports an FTDI FT4232HL without any special features. At some point, the use of FTDI devices became officially supported by Vivado. Unfortunately, despite this support, the documentation remains poor and occasionally nonfunctional. In this article, I will attempt to provide more complete design assistance.

Read More

C/C++ Runtime Startup

When writing a freestanding application, it’s generally necessary for the firmware engineer to handle runtime initialization. Even when a library like newlib includes a rudimentary implementation of crt0.o, initialization is a very application-specific process owing to the need to initialize hardware, memory, and other loading tasks.

In this essay, we examine the current and historical implementation of executable initialization, finishing with a minimal implementation usable with firmware applications.

Note: Most firmware applications need to address the initialization of .data and .bss from nonvolatile memory. That is not addressed in this essay.

Read More

Drone Running

While self-hosting Git isn’t that hard (all you need is a shell accessible through SSH), some tools make it easier. One of them is Gitea, a nice, self-contained Go binary that provides you a GitHub clone without all the complexity and dependency hell of something like GitLab. One of the things it does not provide is an integrated continuous integration/delivery (CI/CD) platform. Instead, it implements the same basic patterns at GitHub allowing for pairing with a range of third-party services, cloud or hosted.

The most common CI paired with Gitea would be Drone. While there are many reasons I’m likely to discard it and try other options, I figure it’s worthwhile to at least share my experience trying to make it work for me, most notably how it handles runners.

Read More

Bazel Linkstamp

Bazel is one of the least terrible build systems out there. It can handle large codebases, mixed languages, and cross-platform builds like a champ. Unfortunately, it suffers from rather poor documentation with an enterprise Java codebase that is a nightmare to decipher.

One of the features I’ve been trying to make use of are linkstamps. The idea behind linkstamps is to embed information such as the Git commit identifier into the resulting binary, providing direct traceability for deployed binaries. Unfortunately, regarding this feature, Bazel suffers from the common documentation anti-pattern where they describe what an option is, not what it does.

Note: These instructions were written at the time of Bazel 4.2.1.

Read More

FreeBSD Jails And Networking

When using FreeBSD, the most common method for virtualization and process isolation are jails. Introduced with FreeBSD 4.0 in March of 2000, they predate the closest Linux equivalent, cgroups (and, by extension, Docker), by nearly a decade.

A core part of any virtualization technology is its interaction with the networking infrastructure. In this regard, I’ve found much of the available documentation lacking, often deferring to third party tools which are no longer maintained. As such, I’ve had to scrape multiple sources and reverse engineer system programs to figure out how it’s put together.

In today’s article, I’ll describe the results of my foray into FreeBSD jail networking. It’s not the most cohesive piece, but I’ll refine it over time and hopefully it will assist someone else in their efforts to deploy FreeBSD jails.

Note: These instructions were written at the time of FreeBSD 13.0.

Read More

Portable Sockets: Basics

In the modern world, people tend to use massive frameworks to accomplish simple tasks. Nothing quite like swatting a fly with a nuclear missile when you load up 100 megs of runtime just to execute ping and post the result to a database. But sometimes, when you’re writing a utility, you want it to be quick and lightweight. And if you’re going through the effort, you might as well see about making it portable.

Every extent Unix system uses BSD sockets for their networking layer, which traces back to 1983 and the release of 4.2BSD. In this model, network connections (“sockets”) are full fledged kernel objects that built on top of the existing Unix API (e.g. read, write, and close). Additional system calls were introduced both to create new sockets (e.g. socket) as well as provide networking-related operations (e.g. connect, listen, and accept).

By comparison, the original version of WinSock was a completely user space affair with its own API, loosely modeled on BSD sockets, but distinct from the system’s native interface. As the interface transitioned into the 32-Bit era with WinSock 2, it began to integrate more closely into the Win32 API. While Microsoft has written some material on porting Unix applications to WinSock, it leaves unanswered the question as to how to portably target both platforms.

Read More

Inline Functions in C and C++

Inline functions are a notable feature of both C and C++. By exposing the source file to the implementation of a function, they allow a variety of optimization techniques that wouldn’t be possible if it had to call out to a subroutine in a different file (at least without link-time optimization).

However, despite the common syntax, the C and C++ languages implement them in very different ways. While C++ takes a “user friendly” approach and automatically manages the manipulation of multiple implementations, C requires a more manual approach. As a result, inline functions are less common in C and mixed language code, generally using the nuclear option of declaring them static.

/* test.h */
inline int test1(void) {
  return 12;
}

/* test.c or test.cpp */
int test2(void) {
  return test1();
}

Sometimes, the easiest way to understand a rule is to see it in action. Let’s analyze how modern compilers deal with C and C++ inline functions in different situations.

Read More

FreeBSD Jail Startup Sequence

On my home server, I use FreeBSD. While FreeBSD beat Linux to the containers by nearly a decade (comparing jails to cgroups), I have to acknowledge that cgroups are the superior design. Whereas jails are a bunch of hacks piled on top of chroot, cgroups are a much cleaner abstraction of the kernel’s namespaces. But even beyond the elegance of the design, software like Docker makes it much easier to run your tools in containers, even if the offloading of sysadmin responsibilities it encourages triggers my OCD.

One of the things Docker does differently than most people’s usage of jails (at least from my limited understanding) is that a docker instance is ephemeral. The last time I touched iocage (years ago, granted), it was still focused on modeling jails like pets, not cattle. So I wanted my jails to go through the closest analog I could to Docker without porting over a massive ecosystem. That means if I’m going to write my own scripts, I need to understand how the FreeBSD jail system is put together.

Note: Jail functionality has improved a lot in the past two years. I had started this essay with a lot of frustration over things I had to work around only to find things much improved during my research.

Read More

wsgiref and Unix Domain Sockets

Recently, I needed to hack together a quick server-side application for a test page. When it comes to quick and dirty, most people turn to Python. While Python is hardly my favorite language, it is certainly suited for the task.

One of my requirements was that I wanted to minimize the number of dependencies. Installing Python is bad enough (my nginx container is extremely bare bones), but installing a massive framework for what was effectively a wrapper around a system command would make things even worse. So I decided to make due with wsgiref.simple_server that ships with CPython.

Unfortunately, when it came time to installing the script on the server, I discovered that simple_server only supports IPv4 and that is baked in. For security purposes, I like to use unix domain sockets whenever possible. It guarantees the endpoint can only be access from the local host and I can even configure permissions based on the user. Fortunately, it isn’t that hard to modify simple_server to support other protocols.

Read More

Subscribe via Atom or RSS