/\___/\
   /       \
  l  u   u  l
--l----*----l--      _   _ _                      _           _             
   \   w   /        | |_(_) |_ ____ __  __ _ _ _ ( )___  _ __| |__ _ __ ___ 
     ======         | / / |  _|_ / '  \/ _` | ' \|/(_-< | '_ \ / _` / _/ -_)
   /       \ __     |_\_\_|\__/__|_|_|_\__,_|_||_| /__/ | .__/_\__,_\__\___|
   l        l\ \                                        |_|                 
   l        l/ /
   l  l l   l /
   \ ml lm /_/
	
kitzman's place

Embedded Programming on Plan9 (#1)

embedded plan9

People look for the right tooling, libraries, and support when considering an operating system. I’ve been using 9front for a while, and wanted to do some embedded programming on it too. There’s no gcc, so SDKs won’t work directly, no tool to flash chips with - most people would use something else.

But don’t give up! Plan9 was used throughout the history for distributed computing, creating operating systems, and high-performance computing. And as we will see, it is quite easy and it does its job well. Why wouldn’t I be able to productively use it?

I chose the STM32F103Bx for doing this. There is already a port of InfernoOS by David Boddie [1], for a similar STM.

Flashing

STM32s support two types of flashing methods. The first one is via USB, using their tooling and drivers. Another one is via UART, which is achieved by configuring the jumper pins for booting in the appropriate mode. I chose the UART protocol - it’s easy to use and probably can be written in an rc(1) script.

The protocol, jumper configuration, and details are described in STElectronics’ AN3155 and AN2606.

Having the specification, a C compiler, and a UART adapter, I wrote a flashing utility [2]. The process took around two days, including pressing the reset button and trying stuff out until it works.

So next time you are in the situation of booting another OS because there is no tooling, try to write your own! Everyone will get to use it, and it might not be as hard as you initially thought.

Compiler

9front already ships with compilers for a series of architectures. The STM supports armv7-m and thumb2, both of which have compilers, loaders and assemblers.

However, the thumb compiler has bugs, and David Boddie fixed some of them. The compiler can be found in his repository [1]. It should work on all platforms InfernoOS works, not only Plan9.

The libc

So having the tool, compiler and datasheets, I was able to bootstrap a simple blinky project.

But that’s not enough. There’s no snprintf, no allocator, etc.

First, I had to write an allocator. That’s not that hard, as a linked-list configured for a memory region does its job quite well. Such an allocator is actually an exercise in Kernighan & Ritchie’s “The C Programming Language”, chapter 8.

My 9front libc.a currently is 1817KB in size - and generally, it’s not made for embedded platforms. InfernoOS’s libkern, is specifically made to also work on embedded platforms, and leave room for the virtual machine as well.

That being said, copy pasting InfernoOS’s libkern did work, with Mr. Boddie’s patches. The architecture specific code is in files appended with -thumb.c, containing implementations for functions looked up by the compiler, which can be found in utils/cc/com64.c:103. Porting to another architecture, would mean implementing those functions.

Great! Who needs SDKs anyway? One is now able to freely write embedded projects, as they normally would.

Next steps

In the next post in the series I will explain porting parts of InfernoOS to the STM32, so you can use its scheduler for an RTOS. The example project will also contain serving 9P2000 over the serial line (which is a pretty neat way of interfacing with your devices).

Conclusion

You can find the code described in this post in [3]. The WIP repository is found at [4], and already contains serveral processes: kconsole, dma2q and devicefs.

I, for one, am pretty happy with the fact that I can switch most of my work and projects onto 9front. You might find it funny but I do this on an RPi1. Another SBC is used as a NAS and general-purpose server, and an Intel NUC is used as a Xen dom0, running VMs with BSDs, Kubernetes nodes, and ocassionally, 9front.

The code which will be showed in part 2, is mostly the same with Plan9 4e kernel code, so it will be a good enough intro to kernel programming as well.

Hopefully, this will ease Plan9’s newcomers attempts to write embedded code, and also encourage them to write their own tooling. :)

Appendix

[1] InfernoOS for STM32

[2] STM32 flashing tool

[3] bare project

[4] RTOS project