This next step is probably the most difficult part of the entire process because there is no one-size-fits-all method for getting the information and every board is different. So rather than concentrating on a specific set of steps, we will be discussing various strategies for acquiring the information. It also depends on which GPIO library you went with.

Strategies can range from looking at the microprocessor data sheet to finding similar code that already has the pins figured out, to having the GPIO library just tell you. Another strategy is simple trial and error by just setting a line and seeing if it changes the value. Often times though, it is a combination of different strategies combined together.

It's entirely possible that you may not need to create a chip file. If a chip file for your board already exists or one that is close enough exists, you should definitely use that one. If you do find that you need to create one, it's probably best to see what already exists and make a copy of that file to use as a starting point. When you make a copy, you will want to copy the entire folder.

If you followed the instruction in the software setup, you should have the Adafruit_Blinka folder in your home directory. Inside of there you'll want to navigate to src/adafruit_blinka/microcontroller which is where all of the chip files are located, sorted by manufacturer.

In the case of the Pine64, the AllWinner H3 chip is already set up, so we will make a copy of the h3 folder and leave it under the allwinner folder. The new folder is called a64.

If you create a new folder from scratch, be sure that __init__.py exists inside the folder or PyPI won't install it along with Blinka.

At a minimum, the folder should contain an __init__.py and pin.py file. The init file will most likely be empty or only contain a comment. The pin.py file will contain all of the Chip pin information. Here's what the h3 pin.py file looks like:

"""Allwinner H3 pin names"""
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin

PA0 = Pin(0)
UART2_TX = PA0
PA1 = Pin(1)
UART2_RX = PA1
PA2 = Pin(2)
PA3 = Pin(3)
PA6 = Pin(6)
PA7 = Pin(7)
PA8 = Pin(8)
PA9 = Pin(9)
PA10 = Pin(10)
PA11 = Pin(11)
TWI0_SCL = PA11
PA12 = Pin(12)
TWI0_SDA = PA12
PA13 = Pin(13)
UART3_TX = PA13
PA14 = Pin(14)
UART3_RX = PA14
SPI1_SCLK = PA14
PA15 = Pin(15)
SPI1_MOSI = PA15
PA16 = Pin(16)
SPI1_MISO = PA16
PA17 = Pin(17)
PA18 = Pin(18)
PA19 = Pin(19)
PA20 = Pin(20)
PA21 = Pin(21)

PC0 = Pin(64)
SPI0_MOSI = PC0
PC1 = Pin(65)
SPI0_MISO = PC1
PC2 = Pin(66)
SPI0_SCLK = PC2
PC3 = Pin(67)
SPI0_CS = PC3
PC4 = Pin(68)
PC7 = Pin(71)

PD14 = Pin(110)

PG6 = Pin(198)
UART1_TX = PG6
PG7 = Pin(199)
UART1_RX = PG7
PG8 = Pin(200)
PG9 = Pin(201)
PG10 = Pin(202)
PG11 = Pin(203)
PG12 = Pin(204)
PG13 = Pin(205)

PL2 = Pin((1, 2))
PL4 = Pin((1, 4))

i2cPorts = ((0, TWI0_SCL, TWI0_SDA),)
# ordered as spiId, sckId, mosiId, misoId
spiPorts = (
    (0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),
    (1, SPI1_SCLK, SPI1_MOSI, SPI1_MISO),
)
# ordered as uartId, txId, rxId
uartPorts = ((3, UART3_TX, UART3_RX),)

Checking with the GPIO library

We'll start with the easiest strategy, which is to check with the GPIO library. The first thing we want to do is map out the chip. We will start off by seeing how many GPIO chips are detected. There should be at least one, but there may be a few. To do this we type:

  • sudo gpiodetect

This tells us that there are 3 GPIO chips on the Pine64 and the number of lines that each controls. It's likely the bulk of them are on gpiochip1.

Next we look for some more detailed information by typing:

  • sudo gpioinfo

In this case, most of the lines are unnamed. In some chips, they may actually have the pin numbers which makes things much easier.

For the Pine64, since there are multiple GPIO chips and there are only 32 lines associated with the first chip. This means the bulk of the lines will most likely be associated with the GPIO chip 1.

In the H3 chip, we are only passing an integer, which means that it associates all the pin numbers with GPIO chip 0. However, for the A64 chip, we will likely need to specify which chip each of the lines is on, so instead os specifying something like:

PC0 = Pin(64)

If line 64 was based off gpiochip1, we would need to use a tuple instead of an integer and specify it more like:

PC0 = Pin((1, 64))

How do we know which line is associated with which GPIO chip? That involves a little bit of guess work. We know there are 32 lines in the First GPIO chip and 256 lines in the second. The third has only 2 lines, so it most likely will not be used.

Looking Up a Pinout Diagram

Sometimes looking up a Pinout diagram can help yield clues. A web search for Pine64 Pinout, yielded this pinout diagram available at http://joey.hazlett.us/pine64/pine64_pins.html, which is very helpful:

According to the diagram, it appears PC0 is using GPIO 64, which matches what we see in the h3 pin mappings.

Checking Data Sheets

The next thing we will do is try and find a data sheet with a web search. The Pine A64 uses the AllWinner A64 chip, which we can figure by doing some web searches and doing some reading. For this chip, there is a data sheet available here.

The important part of this data sheet is section 4 titled Pin Characteristics. It shows us the Pin Names grouped by GPIO blocks starting with GPIO B. You may notice that these Pin names match those in the Pinout Diagram.

Testing a physical GPIO Pin

Just to help out with figuring out the layout, we can test to see if setting a libgpiod line on a chip corresponds to the pin we think it should correspond to. Let's take pin PC0, which appears to be physically connected to Pin 19 of the 40-pin Pi header accord to the Pinout diagram. Let's connect an LED up to it so we can test turning it off and on:

We know it's on gpiochip1 and it uses line 64 and that's the only GPIO chip with enough lines. So we will type in the gpioset command like:

  • sudo gpioset gpiochip1 64=1

If everything is correct, the LED should turn on, which confirms our hypothesis. If we were to try out the same thing with pins such as PB1, which says GPIO 33, it would also likely be on gpiochip1, and after testing, this is in fact the case.

Interpolating the Numbering

Now you may notice that according to the Pinout Diagram, it says pins such as PL10 are using GPIO 362 and we know that none of the GPIO chips have that many lines, so we will take a different approach. There was no GPIO block A, so what if gpiochip0 controls GPIO block L onwards? Let's try connecting PL10, which appears to be connected to Physical Pin 7 up to the LED.

So we will hypothesize that for PL10, it is using gpiochip0 and line 10, so we will type the command:

  • sudo gpioset gpiochip0 10=1

Unfortunately, it didn't turn on the LED. However, after digging through some documentation a bit further, I found that PL10 does in fact correspond to GPIO 10 on gpiochip1. According to the Pinout, 362 refers to the GPIO pin number when accessing the pin via SysFs, which is an old way of accessing the pins and is not terribly efficient. When I set the pin via SysFs, it also did not light up the LED, but when running the gpioset command again, this time I got the error message:

gpioset: error setting the GPIO line values: Device or resource busy

The LED isn't turning on either way, which means we may not be able to run 3 of the pins on the Pi 2 header, but this is acceptable and perhaps we can revisit this in the future. The important thing is we have verified the pin mapping.

For the rest of the GPIO pins, it appears that all of the pins from GPIO B through GPIO H are fine and definitely running off gpiochip1. Let's take a look at a few known values and we will see if a pattern emerges.

According to the pinout diagram, we can see that PC0, PC1, and PC2 correspond to 64, 65, and 66 respectively, so it appears they are in order. PC5 is 69 and PC9 is 73. We can thus infer PC6 through PC8 are likely 70 through 72.

Ok, let's look that the pins starting with PB0, which appears to correspond to 32. According to the data sheet, there are only 10 pins in GPIO block B, so we will likely ignore 42 through 63. In fact, based on the note at the bottom of the Pinout, we can see that every GPIO block has 32 numbers allocated to it which makes figuring out the exact numbers much easier.

Finishing up the GPIO Pins

If there are any GPIO pins that don't belong, go ahead and remove those from the chip.py file. Add only the pins that are going to be used. If the chip.py file already existed from another board, add any new pins that your board uses that the other board may not have used.

Pin Aliases

If you need any aliases, after defining a pin, just refer to the already defined pin rather than making a new pin. For instance, if we wanted to create Pin PC0 and also have the name SPI0_MOSI, we would do something like the following:

Download: file
PC0 = Pin((1, 64))
SPI0_MOSI = PC0

I2C, SPI and UART Ports

We will add any I2C, SPI, and UART pins in a later section and address both the chip and board files at the same time.

Additional Resources

This guide was first published on Apr 01, 2020. It was last updated on Apr 01, 2020.

This page (Adding the Chip File) was last updated on Nov 06, 2020.