OpenBSD on BeagleBone Black Revision C

Overview

BeagleBone Black is a low-cost, community-supported development platform for developers and hobbyists. This board is listed among the supported devices for armv7 target of OpenBSD.

See:

Installation

To install any operating system on this board, at least a 1GB microSD card and a USB to TTL converter is required.

  • Firstly, grab the installation image from one of the official OpenBSD mirrors:
$ ftp https://ftp.openbsd.org/pub/OpenBSD/7.3/armv7/miniroot-am335x-73.img
$ ftp https://ftp.openbsd.org/pub/OpenBSD/7.3/armv7/SHA256.sig
$ signify -C -p /etc/signify/openbsd-73-base.pub -x SHA256.sig miniroot-am335x-73.img
The last command verifies the integrity of the downloaded image.
  • Prepare the microSD card by flashing the image onto it using the "damn destructive" Unix command dd. Beware the following will overwrite the data on your microSD:
$ doas dd if=./miniroot-am335x-73.img of=/dev/rsdXc
Replace rsdXc with your actual disk. Once the write command finishes you can insert the microSD into the board.
  • Plug the USB to TTL cable to a computer. The black wire in the USB to TTL cable must be facing the ethernet port (near the letter J1 on the board), while the green wire must be facing the USB port.
See:
In case your USB to TTL converter differs from what shown above, use the following table to find correct wire connections to the board.
Pin Number on BBB (Signal)Pin Name on Converter
1 (GND)GND
4 (RXD)TXD or TX
5 (TXD)RXD or RX
Remember the numbering above, starts from the side marked with a little white dot near the letter J1 on the board.
  • Having connected the USB to TTL converter, you can connect to the serial console with OpenBSD by using:
$ doas cu -l /dev/cuaU0 -s 115200
Else if on a Linux machine you should try:
$ sudo screen /dev/ttyUSB0 115200
  • While connected to the serial console, press and hold the boot switch button near the microSD card slot, then power up the board either via a 5V DC adapter or a mini-USB cable. As soon as the power is applied, the console screen will be populated by boot messages and soonish you will be prompted to run the OpenBSD installer.
Note: By default when BeagleBone Black is powered up, it will boot from the on-board eMMC flash. To avoid this and boot from the microSD card, the black button near the microSD card slot must be pressed and held, before connecting a power supply to the board.

Accessing GPIOs

There are four user LEDs on the BeagleBone Black which can be used to demonstrate how GPIOs are generally accessed in OpenBSD. Usually GPIOs are grouped into banks or ports, consisting of multiple actual hardware pins. The BeagleBone Black comes with 4 banks each 32 pins wide, which are configured on OpenBSD as device files: /dev/gpio0, /dev/gpio1, /dev/gpio2, /dev/gpio3, respectively. The BeagleBone Black user LEDs are configured under /dev/gpio1 and pin numbers 21 through 24.

Using command line tools to control GPIOs

The OpenBSD provides a basic utility tool to configure and control GPIO pins, called gpioctl. We'll try to toggle the user LED connected to the pin numbered 21 on /dev/gpio1, using this tool.

  • Firstly, configure the respective pin as output and rename it to USR0:
$ doas gpioctl gpio1 21 out USR0
  • Now, you can toggle the LED or set it on or off using any of the commands bellow:
$ doas gpioctl gpio1 21 toggle
$ doas gpioctl gpio1 21 on
$ doas gpioctl gpio1 21 off

Writing an LED blinker in C

This is also possible with shell scrips using gpioctl in a loop, but doing it in C is also fun.

  • Create a file named blinky.c with the following content:
#include <stdio.h>
#include <errno.h>      // errno
#include <fcntl.h>      // open
#include <unistd.h>     // close, sleep
#include <string.h>     // memset
#include <sys/types.h>
#include <sys/gpio.h>
#include <sys/ioctl.h>

#define BLINK_COUNT 10  // number of times to blink

int main(void)
{
        const char * dev = "/dev/gpio1";
        struct gpio_pin_op pin_op;
        int fd;
        int i;

        /* open device file with read and write access */
        fd = open(dev, O_RDWR);
        if (fd < 0) {
                printf("ERROR: could not open device file.\n");
                return errno;
        }
        printf("DEBUG: opened device file successfully.\n");

        for (i = 0; i < BLINK_COUNT; i++) {
                /* zero out pin_op struct */
                memset(&pin_op, 0, sizeof(pin_op));

                /* set pin number to toggle */
                pin_op.gp_pin = 21;

                /* ioctl(2) will return -1 on error */
                if (ioctl(fd, GPIOPINTOGGLE, &pin_op) == -1) {
                        printf("ERROR: could not toggle gpio pin.\n");
                } else {
                        printf("DEBUG: pin %d toggled from %d.\n", pin_op.gp_pin, pin_op.gp_value);
                }

                /* wait for 1 second */
                sleep(1);
        }

        /* be graceful and try to close the device file */
        if (close(fd) == -1) {
                printf("ERROR: could not close device file.\n");
                return errno;
        }
        printf("DEBUG: closed device file successfully.\n");

        return 0;
}
  • Compile the file and run it with root privileges:
$ cc -o blinky blinky.c
$ doas ./blinky
The user LED on the board should blink for 10 seconds, while running this program.
For other operations on GPIOs refer to manual pages gpio(4) and ioctl(2) for possible error values.