A while ago I got a ST Nucleo-H753ZI evaluation board because I wanted to try out Hubris, Oxide's embedded operating system. After getting the basic demo app with the blinking lights running I set it aside for a lack of an idea what to do with it. A few weeks ago I was looking through old Raspberry Pi accessories on the hunt for a project. What stuck out to me wasn't any of the Raspberry Pi stuff, but the old 4 by 3 VGA monitor I had standing around. Could I just wire those pins in the VGA cable up to the GPIOs and produce a signal? As it turns out, yes you can just do that.
Getting Rid of the Sys Task
In the beginning I thought I was gonna be changing the GPIO pins from normal code, so switching them on and off at very high speeds. In hubris there's a stm32xx-sys task that normally controls the GPIO pins and also handles enabling clock to the different components through the Reset and Clock Control (RCC) block.
So normally if you want to set a GPIO pin you'd send a message to the sys task and it would do that for you. I was worried that the overhead of the context switching was gonna be a problem there.
So I decided to get rid of the sys task and do it all in my task.
The Plan
My first plan was to get the screen to just display a single color. I thought that it would be enough to get the vsync and hsync signals right and then just have the green pin high all the time to get a green picture.
Mapping the Registers
The peripherals of our chip are all controlled with registers. Those are memory mapped and to certain addresses. There is a gigantic 3000 page reference manual that describes all those registers. It's all very overwhelming. Luckily there's a Peripheral Access Crate (PAC) that defines an API for reading and writing those registers.
Since we're running under memory protection we need to first make sure we can actually write to those registers. In Hubris that sort of thing happens in an app.toml where all the tasks for an app are defined.
... continue reading