Capemgr keeps track of the BeagleBone Black's expansion boards, known as capes

Lead Image © Maxim Maksutov , 123RF.com

Bred in the Bone

The BeagleBone Black offers many interfacing options, but how can you control which ones are used and how they are configured? We take a detailed look at the Black's Capemgr subsystem and the device tree data structure it manages.

The Texas Instruments Sitara AM3359 [1] processor of the BeagleBone Black (BBB) provides a large number of I/O signals that implement GPIO and various communication interfaces (SPI, I2C, UARTs). Inside the processor, these signals are routed to the chip's physical pins, and those pins are wired to the pins of the BBB's P8 and P9 expansion connectors, providing direct access to the processor's I/O signals for all sorts of different interfacing projects. Whereas the Raspberry Pi makes 26 pins available via its P1 expansion connector, the BBB makes a whopping 92 pins available via its P8 and P9 connectors. This gives the BBB a great deal of flexibility as an interfacing platform. The locations of the P8 and P9 connectors on the BBB can be seen in Figure 1.

Figure 1: The P8 and P9 expansion connectors provide power and signals that originate from the BeagleBone Black's integrated electronics and AM3359 processor. Source: BeagleBone Black System Reference Manual [2].

Far more signals are available internally within the BBB's processor than there are pins on the chip, so not all of these signals can be made available to the outside world at the same time. Users must choose which signal to multiplex (mux), or map, to each processor pin to make the most efficient use of the platform's resources for a particular application. Understanding what each signal does and how it works is necessary to mux the pins effectively and utilize the BBB platform to its full potential.

Capes

Both the BBB and its predecessor, the BeagleBone, support a variety of expansion boards known as "cape" boards or "capes." Capes interface with the BeagleBone family of boards via P8 and P9 to provide additional hardware functionality. Each cape expects the processor's I/O signals to be muxed to a particular configuration so that the cape can interface properly with the processor. Some capes provide pass-through connectors so that up to four capes can be connected to the BBB simultaneously by stacking capes one on top of another. For more information on exactly what a cape is, see the box "What Makes Your Hardware a Cape?"

What Makes Your Hardware a Cape?

Connecting a few wires to the pins of the P8 and P9 connectors to interface the BBB with your own prototype circuits is not difficult, but what is the difference between a few wires interfaced to the BBB and an actual cape? A true cape uses the I2C2 bus (pins P9.19 and P9.20) to identify itself to the Capebus at boot time. If the identification is recognized, the kernel will load the appropriate overlay automatically to mux the pins appropriately and set up the necessary kernel device drivers. Although the BBB has a few built-in capes that are always physically present (e.g., HDMI, eMMC), other capes can be added or removed between boots. Thus, identification is needed to determine dynamically which capes are connected to the system at boot time.

Because many different cape boards are available (with more becoming available every day), hard-coding the kernel with a mux configuration for every single combination of compatible capes is infeasible. This issue isn't limited just to the BeagleBone family of boards: With the proliferation of single-board computers (SBCs) that offer configurable expansion connectors, it is necessary to have a flexible method of muxing processor pins that isn't overly intrusive to the kernel.

To address this problem, the device tree [3] data structure was added to the Linux kernel in 2008. The device tree is a data structure designed to specify pin mux configurations and associate particular kernel drivers with particular pins. To handle any dynamic changes that must be made to the static device tree, the Capemgr [4] (Cape Manager) kernel mechanism is used. Capemgr supports the loading of device tree data from userspace.

In this article, I will look at Capemgr and the device tree, explain which pins on the BBB are available for your projects and which are off-limits by default, and walk you through the process of loading your own modifications to the device tree from userspace via Capemgr.

Understanding the Device Tree

Certain hardware configuration settings of the BBB, such as the core voltage of the processor and various clock signals, usually won't ever change. You can, if necessary, change these settings to customize the BBB for a particular task (e.g., reducing the processor clock speed to reduce power consumption), but it is reasonable to assume that these settings won't need to be changed without recompiling the kernel. Pin muxing configurations, however, can change quite often as capes are added and removed from the BBB between reboots. Pin muxing can even change dynamically at run time. So, how can both the static and dynamic hardware configuration settings of the BBB be represented in the Linux kernel?

The device tree was developed to handle this type of problem, and it greatly reduces the difficulty and complexity of maintaining multiple-hardware configurations. Originally developed as part of the Open Firmware project, the device tree is a tree data structure comprising a hierarchy of nodes that list the properties and configuration of hardware. Each node contains name-value pairs that describe properties associated with the hardware component described by that node. Examples of these properties are the pin mux configurations, the way pins are mapped to kernel device drivers, and any parameters passed into those device drivers.

The device tree is described in a human-readable device tree source (.dts) file compiled by the device tree compiler (dtc) tool into a device tree binary (.dtb) file. The generated .dtb (am335x-boneblack.dtb for the BBB) is loaded by the Linux kernel when the kernel is bootstrapped, and it describes a baseline configuration and the default pin mux settings for the BBB. Listing 1 shows a very simple device tree source file that contains a few nodes, all of which contain at least one property. Real device tree source files can become quite complex, with dozens of nodes with many properties each.

Listing 1

Example Device Tree Source

01 /* Root node of tree */
02 / {
03   /* Child node of root */
04   node1 {
05     /* Properties of node */
06     property1 = "value";
07     property2= <1 2 3>;
08   };
09   /* Child node of root */
10   node2 {
11     property1 = <1>;
12     /* Child node of node2 */
13     node3 {
14       property1 = "value";
15     };
16   };
17 };

To enable and configure other hardware features of the BBB, such as UARTs and the SPI and I2C buses, additional nodes must be added to the device tree. Instead of modifying the source of the device tree, rebuilding it with dtc, and then rebooting the system for the changes to take effect, you can apply an "overlay" to the kernel's device tree. Overlays are fragments of device tree code that add new nodes into the kernel's device tree, which is similar to loading and linking kernel driver modules dynamically into the running kernel. Overlays are implemented in .dts files, just as the device tree is, but they are compiled into device tree binary overlay files (with a .dtbo file extension), rather than .dtb files. The binary overlay files live in the system firmware directory in the root filesystem. For Linux, the firmware directory is the /lib/firmware directory. For Android, it is the /system/vendor/firmware directory.

The device tree is compiled with dtc as part of the kernel build process. To compile your own custom overlays from a .dts file, use the following command (in this example, using a source file named source.dts),

user@beaglebone:~# dtc -O dtb -o [PART_NUM]-[VER].dtbo -b 0 -b 0 -@ source.dts

where [PART_NUM] is the part number and [VER] is the hardware version associated with the overlay. The [PART_NUM] can be any contiguous string that isn't already in use as a part number. Versions are typically expressed as a four-character string, with the first version being 00A0, the second version being 00A1, and so on. The version helps in differentiating among multiple versions of an overlay with the same part number. Unless you are maintaining multiple versions of hardware that each requires its own version-specific overlay, you will be safe assigning a version of 00A0 to all of your own overlays.

Buy this article as PDF

Express-Checkout as PDF

Pages: 6

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content