2011-11-07 5 views
0

J'essaye d'accéder aux broches GPIO sur Arm9 9g20 d'Atmel. Mon code ci-dessous continue d'échouer à

gpio = mmap (0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // début de GPIOA

lecture ARM 9g20 GPIO en utilisant mmap ne fonctionne pas

Quelqu'un pourrait-il m'aider avec mon code et offrir un peu d'exemple de code E/S pour me faire passer cette bosse? Merci.

// gpio.c 
// compile arm-linux-gcc -o button button.c 
// 

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

// GPIO Registers 
//http://www.atmel.com/dyn/resources/prod_documents/doc6384.pdf - page 374 
#define PIO_PER 0x0000 // PIO Enable Register Write-only – 
#define PIO_PDR 0x0004 // PIO Disable Register Write-only – 
#define PIO_PSR 0x0008 // PIO Status Register Read-only 
#define PIO_OER 0x0010 // Output Enable Register Write-only – 
#define PIO_ODR 0x0014 // Output Disable Register Write-only – 
#define PIO_OSR 0x0018 // Output Status Register Read-only. reset 0x0000 0000 
//0x001C Reserved 
#define PIO_IFER 0x0020 // Glitch Input Filter Enable Register Write-only – 
#define PIO_IFDR 0x0024 // Glitch Input Filter Disable Register Write-only – 
#define PIO_IFSR 0x0028 // Glitch Input Filter Status Register Read-only. Reset 0x0000 0000 
//0x002C Reserved 
#define PIO_SODR 0x0030 // Set Output Data Register Write-only – 
#define PIO_CODR 0x0034 // Clear Output Data Register Write-only 
#define PIO_ODSR 0x0038 // Output Data Status Register Read-only or Read-write 
#define PIO_PDSR 0x003C // Pin Data Status Register Read-only 
#define PIO_IER 0x0040 // Interrupt Enable Register Write-only – 
#define PIO_IDR 0x0044 // Interrupt Disable Register Write-only – 
#define PIO_IMR 0x0048 // Interrupt Mask Register Read-only. Reset 0x00000000 
#define PIO_ISR 0x004C // Interrupt Status Register Read-only. Reset 0x00000000 
#define PIO_MDER 0x0050 // Multi-driver Enable Register Write-only – 
#define PIO_MDDR 0x0054 // Multi-driver Disable Register Write-only – 
#define PIO_MDSR 0x0058 // Multi-driver Status Register Read-only. Reset 0x00000000 
//0x005C Reserved 
#define PIO_PUDR 0x0060 // Pull-up Disable Register Write-only – 
#define PIO_PUER 0x0064 // Pull-up Enable Register Write-only – 
#define PIO_PUSR 0x0068 // Pad Pull-up Status Register 
#define PIO_ASR 0x0070 // Peripheral A Select Register Write-only – 
#define PIO_BSR 0x0074 // Peripheral B Select Register Write-only – 
#define PIO_ABSR 0x0078 // AB Status Register Read-only 0x00000000 
//0x007C to 0x009C Reserved 
#define PIO_OWER 0x00A0 // Output Write Enable Write-only – 
#define PIO_OWDR 0x00A4 // Output Write Disable Write-only – 
#define PIO_OWSR 0x00A8 // Output Write Status Register Read-only 0x00000000 


/******************************************************************************************************* 
*             MAIN 
*******************************************************************************************************/ 
int main(int argc, char **argv) { 
    volatile unsigned int *PADR, *PADDR, *PBDR, *PBDDR, *PCDR, *PCDDR; 
    unsigned long *gpio; 

    int fd = open("/dev/mem", O_RDWR|O_SYNC); 
    if (fd < 0){ 
     fprintf(stderr, "Unable to open port\n\r"); 
     exit(fd); 
    } 

    gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // start of GPIOA 

    if(gpio == (void *) -1) { 
     printf("Memory map failed.\n"); 
     exit(0); 
    } else { 
     printf("Memory mapped at address %p.\n", gpio); 
    } 

    PADR = (unsigned int *)(gpio + 0x00);  // port a 
    PADDR = (unsigned int *)(gpio + PIO_OER); // port a output enable 

    *PADDR = 0xff; // make all output 
    *PADR = 0xffff; // turn All of A Off 

    close(fd); 
    return 0; 
} 
+0

avez-vous vérifié que votre adresse de base est sur une limite de page? essayez 0xFFFF0000 ou 0xFF000000, ce genre si chose. Je le vois généralement à l'opposé de ce que vous attendez, le plus gros morceau est plus facile à allouer que de plus petits morceaux concentrés. –

Répondre

0

Vous ne savez pas quel type de défaillance vous rencontrez (elles ne sont pas décrites) mais les opérations avec le port GPIO et les commentaires ne sont pas corrects. Tout d'abord, le registre PIO_PER est le registre d'activation des E/S, la définition des bits n'est pas , ce qui les rend disponibles mais permettant. D'autre part, PIO_OER est en effet pour ce qui rend la sortie et non tout éteindre. Donc, vous devriez coller à la séquence suivante:

// initializing 
*(unsigned int *) (gpio + PIO_PER) = 0xff; // enable 
*(unsigned int *) (gpio + PIO_OER) = 0xff; // set output 

// working 
... 
*(unsigned int *) (gpio + PIO_SODR) = 0xff; // set 1's 
... 
*(unsigned int *) (gpio + PIO_CODR) = 0xff; // set 0's 

MISE À JOUR

Depuis que les pages entières peuvent être mises en correspondance, vous devez prendre cela en considération:

#define MAP_SIZE 4096UL 
#define MAP_MASK (MAP_SIZE - 1) 
#define GPIOA_BASE 0xFFFFF400 

...  
/* Map one page */ 
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIOA_BASE & & ~MAP_MASK); 
...  
gpio = map_base + (GPIOA_BASE & MAP_MASK); 
... 

Vérifiez les sources de outil devmem bien connu: here

+0

qui crée un segfalut
~ # ./gpio Mémoire mappée à l'adresse 0x40068000. Segmentation fault – Jim

+0

voir les mises à jour ci-dessus – pmod

Questions connexes