3

How can access the GPIO pins in C without writing to the sys/class/gpio directory, in a way that would allow me to create my own interface?

I would like to end up able to do something like this:

// Declaring `porta` at some memory address.
unsigned char porta @port 0x7;
// Setting `porta` as input.
porta = 1; 

I've seen similar syntax in microcontroller programming.

So is it possible to declare my pins like that, then set them as input or output?

Reference: http://www.atmel.com/images/avr_3_04.pdf

6
  • You have to mmap kernel space, as the GPIO libs do, if you want some kind of idiosyncratic interface. Analogous questions would be, "How can I manipulate the GPIO pins using functions with Latin names in C?" <- write your own interface. "How can I open and read files using arithmetic operators instead of file descriptors?" <- may have to move to C++ or customize a compiler. Etc. Normally an infinity of ways to do the same thing are not desirable, however.
    – goldilocks
    Commented Nov 28, 2015 at 12:56
  • @goldilocks I don't believe this should be on hold. As is, it is a perfectly reasonable question, unlike your two examples. The answer should point to the Broadcom peripherals PDF and note that in order to access the registers you must use /dev/mem. There are many questions similar to this one but none have good answers. We should write a good answer for one and mark all subsequent ones as duplicates. Commented Nov 29, 2015 at 15:27
  • @AlistairBuxton Fair enough -- although I think as written it is as contrived as my examples, just not as zany. The problem is that it is really two arbitrary parts; the first one is about accessing the GPIOs without using the generic sys interface, which has the kind of answer you are talking about it. But the second part is then how to take that and create an idiosyncratic API -- which is fine, but is an unrelated basic C programming question. It also means writing a rather long answer and boils down to, "Give me all da code please".
    – goldilocks
    Commented Nov 29, 2015 at 16:56
  • ...I've edited the question slightly in that light. Aleksander, if you have a problem with that, feel free to click on the edited... link over my little bear, scroll down to revision 2, and select rollback. But please think about the point I am trying to make and what the nature of "Q&A" vs. "discussion forum" is.
    – goldilocks
    Commented Nov 29, 2015 at 17:01
  • No, it's OK. So what you are saying is, in order to do what i asked for, i have to create my own interface, where i have to define the names of the pins and their addresses and after that using this interface i can accomplish what i was asking? Commented Dec 1, 2015 at 10:09

2 Answers 2

3

TRISA would have to be quite a complicated C macro for that to work on a Pi.

Have a look at http://abyz.me.uk/rpi/pigpio/examples.html#Misc_tiny_gpio which shows possibly the simplest way to access the Pi GPIO via C.

In particular it shows how to implement the following functions.

gpioSetMode       /* set GPIO mode */
gpioGetMode       /* get GPIO mode */
gpioSetPullUpDown /* set internal GPIO pull-up/down */
gpioRead          /* read GPIO */
gpioWrite         /* write GPIO */
gpioReadBank1     /* read levels of GPIO in bank 1 */
gpioReadBank2     /* read levels of GPIO in bank 2 */
gpioClearBank1    /* clear selected GPIO in bank 1 */
gpioClearBank2    /* clear selected GPIO in bank 2 */
gpioSetBank1      /* set selected GPIO in bank 1 */
gpioSetBank2      /* set selected GPIO in bank 2 */
0
3

First we need to declare our address of the BCM2708. Then we add the starting address of the GPIO pins to the BCM2708 address. We need those addresses so we can map them, using the mmap function, which will "expose" them and let us modify them and work with them.

Here is how we can do this:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mmap.h>

#define BCM2708_PERI_BASE (0x3F000000)//decimal 1056964608
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)//decimal 1059061760
#define BLOCK_SIZE (4096)

struct bcm2835_peripheral
{
    int mem_fd;
    void *map;
    volatile unsigned int *addr;//address of mapped area
};
//mmap function
int map_peripheral(struct bcm2835_peripheral *p)
{
    //open the /dev/mem folder with read/write
    if((p->mem_fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0)
    {
        printf("Failed to open /dem/mem, did you sudo?\n");
        return -1;
    }
    p->map = mmap(NULL,
                  BLOCK_SIZE,
                  PROT_READ|PROT_WRITE,
                  MAP_SHARED,
                  p>mem_fd,
                  GPIO_BASE);

    if(p->map == MAP_FAILED)
    {
        printf("mmap failed, MAP_FAILED\n");
        return -1;
    }
    close(p->mem_fd);
    p->addr = (volatile unsigned int *)p->map;

    return 0;
}
//unmap the same memory block
void unmap_peripheral(struct bcm2835_peripheral *p)
{
    munmap(p->map, BLOCK_SIZE);
    close(p->mem_fd);
}


//here is the GPIO manipulation in CLEAN C
//setting the pin as input
void input_GPIO(int gpio_numb)
{
    *(gpio.addr + ((gpio_numb)/10)) &= ~(7<<(((gpio_numb)%10)*3));
}
//setting the pin as output
void output_GPIO(int gpio_numb)
{
    input_GPIO(gpio_numb);
    *(gpio.addr + ((gpio_numb)/10)) |=  (1<<(((gpio_numb)%10)*3));
}
//setting the pin to HIGH
void high_GPIO(int gpio_numb)
{
    *(gpio.addr + 7) = 1 << gpio_numb;
}
//setting the pin to LOW
void low_GPIO(int gpio_numb)
{
    *(gpio.addr + 10) = 1 << gpio_numb;
}
4
  • I'm not sure what makes this code any cleaner than any other. As it stands it does not compile. Could you update the example so it compiles? The code as written would only work on a Pi2.
    – joan
    Commented Dec 18, 2015 at 20:36
  • You can look at a whole working example here: raspberrypi.stackexchange.com/questions/39202/… Commented Dec 19, 2015 at 9:26
  • Yes, that is much better. So if I understand correctly by clean C you mean only using the GNU libraries.
    – joan
    Commented Dec 19, 2015 at 9:54
  • Yes, since i would like to go low level, closer to the hardware, I don't want to use any external libraries, like wiringPi etc. Commented Dec 19, 2015 at 15:41

Your Answer

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

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