Map Raspberry hardware GPIO pins to gpiod chip line numbers

2.3k Views Asked by At

I was playing with my Raspberry Pi over the weekend. I used a tutorial from Freenove that I followed to realize a few simple circuits that are controlled by the GPIO pins on the raspberry.

The Freenove tutorial is using a deprecated library named WiringPi. Besides the fact, that its deprecated, my understanding is that WiringPi adds additional abstractions and simplifications to allow users to focus on their circuits and less on writing boilerplate code to integrate low-level (C) libraries.

Now I want to gain a better understanding about how user space applications interface with the hardware GPIO pins and I am not worried about writing boilerplate code. So I started to play with libgpiod, which has a C API that can be used to read and set GPIO pins and that works well.

One thing that is not clear to me is how I can map the physical hardware GPIO pins on the 40pin connector (which are numbered from 1 to 40) to one of the 54 internal line numbers that gpiod reports when I use the gpioinfo command.

On my Raspberry 3b+ with Raspbian 10 the gpioinfo command prints the following, with all line names showing as unnamed. The list goes on like this but I truncated it at 10 lines.

gpiochip0 - 54 lines:
    line   0:      unnamed       unused  output  active-high 
    line   1:      unnamed       unused  output  active-high 
    line   2:      unnamed       unused  output  active-high 
    line   3:      unnamed       unused  output  active-high 
    line   4:      unnamed       unused  output  active-high 
    line   5:      unnamed       unused  output  active-high 
    line   6:      unnamed       unused  output  active-high 
    line   7:      unnamed       unused  output  active-high 
    line   8:      unnamed       unused  output  active-high 
    line   9:      unnamed       unused   input  active-high 
    line  10:      unnamed       unused   input  active-high 
    [...]

I found an issue about missing GPIO line names which discusses this problem but I do not understand the answer or why it was closed.

How am I supposed to lookup the line numbers of the chip based on a pin name such as GPIO17? I found by trial and error that GPIO17 maps to line 17, but for example CE0 maps to line 8 and SCL1 maps to line 3, which I learned by trial and error using gpioset.

I am not sure if its a good idea to hard-code this mapping into my application, or if I somehow should discover these values programmatically to make the program more portable?

I tried to use gpiod_ctxless_find_line:

gpiod_ctxless_find_line ("SCL1", configuration->chipname, configuration->chipname_length, &offset);

but even while that returns a value of 0 (OK) the resulting offset is 66796 which is not the correct value. I assume it does not return anything, because gpioinfo has no names for the lines.

If I write a C program using libgpiod, can (should?) I discover these mappings at runtime, or is it ok to simply hard-code them? Is is possible that on a future Raspberry the SCL1 will not be at physical pin 5 or map to line 3?

2

There are 2 best solutions below

0
On

The issue you referenced about missing GPIO line names was resuscitated recently, and AFAIK has finally been resolved. The issue was that the device tree did not have gpio-line-names defined. This was corrected in the RPi 4B a while ago, but for some reason the older platforms were overlooked. I think all of the source files have been updated now - though you may still need an rpi-update for a while until the firmware is released for apt updates.

FWIW, I elected to add the gpio-line-names to my RPi 3B+ with a device tree overlay. I did this strictly as a learning exercise, but I'm not sure I learned much as device tree code seems arcane to me. Nevertheless, having finished the overlay project I do like the idea of having an overlay as it allows me to easily change the gpio-line-names to suit my preferences.

3
On

While I was writing this question, I found that the official Raspberry GPIO documentation has these pictures, which show the mapping, and then I realized that the yellow GPIO numbers from the second picture correspond to the libgpiod line numbers. So there is a one-to-one mapping between GPIOxx and line number:

enter image description here

enter image description here

I guess there were two confusing parts in my the learning process. The first was that WiringPi uses different GPIO terms than the Raspberry. For example, WiringPi has two blocks of GPIOs numbered as GPIO0 (wiringPi) to GPIO7 (wiringPi) followed by a gap for the special pins like SDA1 and another block numbered as GPIO21 (wiringPi) to GPIO29 (wiringPi). So the GPIO29 (wiringPi) is actually GPIO21 (raspberry) on the Raspberry.

The second part is that my breakout board shows only the semantic names for some GPIOs rather than the actual GPIO number (for example instead of GPIO 2 (SDA) it only shows SDA).

Using the pinout command one can see the official mapping of the Raspberry Pi which maps GPIOs to physical pins. The same information is present in the gpio readall command in the BMC column, but the name column shows the wiringPi GPIO names not the Raspberry pi GPIO names from the image above.