There are two connectors, P1 and P5, on the Model A and Model B version 2 devices, where various signals are available. All the signals are digital and 3.3V logic level, even though there are 5V power lines avaiable as well. This refers to the Version 2 devices that I have, version 1 devices have slightly different pin-allocations. (pins 3, 5, and 13 are GPIOs 0, 1, and 21 instead of 2, 3, and 27, and there is no P5 connector at all)
Ever since the Model B+ came, all versions since then (A+, Zero, Zero-W, Pi2, Pi3, Pi4 ) have a 40-pin header where the first 26 pins are the same as the P1 connector on the models A and B. There is however no P5 connector or equivalent anymore.
1 3.3V | 2 5.0V |
3 GPIO2 SDA1 | 4 5.0V |
5 GPIO3 SCL1 | 6 Gnd |
7 GPIO4 1Wire* | 8 GPIO14 UART0_TXD |
9 Gnd | 10 GPIO15 UART0_RXD |
11 GPIO17 | 12 GPIO18 PWM* |
13 GPIO27 PCM_DOUT | 14 Gnd |
15 GPIO22 | 16 GPIO23 |
17 3.3V | 18 GPIO24 |
19 GPIO10 SPI0_MOSI | 20 Gnd |
21 GPIO9 SPI0_MISO | 22 GPIO25 |
23 GPIO11 SPI0_SCLK | 24 GPIO8 SPI0_CE0 |
25 Gnd | 26 GPIO7 SPI0_CE1 |
The P1.3/GPIO2/SDA1 and P1.5/GPIO3/SCL1 have an internal pull-up resistor, so no additional pull-up is needed when this is used as an i2c bus. If configured as plain inputs, they will read High when open and can be shorted to GND for Low -- no additional components needed.
2 3.3V | 1 5.0V |
4 GPIO29 SCL0 | 3 GPIO28 SDA 0 |
6 GPIO31 | 5 GPIO30 |
8 Gnd | 7 Gnd |
The i2c functions, SDA0 on GPIO28 and SCL0 on GPIO 29, are enabled by setting the alternate 0 functions on these, and re-setting the functions on GPIO0 (SDA0) and GPIO1 (SCL0) to plain IO.
Orientation seeing the card with P5 to the left of P1, and P1 to the top right; SD-card and power towards the top, network and USB to the bottom, HDMI to the left. P5 has opposite numbering compared to P1.
1 3.3V | 2 5.0V |
3 GPIO2 SDA1 | 4 5.0V |
5 GPIO3 SCL1 | 6 Gnd |
7 GPIO4 1Wire* | 8 GPIO14 UARTx_TXD |
9 Gnd | 10 GPIO15 UARTx_RXD |
11 GPIO17 SPI1_CE1 | 12 GPIO18 PWM* i2s-BCK SPI1_CE0 |
13 GPIO27 PCM_DOUT | 14 Gnd |
15 GPIO22 | 16 GPIO23 |
17 3.3V | 18 GPIO24 |
19 GPIO10 SPI0_MOSI | 20 Gnd |
21 GPIO9 SPI0_MISO | 22 GPIO25 |
23 GPIO11 SPI0_SCLK | 24 GPIO8 SPI0_CE0 |
25 Gnd | 26 GPIO7 SPI0_CE1 |
27 (GPIO0) IDSD I2C0_SDA | 28 (GPIO1) IDSC I2C0_SCL |
29 GPIO5 | 30 GND |
31 GPIO6 | 32 GPIO12 |
33 GPIO13 | 34 GND |
35 GPIO19 i2s-LRCK SPI1_MISO | 36 GPIO16 SPI1_CE2 |
37 GPIO26 | 38 GPIO20 i2s-DIN SPI1_MOSI |
39 Gnd | 40 GPIO21 i2s-DOUT SPI1_SCLK |
The first 26 pins are the same as the ones on the P1 on the older Models A and B. Also, like these, the J8.3/GPIO2/SDA1 and J8.5/GPIO3/SCL1 lines have an internal pull-up resistor, so no additional pull-up is needed when this is used as an i2c bus. If configured as plain inputs, they will read High when open and can be shorted to GND for Low -- no additional components needed.
We can also note that, apart from special use assignments, (i2c, serial, SPI), all GPIOs numbered from 0 thru 27 are available here.
IDSD and IDSC are supposed to be used for an identifier eeprom on an expansion card, and nothing else. As this is also used with the display and camera, re-allocating these when display and/or camera is used, will make those not work right if at all.
However, these are actually the /dev/i2c-0 lines, and GPIO0 and GPIO1, so they might be used in less than compatible ways for other things. Kinda like the i2c bus on the Picotuxes that uses one of the IOs marked as reserved. And like this one, some sort of emission on startup can be expected.
All signals are at 3.3 V -- and many available devices work just fine on 3.3V so connections can be easy. And when needing to run at 5V we can use level translators or similar tricks as has been done with the Picotux or WD Books. Interfacing to a PIC16F690 at 5 V for example will be very similar to what has been done with these.
Max current available from the 3.3V regulator on all the various models (pins P1.1, J8.1, P1.17, J8.17, P5.2, as applicable, combined) is 50 mA. Max current available on the 5.0V lines (P1.2 J8.2, P1.4 J8.4, P5.1 as applicable, combined) is whatever is available from the USB power input, minus what the Raspberry Pi needs, which is 700 mA for the model B or 500 mA for the model A.
The serial port pins are connected to UART1 on the Pi3 and UART0 on all the older ones. The system maps this to /dev/ttyAMA0 in either case. On Pi3 the UART0 is used for the Bluetooth subsystem.
There are several ways to access the GPIO lines, for example:
gpiod | /dev/gpiochip* | The gpio-device handling. Uses ioctl() calls, and much of the hard work is collected in the libgpio. Use libgpiod-dev, #include <gpiod.h>, and -lgpio. Powerful and reasonably easy to work with. There are also some command-line tools available. |
userland | /sys/class/gpio/* | Obsolete as of May 2024. Fairly slow, easy to test and develop, and allows non-privileged users. Good when the speed required is low. |
user-space | /dev/mem | Faster, reasonably easy to develop and use, requires root. Does not directly support interrupts. Very non-portable, and not really recommended, when we have gpiod. |
kernel module | /dev/custom | Fast, lots of setup-work needed (kernel compilation) and certain errors bring down the entire system. Once in place, it does allow non-privileged users. |
I have used all four at the same time in some system, it will work as long as any of the GPIO lines are only handled in one way.
There is a pseudo-file, /sys/kernel/debug/gpio, which shows which of the gpios are being allocated via sysfs or a kernel-module, and which states these are in. /dev/mem gpio access does not show up here.
For kernel modules, the description of the gpio line shown comes from the second argument to the call to the gpio_request() function.
To install this:
apt install gpiod libgpiod-dev libgpiod-doc
Look for info in /usr/include/gpiod.h
#include <gpiod.h> in source
add -lgpiod to the linker invocations
As these files start out as read-only for other than root for the most part, the set-up may have to be done as root, but once the files exist and can be chmod'd 666 then the non-root user may proceed.
To enable a gpio line, echo its number into /sys/class/gpio/export, for example:
echo "7" > /sys/class/gpio/export
We now have a /sys/class/gpio/gpio7 directory, with various files in it, and can read and write these files, for example:
echo "out" > /sys/class/gpio/gpio7/direction
The electrical level (Low or High) depends on the values of active_low and value files. Writing to value for an output gpio line sets its level to whatever was written, and reading value for any gpio line shows the level on it at present.
The control files are
active_low | 0 | 1 (0 means value=0 is Low and value=1 is High, 1 is the opposite) |
direction | in | out |
edge | none | rising | falling | both |
value | 0 is low and 1 is high (or vice versa if active_low is 1) |
uevent | |
power/ |
Reading and writing these from a program is done via ordinary stdio functions such as fopen(), then fgets() or fputs(), then fclose().
The interrupts are enabled by setting the gpioN/edge file to one of rising, falling or both, for it to react to rising or falling edges, or both edges. The gpioN/direction file should read in. Then in a program, the gpioN/value file is opened with O_RDONLY | O_NONBLOCK and the poll(2) function is used to look for POLLPRI. As poll(2) can do several files, catching keypresses by handling POLLIN for stdin can be useful.
I noticed on kernel 4.1.7 that the flag never seemed to be reset, so I had to close and open the gpio value file once the poll() had returned indicating there is a value for me. The value file would otherwise give me the same number no matter what the voltage on the pin is.
This is nice, but it is fairly slow -- I found this useful for push- buttons, and for the rain-gages that close or open a switch for every 1mm or 1/10 mm, but for the 1/100 L pulses from a flowmeter assembly it was not fast enough.
The userland GPIO also shows that we can't perform bit-banging the interface to the HX711 Load Cell Amplifier reliably -- as this has to have 25-27 clock pulses pretty accurately timed, for reading the data and preparing the next reading all within 100ms. Random delays caused by other activity in the operating system precludes this from working reliably right, and occasional wrong values are returned.
Like user-space gpio, this also allows non-privileged users to access the devices. One will have to be root when loading or unloading the modules however, for testing. And certain bugs may result in a non-functional system that has to be re-started...
There is also the matter of getting the development system right. The kernels available on downloads for the Raspberry Pi changes all the time, and when a new kernel is in place, the module will have to be recompiled with it in order to work.
Though a bit more complicated, this isn't impossible, see the page on kernel programming for all the gory details.
With the right settings, however, the makefile (named Kbuild) typically looks like:
MODULE=flowco obj-m:= ${MODULE}.o all: make -C ${KERNEL_SRC} M=$(PWD) modules clean: make -C ${KERNEL_SRC} M=$(PWD) clean
and the only other files required are what will here be referred to as flowco.c which in turn needs flowco_u.h. Running make -f Kbuild on the above will compile the code in flowco.c and link it with other kernel elements and produce the flowco.ko file, which can then be loaded with insmod, maybe automated by adding this load command into /etc/rc.local, or putting the file in with others under /lib/modules.
I prefer using /etc/rc.local, as it is easier to "lose" a file in /lib/modules/somewhere... and when I revisit some project after 6 months, there is the matter of finding it again.
Code in this kernel module has access to the hardware, even directly, or via functions. After having got dibs on the line with gpio_request() we can use gpio_get_value(number), gpio_set_value(number, level), gpio_direction_input(number), gpio_direction_output(number, level) to read and control, as well as an interrupt line with gpio_to_irq() and then request_irq() including the handle function.
There's also the trick of registering the device as a miscellaneous one, if there is no need for a specific major number or many minor numbers or suchlike, using misc_register() -- the device file in /dev/ will then show up right away on startup.
See also more notes on these interrupts below.
Then there is code for handling bit-banging into /dev/mem which isn't all that elegant, as it requires root permissions not just for development (as anything we want to put into /etc/rc.local or the kernel does) but also for use.
I found some notes on various speeds possible on this blog here.14 MHz or more using C and the /dev/kmem interface? interesting...!
So getting a couple MCP3201s to sample at 100 ksps might be possible then.
From the Broadcom datasheet there is information on these pins and how to access registers for them. This can be done in user-space by mapping memory (have to be root) and then writing to and reading various registers.
I have been able to flip some of the bits up and down on request, there are three registers, one for set pin to H, one for clear pin to L, and the third for reading the state of a pin, which is correct whether this is input or output.
The 3.3 V outputs will drive an LS-TTL input without any problem.
The GPIO base address to map with is offset 0x200000 from the peripheral base address, which depends on the model of the Raspberry Pi, as follows:
Models | Baseaddress + offset |
1B, 1A, 1A+, 1B+, Z, ZW | 0x20000000 +0x00200000 |
2B, 3B, 3A+, 3B+ | 0x3F000000 +0x00200000 |
4B | 0xFE000000 +0x00200000 |
Having found out how to access the various registers, I made a utility, gpiostates, which lists the available GPIO lines and what they are currently set to be used for; whether input, output, or some special function. On a Rpi Model B just having been powered on, where the i2c and spi modules are no longer blacklisted, this shows:
GPIO02 pin P1-03 F0=I2C1_SDA GPIO03 pin P1-05 F0=I2C1_SCL GPIO04 pin P1-07 input GPIO07 pin P1-26 F0=SPI0_CE1_N GPIO08 pin P1-24 F0=SPI0_CE0_N GPIO09 pin P1-21 F0=SPI0_MISO GPIO10 pin P1-19 F0=SPI0_MOSI GPIO11 pin P1-23 F0=SPI0_SCLK GPIO14 pin P1-08 F0=UART0_TXD GPIO15 pin P1-10 F0=UART0_RXD GPIO17 pin P1-11 input GPIO18 pin P1-12 input GPIO22 pin P1-15 input GPIO23 pin P1-16 input GPIO24 pin P1-18 input GPIO25 pin P1-22 input GPIO27 pin P1-13 output GPIO28 pin P5-03 input GPIO29 pin P5-04 input GPIO30 pin P5-05 input GPIO31 pin P5-06 input
I found out (from someone calling themselves More Than User -- Many thanks!) how to make the system get an interrupt from a gpio line. Turns out, there is support for this sort of thing in the kernel, at least the 3.6.11 one. And I have made it work with an "accumulator"-type program, that can receive interrupts for the pulses coming from an anemometer, rain gage, or other kind of flow meter, and count and calculate correctly scaled volume. I have had this sort of thing going on the PIC16F628 and PIC16F690 for a while, but since the Raspberry Pi can do this directly, I won't need to add another microcontroller just for this.
To test this, I used an extension board where the switch closures from the anemometer or rain gage (which all use reed switches) is debounced using a capacitor, two resistors and a 4584-type CMOS Schmitt-trigger. This is then connected to the GPIO22, pin 15.
The source is in the file accumulator.c. It uses the gpio_ series of kernel functions to request the gpio line and assign an interrupt service function to it.
This would be how to handle other gpio actions. For example, adding various values depending on the states of some other GPIO inputs, or toggling an output when a new unity value is reached, or when some threshold value is encountered.The kernel gpio structures are discussed in details in /kernel/linux/Documentation/gpio.txt which is a file that comes along with the kernel source.
The author of More Than User has also shown how to make the kernel interrupt send a selected software signal to a user-space process.