Qemu

The Bifferboard can be emulated with a modified version of Qemu.

What gets emulated

  • 486 CPU, with 32MB RAM

  • Serial port

  • Missing cpuid instruction

  • EN29LV640B flash

  • GPIO (via gpio 'panel' interface, see below)

  • r6040 Ethernet controller

  • PCI vendor ID and Customer IDs on the northbridge, so /proc/cpuinfo comes out right

    • OHCI controller (-usbdevice disk:<image> tested)

What doesn't get emulated (TODO)

    • Missing FPU - Linux still probes (and finds) an FPU, it would be good to disable this in Qemu, but I can't work out how

For Qemu 0.15.0, with r6040 support

    • git clone git://github.com/bifferos/bb.git

    • cd bb/seabios

    • make

    • cd ../qemu

    • ./configure

    • make # no need to install it!

  • ./i386-softmmu/qemu -firmware openwrt-rdc-jffs2-64k-bifferboard.img -bios ../seabios/out/bios.bin # to run

    • CTRL-A X quits the emulator

Some systems are unable to build Seabios, so I've attached a build of it at the bottom of this page.

Introducing the GPIO panel

The Panel (or more specifically Patch Panel) can be considered a collection of GPIO pins. The panel is represented by a socket server which tracks the states of the pins owned by the panel. Generally two objects will connect to a patch panel pin - both of these objects are 'clients' of the panel. The clients can either assert state on the pins, or simply read their values. State is asserted by declaring either active high/low drive, passive pull-up (passive pull-down is unsupported), or tri-state (generally an input). The patch panel arbitrates between the connected clients and declares the actual pin value, or declares that pin contention has occured.

The patch panel itself has no knowledge of the GPIO arrangement of any device. It therefore works only in terms of it's own logical pin numbering. For the Bifferboard, these logical pins are assigned as follows:

The panel server must be started before any pins can be connected to. It's started by running ./panel.py (see attachment below). It can be stopped with CTRL-C.

Quick start

    • Download panel.py

    • Download led.py

    • Download button.py

    • Follow the above instructions but apply latest qemu-rdc-gpiopanel-0.10.5-X.patch to Qemu instead and use gpiolib-bzImage.

    • Open a terminal window and run ./panel.py

    • Open another terminal and run ./led.py

    • Open another terminal and run ./button.py

    • Run Qemu in a further terminal.

    • When Linux boots, set GPIO pin 16 as output via sysfs and you will see led.py respond when the LED state changes.

    • It should also be possible to read back the button state.

gpiolib-bzImage is a kernel image with gpiosysfs support compiled in. You can program or read the GPIO pins via the sysfs interface as described here

The Qemu Panel client (qemu-0.10.5/hw/rdc-gpio.c)

In order for Qemu to connect to the Panel it must know how to talk to the panel, and which pin mappings to use. This is achieved with a patch to Qemu which implements the Panel client code in C. The GPIO mappings are defined in g_PinMap at the top of hw/rdc-gpio.c. If the panel is not already running then Qemu will quit with an error on start-up.

The button client (button.py)

The button client is implemented in Python and simply opens a tkinter dialog and allows the user to change the button state (pin 1).

The LED client (led.py)

The LED client is also implemented in Python, and uses a class from the panel.py module (panel.py behaves as both a server and a client library). The LED client is a text mode application and simply prints out the state of the LED when it changes.

In the screenshot above, the led is first connected to a Panel with no other clients. It advertises itself as an input, so we are told that the LED is currently off, and given the reason. In this case the LED input is considered tri-stated (X). We then connect a button, which behaves as a pull-up resistor (P), since the button starts up in the 'not pressed' state. Then the button is pressed, and the LED comes on (0, active drive low). Next we release the button and it once more behaves as a simple pull-up (P).

HD44780 LCD display client (hd44780.py)

This emulates a simple 16 char x 2-line LCD display based on the popular Hitachi protocol. 6 panel lines are required (4 data and 2 control). This has been implemented using pygtk, and requires lcdfont.py for the font bitmaps.

The display can be tested with lcdwrite.py. It connects the server, and attempts to manipulate the GPIO pins to put text on the display.

All programs can be found in Subversion.