Where Are The Registers?
The only question we have to answer now is where are the registers?
This turns out to be a difficult question to answer because the processor implement memory mapping which essentially means that any physical address can appear almost anywhere in the memory map of a running program.
All of the peripheral registers including the GPIO registers we have been describing are in a block of memory 0x2000 0000 to 0x20FF FFFF acording to the documentation but this has been changed to 0x3F00 0000 for the Pi 2 and 3 which is a source of much confusion.
So in the PI 1 the peripheral registers start at 0x2000 0000. For a Pi 2 and later the registers start is indicated by the contents of a file setup by the Linux Device Tree. So to find out where the registers are you have to read:
/proc/device-tree/soc/ranges
which contains three four byte values the address of the start of the memory, the second byte and its size,. the third byte. In practice reading the file returns 0x3F00 0000 for a Pi 2 and 3 but this could change in the future.
The best way to discover where the perhiperhal registers are located is to try to read the file and use the default 0x2000 0000 if it isn't present. For example:
bcm2835_peripherals_base= 0x20000000; int fp; if ((fp = fopen("/proc/device-tree/soc/ranges" , "rb"))) { unsigned char buf[8]; if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) bcm2835_peripherals_base = (uint32_t *)(buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7] << 0); fclose(fp); }
In practice it is easier to rely on the bcm2835 library and the
bcm2835_peripherals_base
variable which is set to the start of the peripherals area when you initialize the library - i.e. it is set correctly for all Pis.
The register addresses can be specified as offsets from bcm2835_peripherals_base but it is easier to take the offsets from where the first register belonging to the device is.
So for the GPIO the first GPIO register is at 0x20 0000, which is BCM2835_GPIO_BASE in the bcm2835 library
That is the starting address of the GPIO registers is given by:
gpio address =bcm2835_peripherals_base + BCM2835_GPIO_BASE
The offsets for each of the registers from this address is
0x0000 | GPFSEL0 GPIO Function Select 0 |
0x0004 | GPFSEL1 GPIO Function Select 1 |
0x0008 | GPFSEL2 GPIO Function Select 2 |
0x000C | GPFSEL3 GPIO Function Select 3 |
0x0010 | GPFSEL4 GPIO Function Select 4 |
0x0014 | GPFSEL5 GPIO Function Select 5 |
0x001C | GPSET0 GPIO Pin Output Set 0 |
0x0020 | GPSET1 GPIO Pin Output Set 1 |
0x0028 | GPCLR0 GPIO Pin Output Clear 0 |
0x002C | GPCLR1 GPIO Pin Output Clear 1 32 W |
0x0034 | GPLEV0 GPIO Pin Level 0 |
0x0038 | GPLEV1 GPIO Pin Level 1 |
0x0040 | GPEDS0 GPIO Pin Event Detect Status 0 |
0x0044 | GPEDS1 GPIO Pin Event Detect Status 1 |
0x004C | GPREN0 GPIO Pin Rising Edge Detect Enable 0 |
0x0050 | GPREN1 GPIO Pin Rising Edge Detect Enable 1 |
0x0058 | GPFEN0 GPIO Pin Falling Edge Detect Enable 0 |
0x005C | GPFEN1 GPIO Pin Falling Edge Detect Enable 1 |
0x0064 | GPHEN0 GPIO Pin High Detect Enable 0 |
0x0068 | GPHEN1 GPIO Pin High Detect Enable 1 |
0x0070 | GPLEN0 GPIO Pin Low Detect Enable 0 |
0x0074 | GPLEN1 GPIO Pin Low Detect Enable 1 |
0x007C | GPAREN0 GPIO Pin Async. Rising Edge Detect |
0x0080 | GPAREN1 GPIO Pin Async. Rising Edge Detect 1 |
0x0088 | GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 |
0x008C | GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 |
0x0094 | GPPUD GPIO Pin Pull-up/down Enable |
0x0098 | GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock |
0x009C | GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock |
The only registers missing from this list are the PAD control registers and these are located in a different area of memory at:
BCM2835_GPIO_PADS=bcm2835_peripherals_base+BCM2835_GPIO_PADS =0x20100000 or =0x3F100000 for Pi2
And the offsets are:
0x002c PADS0 (GPIO 0-27) 0x0030 PADS1 (GPIO 28-45) 0x0034 PADS2 (GPIO 46-53)
You can work out the address of any register listed in the documentation by finding the base address for the registers and adding its offset.
It is worth knowing that you can use
cat /proc/iomem
to discover where devices are in memory. On a Pi 2 you will see:
00000000-3affffff : System RAM 00008000-007e641f : Kernel code 0085e000-0098c1ab : Kernel data 3f006000-3f006fff : dwc_otg 3f007000-3f007eff : /soc/dma@7e007000 3f00b840-3f00b84e : /soc/vchiq 3f00b880-3f00b8bf : /soc/mailbox@7e00b800 3f200000-3f2000b3 : /soc/gpio@7e200000 3f201000-3f201fff : /soc/uart@7e201000 3f201000-3f201fff : /soc/uart@7e201000 3f202000-3f2020ff : /soc/sdhost@7e202000 3f980000-3f98ffff : dwc_otg