7 7
Larry Bank

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

Share this post


Link to post
Share on other sites

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. 

Share this post


Link to post
Share on other sites

I just got the first version ready. It should work correctly with Orange Pi Zero, OPZ+2, Orange Pi One/lite and Nano Pi Duo boards. Please let me know if you want to try it and I'll add you as a developer to my gitlab repo. Once it's in good shape, I'll share it to everyone on github.

Share this post


Link to post
Share on other sites

I just added support for callback interrupts to the GPIO pins. This is functionality exposed by the kernel GPIO driver. What I can't find is a way to set the pull-up / pull-down resistors of the pins. Does anyone know how to do that on Allwinner boards?

Share this post


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 : https://github.com/duxingkei33/orangepi_PC_gpio_pyH3

 

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.

 

Share this post


Link to post
Share on other sites
7 minutes ago, zador.blood.stained said:

Also the sysfs is deprecated, so for the mainline kernel it's recommended to use libgpiod instead.

Thanks for letting me know. I'll read the docs and see how easy it is to swap out the sysfs for gpiod calls.

Share this post


Link to post
Share on other sites

Hi,

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 !

 

Cheers
Tido

Share this post


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
root@orangepizeroplus:~/git/ArmbianIO#

Share this post


Link to post
Share on other sites

Yes, I don't own all of the boards supported by Armbian. The library needs the board name and a pin-to-GPIO table for each supported board. Perhaps you can add the necessary info. You need to add the board name (found in /run/machine.id). Then add the corresponding pin to gpio table for that board.

Share this post


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,
			160,164,184,166,-1,167,162,-1,163,257,
			-1,256,171,254,255,-1,251,233,234,165,
			-1,168,239,238,-1,185,223,224,187,-1,
			188}; 

 

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

If you are not familiar with Git Introduction to GitHub

Share this post


Link to post
Share on other sites

@TidoOh........ Um Yeah, I'm really not understanding those numbers in your Tinkerboard example. I understand -1 means the pin is not available to use as a GPIO but where do I derive the other numbers from?

 

@Larry Bank I'll look into your info this weekend as this might answer my question to Tido.

Share this post


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 ?

Share this post


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,
                        199,1,7,0,-1,3,19,-1,18,15,
                        -1,16,2,14,13,-1,10,-1,5,4}; // last 3 pins are TTY header


 

Share this post


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?

Spoiler

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

 

 

Share this post


Link to post
Share on other sites

12 are used for that, more than I thought but I counted these now :-)

Nevertheless,

6 hours ago, Tido said:

tinker as well as OPi have up to 3-digits number

whereas in the DTS I only found the Pin-Number. I show you a picture of what I am missing here:

5a367926b5513_gpio2.thumb.png.64a65b611e3cd1d0d8d81e6cceb0abfb.png

Share this post


Link to post
Share on other sites

I have already downloaded it, looked at it and again looked at it. Still no solution to what I am looking for. My conclusion:

Either OPi and tinker do it different to Le Potato (Amlogic) or I simply don't know how to read these tables in that PDF.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
7 7