12-14-24
I've started a new branch hal
that separates platform-independent code, located in common.zig
, from platform dependent code. For each target, embedded and desktop, two files need to be created: a hal-{target}.zig
and a main-{target}.zig
. The hal-{target}.zig
files contain the functions
initDisplay()
closeDisplay()
sendRow()
loadBoard()
saveBoard()
These functions handle the two big non-CPU components of each platform: display and storage. They are designed for ease of use on the embedded board, specifically for writing to an eInk display and saving code to permanent memory (FRAM).
The problem with this, and something that has discouraged me, is how this ends up making the desktop side of the code a bit weird. For example, the call to hal.closeDisplay()
for desktop actually sends a private (only accessible from the file) framebuffer to the GPU and renders it. This means that main-desktop.zig
ends up calling this function every step without opening the display beforehand, as hal.initDisplay()
only needs to be called once which conceptually doesn't make much sense.
On the actual card, the MCU will be waking up from sleep and readying the eInk display to store data. The eInk will also persistently keep the last image displayed on it, so there is no need to resend the data like I do with the desktop simulator.
Looking back after a few days, I am less concerned by the weirdness of the desktop code. Since I am adapting something intended to be run in a much different manner to desktop, some sharp edges are alright. There is one more task I would like to get done before I merge this branch back into main and probably order some parts to start to make this work on real hardware: set up a build system for the MSP430.
Testing my code so far has been fairly simple. The vast majority of the time I just do zig build run
with maybe a build mode flag if I want to turn off safety checks. I did use a debugger to solve the corruption issue I ran into earlier, which was a bit tricky but not too bad. I'm expecting getting this code to build for MSP430 to be anything but simple.
For starters, LLVM, and by extension Zig, cannot directly output MSP430 machine code. Instead, it outputs an assembly file that can be assembled by binutils for MSP430. From what I've seen, either a standard binutils (as seen here) or a special build by TI can be used. There is also the option of using Zig's C backend to turn the Zig code into C and using msp430-gcc to turn the C into machine code.
Second, there is the issue of getting Zig to build in whatever system is chosen. I have been using the default build.zig, which is set up to build for the desktop. I'm going to keep this, but I need to set up a process to build the zig code to an assembly file. Ideally this could also be configured to use the toolchain to turn the file into a binary that can be uploaded to the device, but this may be a bit trickier. MSP430 support in Zig is very experimental, so getting it to work may be a challenge. I have had to dig through old github repos and LLVM's internals to find stuff, so it may take a while.