A smart man makes a mistake, learns from it, and never makes that mistake again. But a wise man finds a smart man and learns from him how to avoid the mistake altogether.
—Roy H. Williams
Lately, I've been working on automatic discovery and configuration of devices and peripherals, using
Binary Level Objects, like the
IPMI FRU, the
Devicetree and
Devicetree Overlay formats.
Typically these have been implemented using just a "dumb" storage device,
like an EEPROM, or an
SDcard, or perhaps a
Dynamic NFC/RFID tag.
So, what then, do I mean by a "Smart" Devicetree?
Low Cost Microcontrollers
A few years ago, we were all abuzz about the "$1" ARM Cortex devices like the Cortex M-3, and later, the Cortex M-0 devices. Hat's off to ARM Ltd. for making 32-bit microcontrollers ubiquitous. By now (2015), the cost of simple microcontrollers are more about the amount of flash memory and the features included, than the microcontroller itself. These days I can usually find a low feature, low pin count, microcontroller for little more than the cost of a "dumb" storage device. Additionally, the smartphone and mobile handset market have led the push to smaller packages, and lower power microcontrollers, in order to increase the battery powered run time. So the threshold for adding "intelligence" (i.e. a microcontroller) to solving hardware design problems has gotten very low indeed.
Common Data Structures
Regardless of what kind of microcontroller and development environment you choose for your products, you'll soon realize that you need to keep track of a lot of metadata which most development enviroments will leave up to you, the user. I'm talking about the kinds of data you need regardless of what kind of product you are building, and what kind of firmware/software you are using. How do you keep track of things like Serial Numbers, Version Numbers, MAC ID's, Interface Addresses, etc. in a uniform way? Where do you keep them in your firmware (program)and how do you keep them current without having to change the firmware itself? From a complex Drone design to a more simple toaster oven, wouldn't it be good if we could handle all that metadata in a more simple and consistant way?Common Interfaces
Most of the low cost microcontrollers today have a good mix of common interfaces, like I2C, SPI, and UARTs. And most vendors also include some simple emulation functions, that allow you to reserve an area of the microcontroller's flash memory to emulate a "dumb" storage device using those interfaces. In other words, if you use an I2C EEPROM emulation function on most microcontrollers, then to the outside world connecting to your microcontroller, your microcontroller looks exactly like a "dumb" I2C EEPROM. The same concept applies if you bind one of your SPI Slave controllers to a SPI EEPROM emulator function, then to the outside world, your microcontroller would look just like a "dumb" SPI EEPROM.
Devicetree Flash Mapping
Of course, "under the hood", this solution is not "dumb" at all. When you utilize an I2C or SPI EEPROM emulation function, you generally pass a pointer to the flash memory area that you want reserved for the EEPROM memory emulation. If we are not going to do much else with microcontroller we might even reserve the majority of the microcontrollers flash memory. Now, imagine for a moment that reserved flash memory area is used to hold the Flattened Devicetree "BLOB" of binary data, perhaps for an expansion board. What we have now, is a "Smart Devicetree". We can even access that Devicetree from two different interfaces, namely I2C, and SPI at the same time. In my last article I demonstrated how to map the Devicetree onto a Modbus RTU using a UART interface. I've successfully employed these techniques in several customer designs.
Adding Some Intelligence
You'll notice that I put an "Internal Temperature" block in the above microcontroller block diagram, as most microcontrollers have a junction temperature measurement that can be used to read the internal temperature of the device. Now, imagine for a moment, that the microcontroller takes a initial temperature measurement when it boots, and maintains a running average temperature at boot. So, what happens if we store that as a property into the Flattened Devicetree (BLOB)? Well, now we have a Smart Devicetree.
Summary
Adding the Devicetree data structure to an embedded micrcontroller design is pretty straightforward and simple, and enables the automatic discovery and configuration of a variety of devices and peripherals; and that is just the beginning of what we can do with a Smart Devicetree.
References, Footnotes, and more...
- Modbus Specifications
- Devicetree for Dummies - Thomas Petroni
- BeagleBlack Devicetree Tutorial - Adafruit
- Xilinx Devicetree Tutorial - Xillybus
- Altera Devicetree Tutorial - Xillybus
- ARM Devicetree Support - Ubuntu
- Altera Devicetree Support - Altera
- Index of Devicetree Bindings - kernal.org
- Devicetree Graphing - kernal.org
- libfdt - manipulating FDT Blobs - David Gibson
- Linux Bootloaders - informit.com
- Devicetree PnP - Eli Billauer
- Devicetree Overlay Manager - Pantelis Antoniou
- Devicetree Overlay Proposal - Grant Likely
- BeagleBlack Univeral I/O - cdsteinkuehler
- BeagleBlack Devicetree Overlay Generator - Kilobaser
- GPIOs on the Beaglebone Black using the Devicetree Overlays- derek molloy
- Supporting 200 Different Expansion Boards - elinux.org
- DT, The Disaster so Far - Mark Rutland
- Board File to Devicetree Migration - Pantelis Antoniou
- Devicetree Overlays - Jonathon Corbet