Integrated circuits (ICs) are a very important component of many modern-day devices. Current devices contain controllers and component ICs that communicate with each other with various methods and protocols. In the past these custom-made electronic components required highly specialized knowledge to produce and use. With the relentless push of very-large-scale integration (VLSI) technology, the cost of electronics plummeted, and with open-source development, software availability became ubiquitous. These two phenomena–low cost hardware and open-source software--have given rise to the maker movement that is fueling the rise of Internet of Things (IoT) in which everything is smart and connected.
With the promise of IoT, both established players and new startups are entering the market at a torrid pace with new product announcements. If fact, the amount of device diversity currently seen at the edge is unprecedented, and the applications seem limitless. These devices create massive opportunities in areas such as smart buildings and cities, automotive applications, intelligent vending and retail, manufacturing and industrial processes, biomedical industries, agriculture, environment monitoring, security, and many other verticals.
Microcontrollers (MCUs) like Arduino*, a de facto standard in the IoT space for years, have limited compute power. Many MCUs require programming on bare metal or a real-time OS. Newer products such as Raspberry Pi*, Intel® IoT Developer Kit boards, Linaro 96boards*, and Nvidia Jetson* exhibit more compute power and run on standard Linux* distributions. These products provide the flexibility of programming in an operating system like Linux* with I/Os similar to those of MCU, which increases ease of use.
Most of the aforementioned platforms come as single board computers (SBCs) that interface to peripheral devices through expandable daughter cards, usually referred to as shields, and exposed I/O pins. A variety of protocols are also made available, such as SPI, I2C, PWM, UART, etc. Unfortunately, there is no standard describing how the I/O pins are labeled and programmed, making development a more difficult task. We created the MRAA cross-platform, cross-OS library to abstract the details of I/O pin and bus mappings and simplify the level of effort and understanding required of IoT developers.
Eclipse MRAA (pronounced em-rah) is a low-level library written in the C/C++ language. MRAA abstracts the details associated with accessing and manipulating the basic I/O capabilities of popular IoT platforms and boards and presents a single, concise API delivering the following architectural features:
- Physical Pin Mapping: MRAA provides clear and consistent API function calls that match the corresponding physical pin labels on supported IoT boards.
- Kernel to User Space I/O Abstraction: MRAA serves as a translation layer on top of the Linux* I/O facilities. Although Linux* provides a fairly rich infrastructure for manipulating GPIOs and standard bus protocols, it does so at the kernel level. This presents difficulty for developers not experienced with device drivers, and it does not promote user-space rapid prototyping.
- I/O Expansion: MRAA provides access to I/O expanders and Arduino* MCUs, via Firmata*, connected to a Linux* host running MRAA, using the same API classes found on regular boards. The MRAA project refers to these expanders as subplatforms, and the application runs on the Linux host.
- Portability: Applications developed with the MRAA library can be ported to other supported boards if the same type of I/O exists on the new target. Furthermore, the C APIs simplify portability between Linux* boards and MCUs running Zephyr* RTOS through the use of the ZMRAA project which provides a near one-to-one mapping for the API calls.
NOTE: Although MRAA can be used to write platform-independent code, developers are still responsible for ensuring that code is robust enough to run on various target platforms and accommodate their specific limitations.
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.
We believe the MRAA project will achieve synergy with the Eclipse Kura* project. The project may act as a suitable replacement for the rather limited and now inactive jdk.dio framework. While it is true the MRAA Java* bindings are automatically generated with SWIG*, the MRAA project received several updates for type mapping between C++ and Java* to expose a set of Java* APIs with a native look and feel.
There is good synergy with multiple Eclipse* IoT projects such as Eclipse Mosquitto*, Eclipse Paho*, Eclipse Milo*, and other M2M projects. Furthermore, there is a very good integration between MRAA and the Eclipse* IDE already in place in Intel® System Studio. The Eclipse Foundation* may choose to reuse this in existing products.
Nowadays community spans well beyond Intel. The Eclipse Foundation* would encourage vendor neutrality and act as an arbiter in further development of the MRAA project.
During the initial phases, the project published stable iterations of the framework to the general public at a fast pace, as new features and bug fixes were constantly becoming available. Currently, the release cadence has settled at two major release per year, which include community contributions and fixes along with planned features and milestones from the project’s roadmap.
Library development plans for the upcoming quarters are illustrated in Figure 2.
Figure 2. Future MRAA Development
Near future development focuses on enhancements to the mock platform. The enhancements improve simulation of potential targets, and users receive additional mock I/O classes. These classes include additional configuration options, not only for the I/O APIs themselves but at a mock platform level too (currently this is fixed and offers 1 of each type of I/O only).
Intel plans to continue submitting code for new x86 platform launches and the Intel® IoT Developer Kits. Future releases may involve these features:
- APIs for the I2S Protocol: I2S is available on many higher end IoT platforms for driving audio devices. This will allow the MRAA library to control microphones and speakers for easier audio and speech-based application development.
- IMRAA Enhancements: These enhancements appeal to users working at the OEM/ODM and industrial application level. Development here centers on full conversion of the IMRAA to a daemon along with the addition of Socket support.
- Dynamic FPGA I/O Block Detection: This feature debuted as a proof of concept and will likely be formalized and added to the MRAA library as IoT FPGA developer kit availability increases.
- C# Language Support: The community added this support through external, hand-written bindings. We are currently investigating if they can be merged into the project or generated through SWIG*.