Heut hab ich auch mal wieder ein kleines Problemchen, bei dem ich irgendwie tierisch auf dem Schlauch stehe.
Kurz die Ausgangssituation:
Ich möchte unter Linux via C auf Parallel I/O-Controller zugreifen.
Bislang funktioniert das Setzen/Löschen von einzelnen Output-Pins, nur beim Auslesen des Status der Input-Pins renne ich mit Anlauf gegen eine Wand.
Für die Output-Pins ist bislang folgendes (gekürzte Fasung) vorhanden.
Code:
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE -1)
#define PIOA_BASE 0xfffff400UL
//Input-Pins
#define PIO_A1 ((unsigned long) 1 << 27)
#define PIO_A2 ((unsigned long) 1 << 23)
//Output-Pins
#define PIO_A3 ((unsigned long) 1 << 26)
#define PIO_A4 ((unsigned long) 1 << 25)
//configure Register
#define PIOA_PER PIOA_BASE + 0x00 //PIO ENABLE REGISTER
#define PIOA_PDR PIOA_BASE + 0x04 //PIO DISABLE REGISTER
#define PIOA_OER PIOA_BASE + 0x10 //OUTPUT ENABLE REGISTER
#define PIOA_ODR PIOA_BASE + 0x14 //OUTPUT DISABLE REGISTER
#define PIOA_OSR PIOA_BASE + 0x18 //OUTPUT STATUS REGISTER
#define PIOA_SODR PIOA_BASE + 0x30 //SET OUTPUT DATA REGISTER
#define PIOA_CODR PIOA_BASE + 0x34 //CLEAR OUTPUT DATA REGISTER
#define PIOA_ODSR PIOA_BASE + 0x38 //OUTPUT DATA STATUS REGISTER
#define PIOA_PDSR PIOA_BASE + 0x3C //PIN DATA STATUS REGISTER
#define PIOA_IFER PIOA_BASE + 0x20 //INPUT FILTER ENABLE REGISTER
#define PIOA_IFDR PIOA_BASE + 0x24 //INPUT FILTER DISABLE REGISTER
//Configure macros
#define PIOA_Enable_Register(addr, pio) *((unsigned long *) (addr + (PIOA_PER & MAP_MASK))) = pio
#define PIOA_Disable_Register(addr, pio) *((unsigned long *) (addr + (PIOA_PDR & MAP_MASK))) = pio
#define PIOA_Enable_Output(addr, pio) *((unsigned long *) (addr + (PIOA_OER & MAP_MASK))) = pio
#define PIOA_Disable_Output(addr, pio) *((unsigned long *) (addr + (PIOA_ODR & MAP_MASK))) = pio
#define PIOA_Enable_Inputfilter(addr, pio) *((unsigned long *) (addr + (PIOA_IFER & MAP_MASK))) = pio
#define PIOA_Enable_Input(addr, pio) \
(*((unsigned long *) (addr + (PIOA_ODR & MAP_MASK))) = pio) && \
(*((unsigned long *) (addr + (PIOA_IFER & MAP_MASK))) = pio) && \
(*((unsigned long *) (addr + (PIOA_CODR & MAP_MASK))) = pio)
#define PIOA_Set_Low(addr, pio) *((unsigned long *) (addr + (PIOA_CODR & MAP_MASK))) = pio
#define PIOA_Set_High(addr, pio) *((unsigned long *) (addr + (PIOA_SODR & MAP_MASK))) = pio
int main (void){
int fd;
void *map_base;
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
{
exit(1); //Fehler beim Zugriff auf dev-mem
}
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOA_BASE & ~MAP_MASK);
if (map_base == (void *) -1)
{
exit(1); //Zugriffsfehler
}
PIOA_Enable_Register(map_base, PIO_A1 | PIO_A2 | PIO_A3 | PIO_A4);
PIOA_Enable_Output(map_base, PIO_A3 | PIO_A4);
PIOA_Enable_Inputfilter(map_base, PIO_A1 | PIO_A2);
PIOA_Enable_Input(map_base, PIO_A1 | PIO_A2);
PIOA_Set_Low(map_base, PIO_A3 | PIO_A4);
//PIOA_Set_High(map_base, PIO_A3 | PIO_A4);
/* Hier kommt der Code zum Lesen der Eingaenge rein!! */
if (munmap(map_base, MAP_SIZE) == -1) exit(1);
close(fd);
} * Anm: PIOA deshalb, weil es noch zwei weitere PIO-Controller gibt.....
Via PIOA_Set_Low()/PIOA_Set_High() jeder angegebene Pin auf Highlevel (1/AN) oder Lowlevel (0/Aus) geschaltet werden.
Ich hab inzwischen zum Auslesen der Input-Pins die wildesten Versuche unternommen. Entweder erhalte ich als Fehlermeldung dabei dann "Segmentation fault" oder einen Hexadezimalwert, der mir in dieser Form leider nicht weiterhilft. Vermutlich bin ich mit den kläglichen Versuchen auch völlig auf dem Holzweg......
Ich muss auf mmap() dabei ja dynamisch zugreifen, sprich der Inhalt muss bei Bedarf jeweils neu gelesen werden.
Code:
volatile i=mmap(0, MAP_SIZE, ....);
Die Frage daher: Wie kann ich den Status eines einzelnen Input-Pins feststellen? (Es wird ja auch nur ein Bit gesetzt oder nicht gesetzt sein...... Nur wie komme ich an dieses Bit - ohne gleich ein Bier bestellen zu müssen?)