ArmbianIO API proposal

Recommended Posts

I was chatting with @tido about ways to help the Armbian community and I came up with the idea of a common C library to access the I2C, SPI and GPIOs of all supported boards. There are of course kernel drivers to communicate with these things, but there are differences between boards that this API could help smooth out. For example, different CPUs (and boards) map the GPIO pins very differently. Projects such as WiringOP and WiringNP try to copy the Raspberry Pi library, but this is also flawed because it's based on the BCM283x GPIO numbering. What I propose is to create a set of simple functions for accessing GPIO pins using the physical pin number as a reference. On all boards, the 5V pin will be considered pin 2 and the numbering goes from there. There are also sometimes pushbuttons present on the board which are mapped to GPIO inputs. These are also covered by my API. Much of the code is already written and I will release it shortly.  I'm posting this topic to get feedback and to reach out to people who might make use of this. Here is a list of the functions so far:


int AIOInit(void);

void AIOShutdown(void);

const char * AIOGetBoardName(void);

int AIOOpenI2C(int iChannel, int iAddress);

int AIOOpenSPI(int iChannel, int iSpeed);

int AIOCloseI2C(int iHandle);

int AIOCloseSPI(int iHandle);

int AIOReadI2C(int iHandle, int iRegister, unsigned char *buf, int iCount);

int AIOWriteI2C(int iHandle, int iRegister, unsigned char *buf, int iCount);

int AIOReadSPI(int iHandle, unsigned char *buf, int iCount);

int AIOWriteSPI(int iHandle, unsigned char *buf, int iCount);

int AIOReadWriteSPI(int iHandle, unsigned char *inbuf, unsigned char *outbuf, int iCount);

int AIOReadButton(void);

int AIOAddPin(int iPin, int iDirection);

int AIORemovePin(int iPin);

int AIOReadPin(int iPin);

int AIOWritePin(int iPin, int iValue);

Edited by Tido
added Testers wanted
Link to post
Share on other sites
Donate and support the project!

I'm currently working on a fork of the pyA20 python library which is used quite often by people here when playing with GPIO, spi or i2c. It's not ready for public at the moment, but it will be soon. ;) It has an automated board detection, pin naming is consistent so that you can use your python scripts on every supported board without renaming everything. And it has a 'board detection' mechanism to use the right pin mapping during the installation. 

Link to post
Share on other sites

I see that you are using /sys/class/gpio to access GPIOs.

But other libraries are using /dev/mem to do a "mmap" directly to SoC registers located at 0x01C20800, which is faster and allows also to access to Pn_PUL0/Pn_PUL1 registers at offset 0x1c and 0x20 respectively.

Maybe you can take a look at this library :


Link to post
Share on other sites
1 minute ago, martinayotte said:

I see that you are using /sys/class/gpio to access GPIOs.

But other libraries are using /dev/mem to do a "mmap" directly to SoC registers located at 0x01C20800, which is faster and allows also to access to Pn_PUL0/Pn_PUL1 registers at offset 0x1c and 0x20 respectively.

Maybe you can take a look at this library :


I know there are direct means to access GPIOs, but then I would need to write code unique to each CPU. If Armbian only supported AllWinner H3 devices, it would be an easy decision. For now, I think it's best to keep the code simpler and support all SoCs.


I'm not sure where this project is headed. I don't have the time to turn it into a support-everything/do-everything library. I saw a need and I put together a simple solution. It would be great if this was given the "blessing" of Armbian and turned into a real community effort.


Link to post
Share on other sites


Larry patiently showed my how to use the armbianIO library to talk to the GPIO pins.
While all other go for Python and compatible to RPi - this is different.
This is designed native for SBC (Single Board Computer). No translation to the GPIO numbering necessary it fits 1-to-1.

We have built a first show case where 3 LED show you the temperature of your SoC. I guess you can imagine yourself several scenario's where this can be very helpful.

If you have some LEDs, 25min time it would be great to hear from you if it worked with your SBC

To start, please look here !



Link to post
Share on other sites

Can't use this with Opi zero plus. Get this error


root@orangepizeroplus:~/git/ArmbianIO# make
cc -c -Wall -O2 armbianio.c
armbianio.c: In function ‘GPIOThread’:
armbianio.c:367:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
 int iPin = (int)param; // pin number is passed in
armbianio.c: In function ‘AIOAddGPIOCallback’:
armbianio.c:447:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  pthread_create(&tinfo, NULL, GPIOThread, (void *)iPin);
ar -rc libarmbianio.a armbianio.o ;\
sudo cp libarmbianio.a /usr/local/lib ;\
sudo cp armbianio.h /usr/local/include
root@orangepizeroplus:~/git/ArmbianIO# make -f make_demo
cc -c -Wall -O2 main.c
cc main.o -larmbianio -lpthread -lm -o demo
root@orangepizeroplus:~/git/ArmbianIO# ./demo
Unrecognized board type, aborting...
Problem initializing ArmbianIO library

Link to post
Share on other sites

@pbezza in your Git folder, look for: armbianio.c  and open it in your favorite text-editor.


The following are lists which translate pin numbers into the GPIO numbers used by the different boards. 
The first entry (0) is for the on-board button (if present). 
A   -1   indicates that the pin is not available to use as a GPIO (e.g. +5V, GND, etc).  The numbering normally starts with the 3.3v pin as 1 and the 5V pin as 2. 
The TTY header comes after the last GPIO pin and is numbered from the pin closest to the edge of the board. 

* each line holds exact 10 numbers *


for example:
// Tinkerboard
static int iTinkerPins[] = {-1,-1,-1,252,-1,253,-1,17,161,-1,


Please make a git push - once you have added yours - Thank you.

If you are not familiar with Git Introduction to GitHub

Link to post
Share on other sites

If you look at my Google Docs (in the signature) 3-color-LED example, from Asus I found a very nice table. Yesterday evening I was searching this for Le Potato = fail.

I found the connector in the schematics, but not the numbers as it was for the Asus Tinker Board. I then tried to Google: ARM GPIO (but now what do I looking for - registers - interrups - ??) I simply don't know :blink:

Can someone give some guidance ?

Link to post
Share on other sites

With a little bit of googling, I was able to figure out GPIO assignment for the Orange Pi Zero Plus. It is identical to the Orange Pi Zero.

I don't think I have rights to push to git so here is the code.


// Orange Pi Zero Plus
static int iOPIZPPins[] = {-1,-1,-1,12,-1,11,-1,6,198,-1,
                        -1,16,2,14,13,-1,10,-1,5,4}; // last 3 pins are TTY header


Link to post
Share on other sites
9 hours ago, TonyMac32 said:

GPIO in the device tree.

a well hidden place by libre, nothing in their Wiki :wub:  thank you for showing me Tony.

To get a picture of the list/qty,  I extracted them and put it into a 'logic' order, I only count 36. Of which only 28 are on the 7J1 (40-pin header).

Just as I think about it, how can they be addressed - tinker as well as OPi have up to 3-digits number if you look above. I am afraid I still got nowhere beside listing some pins and their logical place (2j3, 7j1, 9j1). I guess I am again in a one-way street or am I wrong?


01	2J3 Header Pin3
02	2J3 Header Pin4
03	2J3 Header Pin5
04	2J3 Header Pin6

// 40-pin header is 7J1 //
01	7J1 Header Pin3
02	7J1 Header Pin5
03	7J1 Header Pin7
04	7J1 Header Pin8
05	7J1 Header Pin10
06	7J1 Header Pin11
07	7J1 Header Pin12
08	7J1 Header Pin13
09	7J1 Header Pin15
10	7J1 Header Pin16
11	7J1 Header Pin18
12	7J1 Header Pin19
13	7J1 Header Pin21
14	7J1 Header Pin22
15	7J1 Header Pin23
16	7J1 Header Pin24
17	7J1 Header Pin26
18	7J1 Header Pin27
19	7J1 Header Pin28
20	7J1 Header Pin29
21	7J1 Header Pin31
22	7J1 Header Pin32
23	7J1 Header Pin33
24	7J1 Header Pin35
25	7J1 Header Pin36
26	7J1 Header Pin37
27	7J1 Header Pin38
28	7J1 Header Pin40
	9J1 Header Pin2
	9J3 Switch HDMI CEC/
Total	36 Pins of 40



Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.