Conceived in 2014, the Eclipse MRAA project aimed to deliver a high-level, easy-to-use set of APIs for I/O access on Linux* boards and systems, similar to Arduino* offerings for MCU boards. At the time, the project targeted support for platforms such as Intel® Galileo, Intel® Edison and Raspberry Pi* boards, highly popular among IoT enthusiasts and makers. Over time, the project evolved substantially and won the appreciation of multiple IoT communities resulting in a number of new board and feature additions. In fact, the project’s success prompted Arduino* to adopt the use of the library in their Arduino Create* cloud-based IDE in order to target x86 IoT platforms.
Development on boards and kits in Linux* environments continues to present issues in key areas: access of I/O in a platform-independent manner, portability from platform-to-platform, and consistency from revision-to-revision.
Here is a detailed look at each issue:
- Access of I/O in a platform-independent manner: Kernel-level abstractions are low level and can be difficult to use for inexperienced developers. The Linux* kernel exposes the I/O interface through sysfs classes or device nodes. Depending on the implementation, the details can vary from one platform to another quite drastically. However, users expect to be able to use the I/Os at a much higher level of abstraction. For example, in order to initialize i2c bus on the Intel® Edison board, the following steps are needed:
- Set Tristate to 0
- Set GPIO14 to input
- Set GPIO165 to input
- Set GPIO236 to output and disable
- Set GPIO237 to output and disable
- Set tristate to 1
- Set GPIO213 to input
- Set GPI212 to input
- Change pinmode for pin27
- Change pinmode for pin28
These details vary from one board to another and among different revisions of the same board.
- Portability from platform-to-platform: In some situations, usually buses, device drivers provide access to I/O. Configuration of these drivers is done through Device Trees (ARM*) or ACPI tables (x86) and is usually provided by the vendor as part of the BSP. However, there are no set standards for exposing the capabilities of the underlying platform through device drivers. Consequently, developers make choices suitable for the particular platform. This leads to APIs that are not uniform across platforms and creates the need for customization of drivers for sensors connected to these platforms.
- Consistency from revision-to-revision: A development board and the SoC on the board typically undergo revisions either to add new features or to fix bugs. In that process some changes to the I/O interfaces creep in – typically the I/O pin numbering may change. Certain steps needed to enable the I/Os can change or become unnecessary.
Using system classes and devices for GPIO and bus access from software is usually not straightforward in Linux*, since the OS numbering scheme does not match the labeling on the board. MRAA presents a façade which makes the relationship between I/O and the hardware more intuitive to developers. Here are some example class and device paths on a typical board.
Figure 1. Hardware Abstraction MRAA
MRAA makes it easier for developers and sensor manufacturers to map their sensors & actuators on top of supported hardware and allows control of low level communication protocols from user-space using high level languages and constructs.
MRAA is supported on a large number of IoT platforms based on Intel® x86, ARM*, and MIPS processors. One FPGA developer kit is also supported. Further, MRAA introduces the concept of subplatforms for extending I/Os on existing boards or adding I/O capabilities to systems that have none. These I/O expanders are often offered in the form of an IC or an MCU, and they can be connected to the host device and utilized using the same MRAA APIs. In such cases, the user application runs on the host and communicates with the expander via device drivers or 3rd party communication libraries (e.g., Firmata*).
The current list of supported boards is as follows:
- X86: Intel® Galileo, Intel® Edison, Intel® Joule™, Intel® NUC DE3815, Intel® NUC5, MinnowBoard MAX*, MinnowBoard Turbot*, Aaeon*, UP*, UP2*, IEI* Tank 870
- ARM*: Raspberry Pi*, Banana Pi*, Beaglebone* Black, phyBOARD-Wega*, 96Boards* (Bubblegum, DragonBoard, HiKey, Rock, Ultra)
- MIPS: Linkit* Smart 7688, Onion* Omega2
- FPGA: Terasic* DE10-Nano
- Subplatforms: FTDI4222, Arduino 101*, GrovePi+, Generic Firmata* Boards
NOTE: Unfortunately, the JSON format does not work in situations requiring pin muxing or custom steps to initialize I/Os on the platform. Those scenarios require writing problem-solving at the C level.
The MRAA library offers a string initializer feature for the I/O classes. This eliminates the precondition for data type knowledge from higher level frameworks or services that need to initialize and interact with I/Os using the MRAA library. In short, MRAA I/O initializer functions generally use a combination of integers, booleans and strings to specify the required I/O resource. This feature introduces a generic MRAA init_io function which works exclusively on a string input, sending it to an internal parser for decoding and I/O initialization.
IMRAA, a platform configuration service that is part of MRAA, provides platform configuration before user applications initialize the MRAA library. This component has been used mainly for setting up user permissions in order to gain access to I/O resources on Linux systems and to detect and load connected subplatforms when an application is launched. IMRAA could be enhanced, if needed, to act as a daemon for dynamic platform configuration.
At a high level, the MRAA sources are organized as follows:
MRAA is open-source software offered through GitHub*. It can be installed on any Linux* system using the cmake build system, and the project has few dependencies on other system packages, the most notable being SWIG. This source translation framework is necessary if bindings for other supported languages are desired. The supported Operating Systems are:
- Standard Linux* Distributions: Fedora*, Debian*, Ubuntu*, Ubilinux*, Arch Linux*, OpenSUSE*
- Embedded Linux* Distributions and Projects: Yocto Project*, OpenEmbedded, 01.org, Wind River Linux*, Wind River Pulsar Linux*, Android Things*
- Real-time Embedded OS: Zephyr*
- Windows*: Only using Docker* containers and the mock platform
Contributions are checked through the use of the Travis CI system, unit testing, and static code analysis. A system running Doxygen* on a Jenkins* instance generates documentation. Packaging is done on demand on stable releases only. The community maintains most of the distribution channels for the supported OSes listed above.
Over the course of 2017, the project saw over 30K unique visitors and approximately 15K unique downloads according to GitHub* metrics. Good adoption occurred internally at Intel and externally from key companies such as IBM*, Linaro*/ARM*, Google*, Emutex*, Phytec*, GE*, Technexion*, Qualcomm*, STMicroelectronics*, u-blox*, Honeywell*, Siemens*, Mediatek*, and others. Adoption took place either directly, or through custom-designed Intel® IoT Developer Kit boards requested by some of these partners.
The project is still under active development from by Intel and the developer community. The MRAA project is also tightly integrated with Intel® System Studio, a free product that integrates multiple Intel® tools and libraries with the Eclipse* IDE.
*Other names and brands may be claimed as the property of others.