2

I am trying to write a simple led blink program using mmap io. I know my circuit is working(i have already tried it with sysfs approach). Now I am trying to do it with mmap io and I am totally stacked and I can not find where am I doing wrong. If someone can help me, I would be appreciated.

Btw I am using Rpi 2 model B v1.1

Here is my code,

#include <stdio.h>      // perror
#include <sys/mman.h>   // mmap
#include <sys/types.h>  // fd open
#include <sys/stat.h>   // fd open
#include <fcntl.h>      // fd open
#include <unistd.h>     // fd close

#define BCM2708_PERI_BASE       0x20000000
#define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)   // GPIO controller

#define BLOCK_SIZE              (4 * 1024)

// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x)
#define INP_GPIO(g)         *(gpio.addr + ((g) / 10)) &= ~(7 << (((g) % 10) * 3))
#define OUT_GPIO(g)         *(gpio.addr + ((g) / 10)) |=  (1 << (((g) % 10) * 3))
#define SET_GPIO_ALT(g, a)  *(gpio.addr + (((g) / 10))) |= (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3))

#define GPIO_SET            *(gpio.addr + 7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR            *(gpio.addr + 10) // clears bits which are 1 ignores bits which are 0

#define GPIO_READ(g)        *(gpio.addr + 13) &= (1 << (g))

struct bcm2835_peripheral {
    unsigned long addr_p;
    int mem_fd;
    void *map;
    volatile unsigned int *addr;
};

struct bcm2835_peripheral gpio = { GPIO_BASE };

// Exposes the physical address defined in the passed structure using mmap on /dev/mem
int map_peripheral(struct bcm2835_peripheral *p)
{
    // Open /dev/mem
    if ((p->mem_fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
        fprintf(stderr, "Failed to open /dev/mem, try checking permissions.");
        return -1;
    }

    p->map = mmap(
                NULL,
                BLOCK_SIZE,
                PROT_READ | PROT_WRITE,
                MAP_SHARED,
                p->mem_fd,      // File descriptor to physical memory virtual file '/dev/mem'
                p->addr_p       // Address in physical map that we want this memory block to expose
                );

    if (p->map == MAP_FAILED) {
        perror("mmap");
        return -1;
    }

    p->addr = (volatile unsigned int *)p->map;

    return 0;
}

void unmap_peripheral(struct bcm2835_peripheral *p)
{

    munmap(p->map, BLOCK_SIZE);
    close(p->mem_fd);
}

int main()
{
    if(map_peripheral(&gpio) == -1) {
        fprintf(stderr, "Failed to map the physical GPIO registers into the virtual memory space.\n");
        return -1;
    }

    // Define pin 7 as output
    INP_GPIO(4);
    OUT_GPIO(4);

    while(1) {
        // Toggle pin 7 (blink a led!)
        GPIO_SET = 1 << 4;
        sleep(1);

        GPIO_CLR = 1 << 4;
        sleep(1);
    }

    return 0;
}

1 Answer 1

1

I answer my own question; well actually I was doing a silly mistake on the base address of peripherals. I was using rpi1's peri base addr.. peri base addr for rpi2 is 0x3F000000 and for GPIO 0x3F200000

5
  • Why would you bother? There are libraries which already do this e.g. winingpi. If you want to write your own code you should not hard code this kind of stuff, and properly detect the environment.
    – Milliways
    Dec 4, 2015 at 9:08
  • Well I am already aware that wiringPi but I just like to taste that :) Dec 4, 2015 at 9:26
  • @sinadogru Tiny gpio access shows how to use the /dev/gpiomem interface which will let you manipulate the GPIO without needing root access. It also auto detects the Pi version. It's only a couple of hundred lines of code.
    – joan
    Dec 4, 2015 at 11:37
  • @joan Ah yes I have already seen that aswell but did not check it well, but seems like it is well time to check it, Thank you. (BTW how is it possible to manipulate mem without root access?) Dec 4, 2015 at 12:39
  • 1
    @sinadogru You need root privileges to access /dev/mem. However this led to the silly situation where some Python modules were being run with root priviliges simply because they wanted to twiddle a LED. So a special /dev/gpiomem has been created on the Pi. This device may be opened by a user in the group gpio, but the device only gives access to the GPIO memory area.
    – joan
    Dec 4, 2015 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.