Memory Mapped GPIO

You can deal with GPIO pins by mapping physical memory for GPIOs.

Refer to GPIO Register Map document to code.

Download the example source code below and compile/run that.

n2_mmap_gpio.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
 
#define	GPIO_REG_MAP            0xFF634000
#define GPIOX_FSEL_REG_OFFSET   0x116
#define GPIOX_OUTP_REG_OFFSET   0x117
#define GPIOX_INP_REG_OFFSET    0x118
#define BLOCK_SIZE              (4*1024)
 
static volatile uint32_t *gpio;
 
int main(int argc, char **argv) {
    int fd;
 
    if ((fd = open("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) {
        printf("Unable to open /dev/gpiomem\n");
        return -1;
    }
 
    gpio = mmap(0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_REG_MAP);
    if (gpio < 0) {
        printf("Mmap failed.\n");
        return -1;
    }
 
    // Print GPIOX FSEL register
    printf("GPIOX_FSEL register : 0x%08x\n",
           *(unsigned int *)(gpio + (GPIOX_FSEL_REG_OFFSET)));
 
    // Set direction of GPIOX.4 register to out
    *(gpio + (GPIOX_FSEL_REG_OFFSET)) &= ~(1 << 4);
    printf("GPIOX_FSEL register : 0x%08x\n",
           *(unsigned int *)(gpio + (GPIOX_FSEL_REG_OFFSET)));
    // Set GPIOX.4 to high
    *(gpio + (GPIOX_OUTP_REG_OFFSET)) |= (1 << 4);
    printf("GPIOX_INP register : 0x%08x\n",
           *(unsigned int *)(gpio + (GPIOX_INP_REG_OFFSET)));
    // Set GPIOX.4 to low
    *(gpio + (GPIOX_OUTP_REG_OFFSET)) &= ~(1 << 4);
    printf("GPIOX_INP register : 0x%08x\n",
           *(unsigned int *)(gpio + (GPIOX_INP_REG_OFFSET)));
 
    return 0;
}

Note that all GPIO pins we can deal with are set to input mode before executing the example.

The example will set the GPIOX.4 to output mode using GPIOX_FSEL register.

root@odroid:~# gcc -o mmap_gpio mmap_gpio.c
root@odroid:~# ./mmap_gpio
GPIOX_FSEL register : 0xffffffff
GPIOX_FSEL register : 0xffffffef
GPIOX_INP register : 0x00070091
GPIOX_INP register : 0x00070081