Variety's the very spice of life, that gives it all its flavor.
—William Cowper
Those of you who have been following what's been happening with hardware platforms like the Android, Beaglebone Black, Raspberry Pi, and several other small Linux systems, have probably noticed a bit of divergence with respect to the Device Tree EEPROM formats used on these platforms. So far, it's not seemed like the simplification or standardization that everyone had hoped for; and what about cross-platform peripherals?
We now have the original Flattened Device Tree (fdt) format, the Beaglebone Black "CAPE" EEPROM format, the Raspberry Pi "HAT" EEPROM format, and yes, even a few others. Let's do a quick recap of these different EEPROM formats.
Device Trees - Pick a Flavor
We have the "Original Recipe", flattened device tree (FDT) EEPROM format; used on the PowerPC architecture, the Xilinx Virtex series with embedded PowerPC processor, and other Freescale processors.
Then we have the "extra crispy", BeagleBone Black(ened) EEPROM format for the TI OMAP processor :
and then there's "Raspberry flavor", the Raspberry Pi EEPROM format for the Broadcom processor :
and "Vanilla Ice" for those of us working on FMC (FPGA Mezzanine Cards), the IPMI FRU EEPROM format :
Although technically, the IPMI FRU (Intelligent Peripheral Management Interface - Field Replacable Unit)
is not related to the Linux Device Tree, it is used on many FPGA Mezzanine Cards to hold much of the same
design meta-data, so I'm chosing to include it here...
All of these EEPROM formats contain (more or less) the same meta-data about a system platform and/or it's add-on boards and peripherals, and are used to discover the configuration information needed for those peripherals. Things like product name, serial number, manufacturing date, and other important meta-data.
So, if they all contain (more or less) the same meta-data, why have so many formats? Historical reasons mainly, with different groups all working on the same problem; and I think the folks designing add-on boards like "Capes", and "Hats" were also looking for a more compact and easily addressable format than the flattened device tree (FDT).
Enter the Raspberry Pi HAT EEPROM format
When I first saw the Raspberry Pi HAT specification I wasn't sure that I liked the proposed Raspberry Pi EEPROM format, because the structure wasn't as simple to parse as the BeagleBone Black CAPE EEPROM format. The BeagleBone Black CAPE EEPROM format specifies fixed sized fields at fixed offsets (which become constants at compile time), where as the other formats require a run time parser to interpret the "live" data structure. The Raspberry Pi EEPROM format introduces the concept of ATOMs of data, basically a container format with checksum for each. The ATOM types include the typical header information as well as the PinMap and separate copy of the flattened device tree (FDT) for each add-on card (i.e. HAT) as mandatory requirements. While I laud them for that effort at completeness, making all of those ATOM fields mandatory is going to require a large EEPROM for each HAT; and it still doesn't really address the problem of cross-platform peripherals and different PinMap requirements. However, after looking at the HAT specification for a while, I really do like the simple and extendable ATOM concept for arranging the storage of meta-data in the HAT EEPROM. I think that there is a lot that could be done (easily) using different ATOM types for open (unencrypted), and secure (encrypted) areas within the EEPROM, allowing important areas (like pinmap or microcode/firmware perhaps) to be secure/signed objects that need to be decrypted/verified before use.
The PinMap Problem
The most "system platform specific" meta-data contained in these EEPROM formats are things like the "compatible" architecture binding, memory size/reservations, and the PinMap information; which determines what pins are used for inputs (switches, sensors), outputs (LED's, actuators), and other functions. The PinMap information is specific to one "compatible" architecture binding, and so the PinMap information for the TI AM3358 (Beaglebone) doesn't work for the Broadcom BCM2835 (RaspPi), etc. That could make it harder to design one product that supports several different "compatible" architecture bindings. In other words, if I have an add-on board that can plug into either a Beaglebone Black OR a Raspberry Pi, (presumably with an adaptor) then how can I get it to work on both platforms with one EEPROM?The short answer right now, is that I don't think you can (easily).
The idea behind having a PinMux section, is to be able to read configuration information that may be required very early in the boot-up process, such as configuring the display screen in order to see the system bootup messages, as the system is booting. But the vast majority of add-on peripherals won't need to redefine the basic pin multiplexing of the system platform to function, they will simply add a peripheral to an existing I2C, SPI, or UART interface that has already been defined by the FDT at boot time. So, why all the extra complexity?
What's the Cross-Platform Use Model, Kenneth?
If you think about other (bus) interfaces, like USB, PCI, and PCI-express, they are more microprocessor make/model agnostic, because you design to the bus interface. That's why for example, a PCI card works on a variety of micro-processors (Intel, AMD, ARM, etc.) because the bus definition is independent of the processor. The same kind of approach could be taken with the Device Tree - binding the microprocessor pins to (virtual) buses like UART1, I2C1, SPI2, etc. and then binding the specific peripherals to those (virtual) buses using the device tree overlay. That is possible today, but most designers bind peripherals directly to specific device pins.
So what is the Cross-Platform Use Model today?
I suppose with the current device tree and overlay implementations
you could erase and rewrite the product EEPROM for
each different model of microprocessor, but that's a manufacturing/logistics nightmare.
Or you could use the FDT EEPROM format, and include a whole separate FDT tree for each
different model of microprocesor - but that's going to use a lot of EEPROM memory.
So there are solutions today, they are just NOT very simple or elegant.
Suggestions for Cross-Platform Device Trees
- Headers for Peripherals should be Architecture Neutral :
Consider that someone is using an adaptor to put a Raspberry PI HAT on a BeagleBone Black, or visa versa. The "Header" information of Product Name/Model/UUID etc. is NOT Architecture specific - why make it so? The different device tree files for the same peripheral could be organized by the "compatible" tag. For example, if I have a Cross-Platform peripheral named "myWidget", it could be something like :
/firmware/AM3358/myWidget.dts
/firmware/BCM2835/myWidget.dts
- Put Architecture Specific Data in it's own ATOM :
If I need to include a different PinMap overlay for TI AM3358 and Broadcom BCM2835, how about making a PinMap ATOM type that includes the processor "compatible" field? That way, you can search the different PinMap ATOMs for your "compatible" processor type and just use that one. As a device overlay, it would be smaller in size, as it would just need to define the pins that are remapped. - Define Pin Mapping in terms of Common Interface Types
While different microprocessors may have different pin names and types, they usually implement standard interfaces like UART1, I2C1, SPI2, GPIO, etc. If the primary, architecture specific FDT bound pins to standard interface types, then the device tree overlays could be much more generic.
In coming articles, I'll present some ideas for mapping the standard interfaces like GPIO, UART1, I2C1, SPI2, etc. as "Smart Objects", and how that can address some of the cross-platform interface problems facing designers today.
References, Footnotes, and more...
- Device Tree for Dummies - Thomas Petroni
- BeagleBlack Device Tree Tutorial - Adafruit
- Xilinx Device Tree Tutorial - Xillybus
- Altera Device Tree Tutorial - Xillybus
- ARM Device Tree Support - Ubuntu
- Altera Device Tree Support - Altera
- Index of Device Tree Bindings - kernal.org
- Device Tree Graphing - kernal.org
- libfdt - manipulating FDT Blobs - David Gibson
- Linux Bootloaders - informit.com
- Device Tree PnP - Eli Billauer
- Device Tree Overlay Manager - Pantelis Antoniou
- Device Tree Overlay Proposal - Grant Likely
- BeagleBlack Univeral I/O - cdsteinkuehler
- BeagleBlack Device Tree Overlay Generator - Kilobaser
- GPIOs on the Beaglebone Black using the Device Tree Overlays- derek molloy
- Supporting 200 Different Expansion Boards - elinux.org
- DT, The Disaster so Far - Mark Rutland
- Board File to Device Tree Migration - Pantelis Antoniou
- Device Tree Overlays - Jonathon Corbet