Email me
Why there are two firmware toolchains
← Self-balancing robot

How it works

Why there are two firmware toolchains

Keil came with the Yahboom kit, a Mac forced a portable GCC path, and Keil stayed as the reference until the car balanced.

The main reason I used Keil was that it was simply part of Yahboom’s original project setup. They had example projects ready to go, so getting started and flashing through Keil was easy. However, while I never intended to switch my laptop to a Mac, I got an insane deal on the last 16-inch M4 Max at Costco Japan, so I couldn’t pass it up. Unfortunately, Keil only runs on Windows, so I needed a new toolchain that would work on a Mac.

After a bit of searching and AIing (if that is even a word), I settled on arm-none-eabi-gcc, a CMake toolchain file and OpenOCD over SWD. None of these care which operating system they run on, which is handy as I also use Ubuntu.

Why not just run Keil somewhere else

I did initially think of running Keil through a Windows VM, but I soon found out that passing the ST-Link through USB on Apple Silicon is more trouble than it is worth. STM32CubeIDE was another option, and Yahboom already had some setup instructions for it. I decided not to go with this as CubeIDE’s code generator produces ST’s HAL code, while this firmware is built on the older Standard Peripheral Library.

Overall, the swap to the GCC setup wasn’t too bad. The chip is an STM32F103RCT6, a Cortex-M3 with no FPU, and GCC startup and linker files for it already exist. The shared source compiles under both Keil and GCC untouched. The main things that differ are the startup assembly, the linker script, the build files, and a few other bits and bobs.

Benefits of the switch

The main benefit is that the build runs on macOS, Linux and Windows, so I have one consistent setup. The first proper flash was done from Windows, using an image built on the Mac. Being able to switch platforms that easily saves a lot of headaches.

The GCC image links clean at about 42.6 KB of flash and 2.4 KB of RAM, roughly 17% of the STM32F103’s flash. Because it no longer depends on a Windows desktop, it also builds in CI on Linux with a different GCC version.

One thing that the CI build found was that the vendor files included "ioi2c.h" and "MPU6050.h", but the files on disk were named IOI2C.h and mpu6050.h. macOS has a case-insensitive filesystem, so it quietly resolved the mismatch. Linux did not. So the Mac had been hiding a broken include all along.

Another issue I ran across was that the CMake build directory records the machine that created it. This includes its source path, its generator and its make. A build directory synced from the Mac failed on Windows straight away. Build directories are per-machine and disposable; only the source is shared.

Why Keil has not been removed

The main toolchain is now GCC, but I kept the Keil setup as a known-good reference while getting the car to balance. Changing the compiler and the controller at the same time would have made every failure ambiguous. Now that it is balancing pretty well, I will probably remove Keil soon.