Skip to content

ycoroneos/G.E.R.T

Repository files navigation

G.E.R.T : Golang Embedded Run-Time

bootingscope shot laser trace

WARNING : This is a research prototype so don't use it for critical things yet

GERT is a modified version of Go that runs bare-metal on armv7a SOCs. The minimal set of OS primitives that Go relies on have been re-implemented entirely in Go and Plan 9 assembly inside the modified runtime. The goal of this project is to bring the benefits of a high-level, type-safe, and garbage-collected language to bare-metal embedded environments. GERT has been developed for the Wandboard Quad (iMX6 Quad SOC), but GERT can be ported to any armv7a SOC with adequate documentation.

Features

  • Improved latency compared to Linux user-space C
  • All of Go's concurrency features, such as goroutines and channels, on bare-metal
  • Greater portability than bare-metal C
  • Drivers written for the iMX6 UART, SPI, SDCARD, GPT, IOMUX and much more

Quickstart

Materials Needed

GERT can either run in the QEMU emulator or on real hardware. To emulate GERT you must install QEMU. Follow the install instructions below because they include a QEMU installation. To run GERT on real hardware, you will need to get a Wandboard Quad and an SD card, or any other dev kit which uses the Freescale iMX6 Quad SOC. GERT only works with the iMX6 right now because its memory map is hard-coded into the kernel. I plan to bring GERT to the raspi eventually, but don't wait for me, feel free to contribute!

Directory Layout

Directory Function
golang_embedded Modified Go runtime which runs on bare-metal. It has its own repo which explains modifications in detail
qemu QEMU git master branch. submoduled
thesis My master's thesis. Contains a pretty detailed description of this work. It may eventually become outdated
gert/armv7a Contains the user-facing code for running GERT on the Wandboard Quad dev board
gert/armv7a/uboot_bin Images for the U-boot bootloader, which configures basic device clocks and loads GERT off the sd card
gert/armv7a/boot Second-stage bootloader written in C that prepares the initial Go stack
gert/armv7a/embedded Go package which contains many drivers for the iMX6 Quad cpu
gert/armv7a/doc Technical reference manuals on the armv7a, cortex-a9 mpcore architectures, and iMX6 SOC
gert/armv7a/programs A storage directory for some GERT programs
gert/armv7a/measurements Benchmarks and measurements I took for my thesis
gert/armv7a/debug JTAG scripts for the JLink EDU

Installation

These commands will build QEMU from source and also download all of the dependencies required to build GERT and the Go runtime. You also need to have regular Go installed on your system in order to bootstrap the compilation of G.E.R.T and Go.

Ubuntu

First, in ~/.bashrc, put export GOROOT_BOOTSTRAP=$(go env GOROOT) Then make sure you have the deb-src repositories uncommented in /etc/apt/sources.list.

 sudo apt install gcc-arm-none-eabi gdb-arm-none-eabi golang git
 sudo apt-get build-dep golang qemu
 git clone https://github.com/ycoroneos/G.E.R.T.git
 cd G.E.R.T
 git submodule update --recursive --init
 cd qemu && ./configure --target-list=arm-softmmu && make -j4 && cd ..
 cd gert/armv7a && make runtime && UPROG=programs/hello make && make qemu

If all went well, you should be running the 'hello' program in QEMU. Press CTRL+A then X to quit QEMU.

Mac OS

Put export GOROOT_BOOTSTRAP=$(go env GOROOT) in ~/.bash_profile. In order to get the build dependencies for Go, QEMU, and armv7a development I recommend using homebrew. You probably also need the xcode command line tools installed.

 brew tap PX4/homebrew-px4
 brew update
 brew install gcc-arm-none-eabi qemu
 git clone https://github.com/ycoroneos/G.E.R.T.git
 cd G.E.R.T
 git submodule update --recursive --init
 cd qemu && ./configure --target-list=arm-softmmu && make -j4 && cd ..
 cd gert/armv7a && make runtime && UPROG=programs/hello make && make qemu

If all went well, you should be running the 'hello' program in QEMU. Press CTRL+A then X to quit QEMU.

Programming With GERT

GERT programs live inside the gert/armv7a/programs directory. Each program folder must contain three things: kernel.go, irq.go, and userprog.go. Take a look at programs/hello to get a feel for the layout, then look at programs/gopher to see how to interface a laser projector. Remember that GERT programs are Go programs. Besides for the quirky layout and the few constraints listed below, you should go about programming in GERT as you do in Go.

kernel.go

This is not the actual GERT kernel, but it contains the GERT entry point, initialization for the interrupt controller, and code to enable all 4 cpus on the iMX6. It's boilerplate code you would have written anyway. The actual GERT kernel is in the golang_embedded repo

irq.go

Contains the interrupt service routine that GERT executes when a cpu gets an interrupt (switches to ISR mode). Every cpu can concurrently execute in the interrupt handler; interrupts are not serialized. There are some basic rules you must obey inside the interrupt handler though : no blocking operations and no allocations on the heap. This is because the garbage collector might be running while an interrupt is being serviced. The irqnum input is the ID of the SPI that was received. You must enable the specific interrupts you want to receive in the ARM GIC before the interrupt handler will ever execute. Look in the doc folder for GIC documentation.

userprog.go

This contains your GERT program. There are at least two functions you must implement: user_init, which is called once, and user_loop, which is called repeatedly. Most of the standard libraries work as well as channels and goroutines. The embedded package contains drivers for many iMX6 peripherals for you to play around with. If you find a standard library that doesn't work (and you want it to work), then either make an issue on github or submit a fix.

Working With GERT

gert/armv7a is the working directory so you should execute all commands from in there. Everytime you change the runtime run make runtime. To build a GERT program, run UPROG=<your prog dir> make. To run your GERT program in QEMU do make qemu. To put your GERT program on an sd card and boot it run SDCARD=/dev/<your sdcard> make sdcard

Debugging

Many bugs in a GERT program result in a Go panic, which prints a very useful backtrace along with a useful error message. This is usually enough to fix the problem. If the bug is serious, it may be a kernel bug. If you still want to tackle it, then look in my thesis for an overview of the different kernel components and the virtual memory map. gert_arm.go inside the src/runtime folder of the Go runtime has the majority of the GERT kernel.

QEMU

Try to reproduce your error in QEMU. It will significantly reduce debugging time. Run your faulty GERT program with make qemud and connect to it with gdb-arm-none-eabi. GERT programs are compiled with debugging symbols and Go has excellent support for GDB.

JTAG

QEMU does not emulate most of the iMX6 peripherals or cpu very well. You may need to use a JTAG adaptor to step single instructions on the actual hardware. There are JTAG scripts for attaching to specific Cortex A9 cores inside the gert/armv7a/debug directory. These scripts each setup a gdb server that you can connect to with gdb-arm-none-eabi again. These scripts work for the Segger JLink EDU. They can probably work with other Segger products but not with OpenOCD.