C Programm for accessing GPIO

Started by Kampi, July 12, 2014, 09:19:39 PM

Previous topic - Next topic

Kampi

Hello Guys,

I have written a small C-Programm to Access GPIO over /dev/mem


#include <stdio.h> // Standard Ein-/Ausgabe
#include <sys/mman.h> // Für die mmap() Funktion
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define GPIO_Basis 0x01C20800

// Struct zur Beschreibung der Peripherie
struct A20_Peripherie {
unsigned long Adresse; // Adresse der entsprechenden Peripherie
int Memory; // Filedescriptor /dev/mem
void *Map; // Zeiger auf den markieren RAM Bereich für die Peripherie
volatile unsigned int *Addr; // Die physikalische Adresse im RAM die beschrieben werden soll
};

struct A20_Peripherie GPIO = {GPIO_Basis}; // Neues Struct für die GPIO generieren und darin die GPIO Adresse speichern

int RAM_Map(struct A20_Peripherie *Peripherie)
{
Peripherie->Memory = open("/dev/mem", O_RDWR | O_SYNC);

if(Peripherie->Memory < 0)
{
printf("Oeffnen von /dev/mem fehlgeschlagen!\n");
return -1;
}

// RAM Zugriff beim Betriebssystem anmelden
Peripherie->Map = mmap(
NULL, // Gesamten RAM zur Auswahl stellen
getpagesize(),
PROT_READ | PROT_WRITE, // Zugriffsmodi auf den RAM
MAP_SHARED, // Updates im Mapping werden für andere Prozesse sichtbar gemacht
Peripherie->Memory, // Filehandle übergeben
Peripherie->Adresse // Zu mappende Adresse übergeben
);

if(Peripherie->Map < 0)
{
printf("Mapping fehlgeschlagen!\n");
return -1;
}

Peripherie->Addr = (volatile unsigned int *)Peripherie->Map; // Die Adresse zeigt jetzt auf das Mapping -> Beschreiben der Adresse
// bewirkt ein Beschreiben des gemappten Bereiches
return 0;
}

// Aufheben des Mappingbereiches
void Delete_RAM_Map(struct A20_Peripherie *Peripherie)
{
munmap(
Peripherie->Map, // Zu löschende Mapping übergeben
getpagesize()
);
}

int main()
{
if(RAM_Map(&GPIO) == -1)
{
printf("Mappen der GPIO fehlgeschlagen!\n");
return -1;
}

*(GPIO.Addr + 0xD8) = 1 << 0;
*(GPIO.Addr + 0xE8) = 1 << 0;

while(1)
{

}

return 0;
}



If I want to execute it, I got the Error "Segmentation fault". I start this Programm as root.
Why I get this Error?

Thank you!


Kampi

Hello,

tested it with this Programm (works on Raspberry Pi):


#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define BLOCK_SIZE 4096
#define Peripherie_Basis 0x20000000
#define GPIO_Basis 0x01C20800

// Struct für die nötigen Peripherie Informationen
struct BCM2835_Peripherie {
unsigned long Adresse;
int Memory;
void *Map;
volatile unsigned int *Addr;
};

// Startadresse des GPIO-Controllers in das Struct rein schreiben
struct BCM2835_Peripherie GPIO = {GPIO_Basis};

int RAM_Map(struct BCM2835_Peripherie *Peripherie);

// Funktion zum markieren der Speicherbereiche
int RAM_Map(struct BCM2835_Peripherie *Peripherie)
{
Peripherie->Memory = open("/dev/mem", O_RDWR | O_SYNC);

if(Peripherie->Memory < 0)
{
printf("Oeffnen von /dev/mem fehlgeschlagen!\n");
return -1;
}

Peripherie->Map = mmap(
NULL,
BLOCK_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
Peripherie->Memory,
Peripherie->Adresse
);

if(Peripherie->Map < 0)
{
printf("Mapping fehlgeschlagen!\n");
return -1;
}

Peripherie->Addr = (volatile unsigned int *)Peripherie->Map;
return 0;
}




int main()
{
if(RAM_Map(&GPIO) == -1)
{
printf("Mappen der GPIO fehlgeschlagen!\n");
return -1;
}

*(GPIO.Addr + 0xD8) = 001 << 21;
*(GPIO.Addr + 0xE8) = 1 << 17;

return 0;
}


Change the Adresses, but the Error is still there.

JohnS

RPi uses BCM cpu.  Its a lot different.

Maybe datasheet for cpu you have will be enough to change code as needed.

John

Kampi

Yes, I know that the RPi use the BCM2835.
But I think that accessing GPIO over /dev/mem is still the same procedure. So I take my Raspberry Pi Programm and change the Adress of GPIO Base and the Register:

http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf

Or is there something else, which I have to change in the Code?

Mouchon


Kampi

Thank you for that link.
I compare it with my Programm and then I will see what´s wrong.

herter

Hello,

Mouchon, this code seems not to manage the interrupts?

Thanks

JohnS

That's what the kernel's for (else better not to use interrupts).

John

herter


JohnS

You lost me.  An interrupt is an interrupt.

Are you wanting to run "bare metal" i.e. no Linux & no Android?

John

Mouchon

This code doesn't handle interrupt. The only way to handle it is to use gpio drivers and use

/sys/class/gpio fs. Or make your own kernel module.

kr

Kampi

Don´t understanding my Problem... don´t find my misstake.
>.<