Skip to main content
\(\newcommand{\doubler}[1]{2#1} \newcommand{\binary}{\texttt} \newcommand{\hex}{\texttt} \newcommand{\octal}{\texttt} \newcommand{\prog}{\texttt} \newcommand{\lt}{ < } \newcommand{\gt}{ > } \newcommand{\amp}{ & } \)

Section19.2GPIO Connections

Table 19.2.1 shows the relationship between the GPIO pins and the header pins for the 40-pin header. Table 19.2.2 shows the relationship for Revision 2.0 of the 26-bit header, and Table 19.2.3 shows the relationship for Revision 1.0 of the 26-pin header. If you have a Raspberry Pi with a 26-pin header, you will need to consult the Raspberry Pi website to determine which Revision you have.

GPIO Header GPIO
Register Bits Pin Pin Pin Bits Register
\(3.3\) volts \(1\) \(2\) \(5.0\) volts
GPFSEL0 \(8-6\) FSEL2 \(3\) \(4\) \(5.0\) volts
GPFSEL0 \(11-9\) FSEL3 \(5\) \(6\) ground
GPFSEL0 \(14-12\) FSEL4 \(7\) \(8\) FSEL14 \(14-12\) GPFSEL1
ground \(9\) \(10\) FSEL15 \(17-15\) GPFSEL1
GPFSEL1 \(23-21\) FSEL17 \(11\) \(12\) FSEL18 \(26-24\) GPFSEL1
GPFSEL2 \(23-21\) FSEL27 \(13\) \(14\) ground
GPFSEL2 \(8-6\) FSEL22 \(15\) \(16\) FSEL23 \(11-9\) GPFSEL2
\(3.3\) volts \(17\) \(18\) FSEL24 \(14-12\) GPFSEL2
GPFSEL1 \(2-0\) FSEL10 \(19\) \(20\) ground
GPFSEL0 \(29-27\) FSEL9 \(21\) \(22\) FSEL25 \(17-15\) GPFSEL2
GPFSEL1 \(5-3\) FSEL11 \(23\) \(24\) FSEL8 \(26-24\) GPFSEL0
ground \(25\) \(26\) FSEL7 \(23-21\) GPFSEL0
do not connect \(27\) \(28\) do not connect
GPFSEL0 \(17-15\) FSEL5 \(29\) \(30\) ground
GPFSEL0 \(20-18\) FSEL6 \(31\) \(32\) FSEL12 \(8-6\) GPFSEL1
GPFSEL1 \(11-9\) FSEL13 \(33\) \(34\) ground
GPFSEL1 \(29-27\) FSEL19 \(35\) \(36\) FSEL16 \(20-18\) GPFSEL1
GPFSEL2 \(20-18\) FSEL26 \(37\) \(38\) FSEL20 \(2-0\) GPFSEL2
ground \(39\) \(40\) FSEL21 \(5-3\) GPFSEL2
Table19.2.1GPIO functions for 40-pin header. GPFSELm is the \(m^{th}\) GPIO register and FSELn is the \(n^{th}\) GPIO pin. Edge of Raspberry Pi board is to the right.
GPIO Header GPIO
Register Bits Pin Pin Pin Bits Register
\(3.3\) volts \(1\) \(2\) \(5.0\) volts
GPFSEL0 \(8-6\) FSEL2 \(3\) \(4\) \(5.0\) volts
GPFSEL0 \(11-9\) FSEL3 \(5\) \(6\) ground
GPFSEL0 \(14-12\) FSEL4 \(7\) \(8\) FSEL14 \(14-12\) GPFSEL1
ground \(9\) \(10\) FSEL15 \(17-15\) GPFSEL1
GPFSEL1 \(23-21\) FSEL17 \(11\) \(12\) FSEL18 \(26-24\) GPFSEL1
GPFSEL2 \(23-21\) FSEL27 \(13\) \(14\) ground
GPFSEL2 \(8-6\) FSEL22 \(15\) \(16\) FSEL23 \(11-9\) GPFSEL2
\(3.3\) volts \(17\) \(18\) FSEL24 \(14-12\) GPFSEL2
GPFSEL1 \(2-0\) FSEL10 \(19\) \(20\) ground
GPFSEL0 \(29-27\) FSEL9 \(21\) \(22\) FSEL25 \(17-15\) GPFSEL2
GPFSEL1 \(5-3\) FSEL11 \(23\) \(24\) FSEL8 \(26-24\) GPFSEL0
ground \(25\) \(26\) FSEL7 \(23-21\) GPFSEL0
Table19.2.2GPIO functions for 26-pin header (Revision 2.0). GPFSELm is the \(m^{th}\) GPIO register and FSELn is the \(n^{th}\) GPIO pin. Edge of Raspberry Pi board is to the right.
GPIO Header GPIO
Register Bits Pin Pin Pin Bits Register
\(3.3\) volts \(1\) \(2\) \(5.0\) volts
GPFSEL0 \(2-0\) FSEL0 \(3\) \(4\) \(5.0\) volts
GPFSEL0 \(5-3\) FSEL1 \(5\) \(6\) ground
GPFSEL0 \(14-12\) FSEL4 \(7\) \(8\) FSEL14 \(14-12\) GPFSEL1
ground \(9\) \(10\) FSEL15 \(17-15\) GPFSEL1
GPFSEL1 \(23-21\) FSEL17 \(11\) \(12\) FSEL18 \(26-24\) GPFSEL1
GPFSEL2 \(23-21\) FSEL27 \(13\) \(14\) ground
GPFSEL2 \(8-6\) FSEL22 \(15\) \(16\) FSEL23 \(11-9\) GPFSEL2
\(3.3\) volts \(17\) \(18\) FSEL24 \(14-12\) GPFSEL2
GPFSEL1 \(2-0\) FSEL10 \(19\) \(20\) ground
GPFSEL0 \(29-27\) FSEL9 \(21\) \(22\) FSEL25 \(17-15\) GPFSEL2
GPFSEL1 \(5-3\) FSEL11 \(23\) \(24\) FSEL8 \(26-24\) GPFSEL0
ground \(25\) \(26\) FSEL7 \(23-21\) GPFSEL0
Table19.2.3GPIO functions for 26-pin header (Revision 1.0). GPFSELm is the \(m^{th}\) GPIO register and FSELn is the \(n^{th}\) GPIO pin. Edge of Raspberry Pi board is to the right.

Table 19.2.4 shows which bits in the GPIO function select registers control physical pins on the GPIO header.

Bits
GPIO Register \(29-27\) \(26-24\) \(23-21\) \(20-18\) \(17-15\) \(14-12\) \(11-9\) \(8-6\) \(5-3\) \(2-0\)
GPFLSEL0 \(21\) \(24\) \(26\) \(31\) \(29\) \(7\) \(5\) \(3\)
GPFLSEL1 \(35\) \(12\) \(11\) \(36\) \(10\) \(8\) \(33\) \(32\) \(23\)
GPFLSEL2 \(13\) \(37\) \(22\) \(18\) \(16\) \(15\) \(40\) \(38\)
Table19.2.4Header pin numbers controlled by 3-bit fields in registers GPFLSEL0GPFLSEL2, 40-pin header.

Table 19.2.5 shows the locations of the three GPIO registers that are used to select the pin functions Table 19.2.4.

Name Datasheet Address GPIO Offset
GPFSEL0 \(\hex{0x7e200000}\) \(\hex{0x0000}\)
GPFSEL1 \(\hex{0x7e200004}\) \(\hex{0x0004}\)
GPFSEL2 \(\hex{0x7e200008}\) \(\hex{0x0008}\)
Table19.2.5Offsets of the GPIO registers used to select the function of GPIO pins.

Thus if we wish to access pin number 12 on the GPIO header, we need to access bits \(26\)–\(24\) at \(\hex{0x004}\) relative to virtual address in our program that we get from the call to the mmap function.

Using one of the pins in the header connection is a two-step process:

  1. Select the function of the pin. Each connector pin can be selected to be either an input or an output. Most can also be selected for alternate functions, but we will not do so in this book.

  2. Turn the pin on (Set) or off (Clear). There are two separate sets of GPIO registers for either setting a pin function or clearing it.

The first step can be accomplished as shown in Listing 19.2.6.

@ gpioPinFSelect.s
@ Selects a function for a GPIO pin. Assumes that GPIO registers
@ have been mapped to programming memory.
@ Calling sequence:
@       r0 <- address of GPIO in mapped memory
@       r1 <- pin number
@       r2 <- pin function
@       bl gpioPinFSelect
@ Bob Plantz - 30 August 2016

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    PIN_FIELD,0b111 @ 3 bits

@ The program
        .text
        .align  2
        .global gpioPinFSelect
        .type   gpioPinFSelect, %function
gpioPinFSelect:
        stmfd   sp!, {r4, r5, r6, fp, lr}   @ save caller's info
        add     fp, sp, 12      @ our frame pointer
        sub     sp, sp, 4       @ keep sp on 8-byte boundary
        
        mov     r4, r0          @ save pointer to GPIO
        mov     r5, r1          @ save pin number
        mov     r6, r2          @ save function code
        
@ Compute address of GPFSEL register and pin field        
        mov     r3, 10          @ divisor
        udiv    r0, r5, r3      @ GPFSEL number
        
        mul     r1, r0, r3      @ compute remainder
        sub     r1, r5, r1      @     for GPFSEL pin
        
@ Set up the GPIO pin funtion register in programming memory
        lsl     r0, r0, 2       @ 4 bytes in a register
        add     r0, r4, r0      @ GPFSELn address
        ldr     r2, [r0]        @ get entire register
        
        mov     r3, r1          @ need to multiply pin
        add     r1, r1, r3 1    @    position by 3
        mov     r3, PIN_FIELD   @ gpio pin field
        lsl     r3, r3, r1      @ shift to pin position
        bic     r2, r2, r3      @ clear pin field

        lsl     r6, r6, r1      @ shift function code to pin position
        orr     r2, r2, r6      @ enter function code
        str     r2, [r0]        @ update register
        
        mov     r0, 0           @ return 0;
        add     sp, sp, 4       @ fix sp
        ldmfd   sp!, {r4, r5, r6, fp, lr}   @ restore caller's info
        bx      lr              @ return
Listing19.2.6Selecting the function of a GPIO pin. (prog asm)

Selecting the function of a pin involves working with three bits within a 32-bit register. We need to be careful not to disturb the other 29 bits in the register. The first step is to clear the bits within the desired 3-bit field. In the following code segment the value in register we are working with has been loaded into r2 and the pin number is in r1.

mov     r3, r1          @ need to multiply pin
add     r1, r1, r3 1    @    position by 3
mov     r3, PIN_FIELD   @ gpio pin field
lsl     r3, r3, r1      @ shift to pin position
bic     r2, r2, r3      @ clear pin field

Multiplying the pin number by \(2\) (left shift one bit) and adding it to itself is a fast, simple way to multiply by \(3\text{.}\)

Clearing the three bits requires a new instruction, bic.

BIC

Performs a bitwise AND between the NOT of a bit pattern and a value in a register, thus clearing the bits in the register as specified by the bit pattern.

BIC{S}{<c>}  {<Rd>,} <Rn>, #<const>           % immediate
BIC{S}{<c>}  {<Rd>,} <Rn>, <Rm>{, <shift>}    % register
BIC{S}{<c>}  {<Rd>,} <Rn>, <Rm>, <type> <Rs>  % register-shifted register

  • If ‘S’ is present the condition flags are updated according to the result. If absent, the condition flags are not changed.

  • <c> is the condition code, Table 9.2.1.

  • <Rd> specifies the destination register, and <Rm> and <Rn> are the source registers. <Rs> contains the shift amount in the “register-shifted register” form.

  • \(-257 \le const \le +256\text{,}\) or \(const = +256, +260, +264, \ldots, +65280\text{,}\) or \(const = -261, -265, \ldots, -65281\text{.}\) This odd sequence of values will be explained in Section 11.3.3

  • <shift> and <type> are explained in Section 9.2.3

In the “immediate” form, a bitwise AND is performed between the NOT of <const> and the value in <Rn>. In the “register” and “register-shifted register” forms, a bitwise AND is performed between the value in <Rn> and the NOT of the value in <Rm>. If a shift is specified, the value in <Rm> is shifted by the specified amount before the AND is performed. If <Rd> is present the result is stored there and <Rn> is unchanged. If not, the result is stored in <Rn>. The values in <Rm> and <Rs> are unchanged.

After the bit field has been cleared, we can now use orr to store the new function code in the 3-bit field without disturbing the other 29 bits:

lsl     r6, r6, r1      @ shift function code to pin position
orr     r2, r2, r6      @ enter function code

For the second step, Table 19.2.7 shows the locations of the registers that are used to set or clear a pin once its function has been selected and the pin number that corresponds to each bit in the set and clear registers.

Name Datasheet Address GPIO Offset Bits Corresponding Pins
GPSET0 \(\hex{0x7e20001c}\) \(\hex{0x001c}\) \(\binary{31}\) – \(\binary{0}\) \(31\) – \(0\)
GPSET1 \(\hex{0x7e200020}\) \(\hex{0x0020}\) \(\binary{21}\) – \(\binary{0}\) \(53\) – \(32\)
GPCLR0 \(\hex{0x7e200028}\) \(\hex{0x0028}\) \(\binary{31}\) – \(\binary{0}\) \(31\) – \(0\)
GPCLR1 \(\hex{0x7e20002c}\) \(\hex{0x002c}\) \(\binary{21}\) – \(\binary{0}\) \(53\) – \(32\)
Table19.2.7Offsets of the GPIO registers for setting and clearing a pin.

Setting a pin can be accomplished as shown in Listing 19.2.8.

@ gpioPinSet.s
@ Sets a GPIO pin. Assumes that GPIO registers
@ have been mapped to programming memory.
@ Calling sequence:
@       r0 <- address of GPIO in mapped memory
@       r1 <- pin number
@       bl gpioPinSet
@ Bob Plantz - 27 August 2016

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    PIN,1           @ 1 bit for pin
        .equ    PINS_IN_REG,32
        .equ    GPSET0,0x1c     @ set register offset

@ The program
        .text
        .align  2
        .global gpioPinSet
        .type   gpioPinSet, %function
gpioPinSet:
        stmfd   sp!, {r4, r5, fp, lr}   @ save caller's info
        add     fp, sp, 12      @ our frame pointer
        
        add     r4, r0, GPSET0  @ pointer to GPSET regs.
        mov     r5, r1          @ save pin number
        
@ Compute address of GPSET register and pin field        
        mov     r3, PINS_IN_REG @ divisor
        udiv    r0, r5, r3      @ GPSET number
        mul     r1, r0, r3      @ compute remainder
        sub     r1, r5, r1      @     for relative pin position
        lsl     r0, r0, 2       @ 4 bytes in a register
        add     r0, r0, r4      @ address of GPSETn
        
@ Set up the GPIO pin funtion register in programming memory
        ldr     r2, [r0]        @ get entire register
        mov     r3, PIN         @ one pin
        lsl     r3, r3, r1      @ shift to pin position
        orr     r2, r2, r3      @ set bit
        str     r2, [r0]        @ update register
        
        mov     r0, 0           @ return 0;
        ldmfd   sp!, {r4, r5, fp, lr}   @ restore caller's info
        bx      lr              @ return
Listing19.2.8Setting a GPIO pin. (prog asm)

It is important to understand that storing a \(\binary{0}\) in the bit position corresponding to a pin does not clear the pin. To clear a pin, you need to store a \(\binary{1}\) in the corresponding bit in the appropriate GPCLRn register. This eliminates the possiblity of accidentally clearing other pins while setting one pin. The clear operation operates in the same manner.

Subsection19.2.1Exercises

1

Write an assembly language program that blinks an LED five time. The LED will be on for 1 second then off for 1 second. Use the sleep function for timing, which is described in man 3 sleep.

Hint Solution