now we are going deep.
how to reach gpio pins on raspberrypi. as I sad before
one of them /sys/class/gpio file system. if you use it, it will be slow. you can find performance tests
one of them is writing a linux driver. it will be fast
and the last one is, user space driver. it will be also fast.
I will explain in this article. writing a user space driver.
I will write this code explanation with my codes.
also we need the arm bcm2835 peripherals document.
we will map raspberrypi memory. and change values in memory.
first of all we are getting peripherals start phsical address from document(page 6)
#define PERIPHERALS_BASE_PHYSICAL 0x20000000
then we are getting gpio register physical start address from document(page 90)
this document says that gpio peripherals start from 0x7e20 0000, but this address are not physical address. we can easily convert them. 0x7e20 0000 means PERIPHERALS_BASE_PHYSICAL+ 0x20 0000 pyhsical address.
#define PERIPHERALS_REGISTER_PHYSICAL 0x200000
raspberry pi has 54 GPIOS pin in SOC. now we will map memory to our program. you must be root to do this.
creating some variables
//lenght of registers end to top
#define REGISTERS_SIZE (0x7E2000B0-0x7E200000)
int mem_fd;
volatile int * gpio;
opening memory device
mem_fd = open(“/dev/mem”, O_RDWR | O_SYNC);
mapping to our space
gpio = (volatile int *) mmap(NULL, REGISTERS_SIZE,PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
(PERIPHERALS_BASE_PHYSICAL + PERIPHERALS_REGISTER_PHYSICAL));
as above picture, there is “GPIO Function Select 0″,”GPIO Function Select 1” etc… there is 6 count. every them is 32 bits. this is important!
you can use this registers to manage functions of pins. you can set to OUTPUT,INPUT,TxD or etc.
you can manage pins with 3 bits
000 = GPIO Pin is an input
001 = GPIO Pin is an output
100 = GPIO Pin takes alternate function 0
101 = GPIO Pin takes alternate function 1
110 = GPIO Pin takes alternate function 2
111 = GPIO Pin takes alternate function 3
011 = GPIO Pin takes alternate function 4
010 = GPIO Pin takes alternate function 5
alternate function means, you can set some bits for using different functions. suppose I2C,RxD,PWM etc…
you can find which pin can have an alternate function from page 102. a sample image below
lets continue,every 32 function select bits can manage only 10 pins. ( 3×10=30).
if you want to manage pin 21, you can calculate its position like this
24/10=2 this means that your pin is in “GPIO Function Select 3” bits.
#define PIN_MODE_POSITION(number) (number/10)
every 3 bits is assigned to a pin,
24%10=4 you are the 5th pin in “GPIO Function Select 3” bits. and every pin has 3 bit than 12-13-14 is your pin
#define PIN_MODE_SHIFT(number) ((number%10)*3)
if you set 000 then pin 24 is input
if you set 001 then pin 24 is output
if you set 100 then pin 24 is ALT_FUNC_0 from above picture.
for setting pin INPUT
*(gpio + PIN_MODE_POSITION(number)) &= ~(0x0000007<< PIN_MODE_SHIFT(number));
for setting pin OUTPUT
first setting all zero (000)
*(gpio + PIN_MODE_POSITION(number)) &= ~(0x0000007<< PIN_MODE_SHIFT(number));
then setting 001
*(gpio + PIN_MODE_POSITION(number)) |= 0x01<< PIN_MODE_SHIFT(number);
lets continue to set LOW and set HIGH
First set HIGH
you must use below addresses
0x 7E20 001C GPSET0 GPIO Pin Output Set 0
0x 7E20 0020 GPSET1 GPIO Pin Output Set 1
you have got 2 registers 32 bit
as I said, there is 54 pin on raspi SOC , then you need 64 bit
if pin number is 24 then where your address start
24/32=0
#define PIN_WRITE_POSITION(number) ((number/32))
what is your address
gpio + 7 +PIN_WRITE_POSITION(24) is your address
what will you write that address 1<< number%32
#define PIN_WRITE_SHIFT(number) (number%32)
to set HIGH
*(gpio + 7 + PIN_WRITE_POSITION(number) ) = 1 << PIN_WRITE_SHIFT(number);
Second set LOW
find output clear parts from document as above,
0x 7E20 0028 GPCLR0 GPIO Pin Output Clear 0
0x 7E20 002C GPCLR1 GPIO Pin Output Clear 1
you have got 64 bits again
to set low
*(gpio + 10 + PIN_WRITE_POSITION(number) ) = 1 << PIN_WRITE_SHIFT(number);
and this is the main.c file main
download and
gcc -o blink main.c
./blink