Open Klave

Developer Notes

Tutorial 1: Get to know your tools

Get to know your tools

These developer notes assume almost no knowledge. The goal is to learn everything required to write a bare metal operating system for the STM32 by playing and experimentation, diving deeper each iteration and trying to accomplish progressively more difficult tasks.

Tutorial 2: Ripping, restoring, and decompiling the factory operating system

Ripping, restoring, and decompiling the factory operating system.

In this tutorial we’re going to review the memory layout of the STM32F103. We’ll use this information and our tools to copy both the factory bootloader and factory operating system to our development computer. We’ll finish by opening both the bootloader and operating system in Ghidra, and writing some early observations about how they work.

Tutorial 3: Development techniques in GDB

Development techniques.

We will cover three techniques to reverse engineer a running chip using GDB. First, we will learn how to examine the state of all the incoming and outgoing wires in the chip (GPIO). Then, we will practice selectively turning off device peripherals to see what happens. Finally, we will introduce function prototyping. Using GDB, we can reset the device and establish the minimal routine that is necessary to accomplish some objective, for example, make a pad change a color, or write a character to the LCD screen.

As the STM32F103 has a memory mapped peripheral, most operating system stuff boils down to reading from an address, writing to that address, and looping. We can prototype in GDB first, and then translate the minimal routine almost line for line to C and build on it.

Tutorial 4: Put it together to drive the LCD Screen

Learn About the Display

The LCD Display on the MPK249 is a Winstar model number WH2004a.

Tutorial 5: Writing a USB driver for a chip the hard way

Write a USB driver the hard way

USB is a really fast protocol. Unlike driving the LCD, USB messages transact too fast for us to be able to send or receive specific messages in real time using GDB and stepping through the results. In this tutorial, we’re going to write a USB driver the slow way. We’re going to learn about every single register that makes USB work, as well as deep-dive into the protocol itself. We’ll master one transaction at a time, from device enumeration to sending midi back and forth to the computer.

A note: this technique is excellent for learning, but creates barely-legible spaghetti code if you take it too seriously. A USB driver is one of the areas where abstraction is really important. Once you learn the basics, you should do your best to abstract away from them in your code so a reader can understand what is going on.

Tutorial 6: Send keyboard notes by understanding USART

Sending notes to the computer

In this Tutorial, we’re going to understand how to send key press events to the connected computer.

Tutorial 7: Detect the Pad, Fader, and Knob movements via ADC

Detect Pad, Fader and Knob Movements via the Analog to Digital Converter (ADC) and DMA

We’re going to dive in to both the DMA and the ADC in this tutorial.

Tutorial 8: Colors! using the serial peripherial interface (SPI)


In this tutorial we’re going to figure out how to light up the pads and buttons, as well as read their current values, via the SPI. Our research into the pad colors yields a meaningful improvement over the factory operating system: we can use timing and animation to cycle the red, green, and blue LED cycles and achieve 1000s of distinct colors, where the factory default only permits 17.

Tutorial 9: Compile-time testing in C-ish

Compile-time testing in C-ish

Open Klave is written in C, but its target architecture is a piano, not the development computer. It can be difficult creating data structures and abstractions for a different chip. You don’t know stuff works until you try to run it.

In this tutorial we review C-ish, which is my term for writing in C, except we also permit the constexpr keyword from C++17 on, and we use a C++ compiler. By writing in C-ish, we can dramatically reduce the complexity of our operating system by mostly sticking to C conventions. But the constexpr keyword will permit some compiler testing and sanity-checking before anything is transmitted to the device.

We will finish by examining Open Klave’s “Global Event Stack,” and write some compile time tests. And we’ll consider some caveat and limitations to this approach.