The Gpio Library for Toradex Computer-on-Modules (CoMs)

Friday, September 18, 2015


Do you remember the good old times of the 8bit microcontrollers? Using a digital IO was one of the simplest tasks you could do – one bit to select the direction and one more bit to set or request the pin level was all you needed to know.

Today’s Arm processors are highly versatile systems on a chip and offer many more options to configure an IO. Not only direction and level, but also slew rates, pull resistors and alternate functions can be adjusted at runtime. Configuring all the required register bits correctly is not so easy anymore, especially if want to do that task from a modern operating system like Windows Embedded or Linux.

IO Representation
Using a computer on module poses even more challenges: Given you want to toggle IO #12; is 12 the logical Gpio number? Is it a CPU ball or a module pin? Maybe even a connector pin number of the entire embedded device? It is a good practice to define this carefully in order to avoid confusion.

For using the Toradex Gpio Library, the first step is to understand how IOs are represented. All IOs are stored as a 32bit number. The upper 16 bits define the context of the IO (SODIMM pin / GPIO) while the lower 16 bits define the actual number. For example the Colibri SODIMM pin 17 is represented by the 32bit number 0x00200011:

Bits 31..16 Bits 15..0
0x0020 0x0011
This is an SODIMM pin… …number 17

To simplify the programmers’ life we have defined a data type uIo, along with a number of C macros to work with the uIo pin definitions. It is important to note that there are two sets of macros: One for the static initialization of variables, e.g.

uIo myPin = COLIBRI_PIN(17);

and one for the dynamic use in the program code, e.g.

myPin.GenericDefinition = IOCOLIBRIPIN(17);

Due to limitations of the C compiler, it was not possible to define one macro for both use cases.

Main Library Functions
Now that you know how an IO is represented, let’s see what we can do to it. The Gpio library has one major function to modify an IO: Gpio_SetConfigString(). You simply pass a string to this function to define all the parameters that shall be changed. This could look like dir=out, lvl=1, pull=up100k Isn’t that easy? The only thing you need to do is look up the correct keywords in the documentation of the Gpio library.

There are two equivalent functions to read back the current IO configuration Gpio_GetConfigString() and Gpio_GetConfigInt().

More Performance
So that’s all? Not really. As you might imagine, the string parsing we use for the generic functions consumes quite some CPU cycles. This is usually affordable, given the high performance of a modern Arm processor – especially if you simply want to turn on an LED once in a while. For higher performance requirements, we added individual functions to set and get IO levels and directions.

The effect of

Gpio_SetConfigString(handle, io, NULL, Llvl=1, StoreVolatile);

is identical to

Gpio_SetLevel(handle, io, ioHigh);

but the latter executes much faster.

Let me guess your next question: Why should I use Gpio_SetConfigString() at all? It looks more complicated, executes slower, so where’s the benefit?

More Flexibility
First it is a generic approach. We need the Gpio_SetConfigString() function anyway to configure more sophisticated parameters like the pull resistor value or slew rate – so it is an obvious solution to use the same string to setup the whole pin configuration, including direction and pin level.

Second, we support storing such pin configurations in the Windows CE registry. Whether you use program code to create the registry entries, or whether you do this as part of your individual device setup does not matter.

You can provide a registry path to the Gpio_Init() function. When calling a subsequent Gpio_Open(), the library searches for IO configuration entries in this path, and applies them to the hardware. To give you an example: insert the following registry value:

colibripin_133=altfn=-1, dir=in, pull=down

Once you call

h = Gpio_Init(LHKLM\\SOFTWARE\\myGpio);

The module pin 133 is automatically configured as GPIO, input, and with a default pulldown resistor.

The Gpio library is intended to be a simple still flexible building block for your own embedded device applications. At the time of writing, the library was available for all our NXP®/Freescale based products, covering the full range from the Colibri VF50 to the Apalis iMX6 quad core computer modules.

We use this library as the base for our own Windows CE drivers and tools with the goal to provide a unified notation for all GPIO related code.

The full set of libraries and demo code is freely available for download. The demo code includes a command line tool to configure GPIOs:

Author: Andy Kiser, Senior Development Engineer, Toradex AG
Share this on:


Chitresh Gupta - 8 years | Reply

A great blog to introduce Toradex customers with new concept of GPIO library, succeeding the blog on "Evolution of the Toradex CE Libraries". I am sure it will clear away any ambiguity that Toradex customers might have with xxx_Set/GetConfigString() functions too.

Leave a comment

Please login to leave a comment!
Have a Question?