Written by Anna Mistele
The Raspberry Pi has 54 GPIO pins (pins 0 to 53) that can be used to interact with external sensors and devices. GPIO pins are peripherals, and they are controlled via special memory locations called peripheral registers. Keep in mind that peripheral registers are not the same as the other registers we learned about (r0–r15).
To control the GPIO pins, we use the four gpio peripheral registers: FSEL, SET, CLR, and LEV. The table below shows
the memory addresses of these registers. (Some of the addresses are labeled "Reserved", which means we don't want to mess with them.)

I adapted this table from the Broadcom BCM2835 ARM Peripherals datasheet, p.90!
Notice that there are six FSEL registers but only 2 each of SET, CLR, and LEV. Why is this? Each FSEL register is listed as controlling 10 GPIO pins, such as FSEL0 for pins 0-9. The SET0 register covers 32 pins, from 0 to 31. The SET, CLR, and LEV registers deal with pins being on or off, a state which can be represented with a single bit per pin. In contrast, a FSEL register is used to set the function
of a pin, of which there are eight possible settings (input, output, ALT0-ALT5). To distinguish eight different possibilites requires three bits, so we can fit at most 10 pins (= 30 bits) into a 32-bit FSEL register (with 2 bits left over). Thus to control all 54 GPIO pins requires six FSEL registers and 2 each of SET/CLR/LEV.
Configure a pin:FSEL
The FSEL registers are used to set the function of a GPIO pin. The eight different pin functions are Input, Output, and six Alternate functions 0-5. Each function is represented as three bits. For example, the Input function is 000 and Output function is 001.
The Output function configures a pin to be used as an output. We can change the value of an output pin using SET and CLR. This lets us turn on LEDs, for example.
The Input function configures a pin to be used as an input. We can read the value of the pin using LEV. This lets us determine whether a button has been pressed, for example.
To set GPIO pin 3 as an output, for instance, we would set bits 6-8 (highlighted below) to 001 in the FSEL0 register.

Turn on a pin: SET
The SET registers are used to turn on a GPIO output pin. (We cannot turn off a GPIO output pin with SET, instead see CLR below).
For example, if we wanted to turn on GPIO pin 26, we could write the value 0b00000100000000000000000000000000 into the SET0 register. That will turn on pin 26.

SET registers are write-only. You write to the register to turn a pin on, but it is not possible to read from the reigster to get the current state. (Technically, it will let you read the SET register, but you can't trust that the values will be accurate. Instead see LEV below.)
Turn off a pin: CLR
The CLR registers are used to turn off a GPIO output pin. Writing a 1 to a specific bit in the CLR register will turn off
the pin. It is not intuitive—you would assume that you write a 1 to turn something on, and a 0 to turn something off! to turn off (CLR) is separate from the mechansim to turn on (SET). In both cases, we write a 1, and whether this causes the pin to turn on or off is determined by whether we are writing the 1 into the SET register or the CLR register.
Writing 0b00000100000000000000000000000000 into the CLR0 register would turn off GPIO pin 26. This is the same value used to turn on pin 26, but we write the value to a different address (0x20200028, CLR0, instead of 0x2020001C, SET0).

Like SET, CLR registers are write-only. Reading from the CLR register cannot be used to reliably read the current state.
Read a pin: LEV
The LEV registers are used to read the on-off value of a GPIO pin. The LEV value can be read for any pins, whether it is an input or an output pin. It makes most sense to read the
LEV of an input pin, because we haven't set that value ourselves (it's from an outside source). LEV registers are laid out like SET and CLR registers (32 bits,
representing 32 pins). If the bit value is 1, the corresponding gpio is on, and if 0, it is off.
LEV registers are read-only. We can't write to a LEV register to turn on or off a pin (use SET
or CLR instead).