Digital Experience

Raspberry Pi GPIO with Kotlin Native


Nish Tahir

Principal Software Engineer

Kotlin has been getting a lot of attention as an officially supported language on the Android platform. While it works fantastically there and on the JVM, it does target other platforms: namely, the web with KotlinJS and native platforms via Kotlin native.

If you aren’t familiar, the Kotlin native (fondly referred to as Konan) toolchain expands the Kotlin compiler with the ability to output native executables that don’t need to run inside of a VM. If you are interested in learning more about the platform, I go into quite a bit of detail in a previous related post: A look into Kotlin native.

While Konan is still in its early access preview stages, it’s already capable of targeting quite a few platforms not the least of which is the Raspberry Pi 2 and 3. In this blog post, I’ll illustrate the process involved in using native libraries with Konan using Konan to access the Raspberry Pi’s GPIO using WiringPi.

Enter WiringPi

WiringPi is a simple abstraction for PIN-based GPIO access. Many of its APIs are designed to mimic the Arduino Wiring system, so anyone with Arduino experience will feel right at home using WiringPi.

Before getting started, it’s important to note that, at the time of this writing, you can only cross-compile Kotlin native code for the Raspberry Pi on a Linux OS.

This is a limitation of the compiler that is expected to be resolved in the future. If you are working on a different platform you can choose to follow along in a virtual machine.

We’ll need to build WiringPi from source and statically link and archive the resulting native objects. Thankfully, the included Makefile does this for us.

This step needs to be done on the Raspberry Pi because the resulting objects are compiled specifically for its architecture.

While it is possible to cross-compile for the device, it’s beyond the scope of this post.

The compiled output generates libwiringPi.a, which is an archive containing the native library.

Next, we need to create a *.def definitions file for our library. This file tells Konan which headers to include while generating method stubs for interacting with our native library. We’ll have to copy the header files into our project. We can define these in a file called wiringPi.def.

Next, we need to put together our project’s build script. We’ll be using Gradle. Here’s the entire build script to get started.

Now let’s break down the important bits. Here we are defining a konanInterop. This essentially tells Konan that we plan on including some native libraries and headers.

Here, we define an interim called wiringPi and point it at the wiringPi.def file that we defined earlier. We’re also adding the src/include/ directory to search for header files using the includeDirs property.

In order to link to the wiringPi library we just generated, we use the linkerOpts property.

The -l flag is used to tell it to link to libwiringPi.a note on the omission of the lib prefix. The -L flag is used to add src/include/ to the search path.

In order to generate an executable artifact from our source, we have to define konanArtifacts.

In this example we define ktpi as our build artifact, include the wiringPi interop, and set the 'raspberrypi' as the target architecture. We also set src/main/ as the input sources folder for our build.

We are finally ready to write code. Here’s the source for a sample blink application that simply turns an LED on and off indefinitely.

First, we import the generated method stubs and the interop library. This is just boilerplate for stuff we will want to do later.

Next, we define the pin number for the GPIO pin we plan to use. In this case, I selected pin 0 based on the simplified WiringPi pin numbering system. For a full description of the pinout and alternative pin numbering schemes, I recommend reading through the official documentation.

The main function is pretty self-explanatory. We invoke wiringPiSetup(), which is required before using any of the library's functionality. Then, we register our GPIO pin as output using pinMode(LED, OUTPUT), like we would on the Arduino.

Finally, we set up an infinite loop where we toggle our pin between the high and low states using digitalWrite.

We simply run the gradle build command to build and then execute the generated *.kexe artifact.

The complete sample project is available on GitHub here.

Conclusion

Kotlin native is shaping up to be a great alternative to writing code targeting native platforms. Its most attractive feature is its interoperability with C. We’ve explored using native libraries to build native apps targeting the Raspberry Pi. While there is a bit of setup involved, it’s really easy to work with.

Be the first to know

Get curated content delivered right to your inbox. No more searching. No more scrolling.

Subscribe now