2017-06-02 4 views
-1

J'essaie d'accéder aux registres d'adresses physiques sur mon ARM (https://4donline.ihs.com/images/VipMasterIC/IC/ATML/ATML-S-A0001248554/ATML-S-A0001248554-1.pdf) avec mmap mais je ne sais pas quelle longueur mettre.
Par exemple, si j'ai un registre à l'adresse 0xFFFFFCE8 dans lequel j'ai accès à 32 bits.
Que dois-je mettre mmap size_t?

Merci pour votre aide!

EDIT:
Here et here nous pouvons voir qu'ils mettent 4096, et le premier, il est un SAM9 presque la même que la mienne.
Alors, pourquoi ont-ils mis 4096?
Peut-être parce que si je fais:Taille de la carte et mmap Erreur d'argument invalide

#include <unistd.h> 
long sz = sysconf(_SC_PAGESIZE); 
printf("%ld",sz); 

réponse Th est 4096 ...

EDIT 2:
Basé sur this post Je pourrais écrire ceci:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <fcntl.h> 

#define handle_error(msg) \ 
      do { perror(msg); exit(EXIT_FAILURE); } while (0) 

#define PIOD_START_ADDR      0xFFFFFA00 
#define PIOD_STOP_ADDR      0xFFFFFC00 
#define PIOD_SIZE       (PIOD_STOP_ADDR-PIOD_START_ADDR) 

#define PIO_WPMR_OFFSET      0xE4 // PIO Write Protection Mode Register Bank D 

#define PIO_PUER_OFFSET      0x64 // PIO Pull-Up Enable Register Bank D 
#define PIO_PUSR_OFFSET      0x68 // PIO Pull-Up Status Register Bank D 

#define LED7_ON        0xFFDFFFFF // LED7 Mask ON 
#define LED7_OFF       0xFFFFFFFF // LED7 Mask OFF 
#define DESABLE_WRITE_PROTECTION_BANK_D  0x50494F00 // Desable write protection 

int main(void) { 
    volatile void *gpio_D_addr; 
    volatile unsigned int *gpio_pullup_enable_addr; 
    volatile unsigned int *gpio_pullup_status_addr; 
    volatile unsigned int *gpio_enable_write_addr; 

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

    gpio_D_addr = mmap(0, PIOD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR); 
    gpio_addr = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDR); 

    if(gpio_D_addr == MAP_FAILED){ 
     handle_error("mmap"); 
    } 

    gpio_enable_write_addr = gpio_D_addr + PIO_WPMR_OFFSET; 
    gpio_pullup_enable_addr = gpio_D_addr + PIO_PUER_OFFSET; 
    gpio_pullup_status_addr = gpio_D_addr + PIO_PUSR_OFFSET; 

    *gpio_enable_write_addr = DESABLE_WRITE_PROTECTION_BANK_D; 

    *gpio_pullup_enable_addr = *gpio_pullup_status_addr & LED7_ON; 

    return 0; 
} 

Mais j'ai un mmap: Invalid argument Erreur. -> Mais en changeant la mmap comme si (merci à ce thread): mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR & ~MAP_MASK); avec:

#define MAP_SIZE       4096UL 
#define MAP_MASK       (MAP_SIZE - 1) 

Je n'ai plus l'erreur, mais rien ne se passait ...

Toute idée?

Répondre

1

Merci à @vlk et son library en python je pourrais le faire fonctionner! Voici un petit exemple pour une LED basculer:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <fcntl.h> 


#define handle_error(msg) \ 
      do { perror(msg); exit(EXIT_FAILURE); } while (0) 

#define _PIOD_BANK_D       0xA00 

#define _PIO_OFFSET        0xFFFFF000 

/* When executing this on the board : 
    long sz = sysconf(_SC_PAGESIZE); 
    printf("%ld\n\r",sz); 
    We have 4096. 
*/ 
#define _MAP_SIZE       0x1000 // 4096 

#define _WPMR_OFFSET      0x0E4 // PIO Write Protection Mode Register Bank D 

#define _PIO_ENABLE       0x000 
#define _PIO_DISABLE      0x004 
#define _PIO_STATUS       0x008 
#define _OUTPUT_ENABLE      0x010 
#define _OUTPUT_DISABLE      0x014 
#define _OUTPUT_STATUS      0x018 
#define _FILTER_ENABLE      0x020 
#define _FILTER_DISABLE      0x024 
#define _FILTER_STATUS      0x028 
#define _OUTPUT_DATA_SET     0x030 
#define _OUTPUT_DATA_CLEAR     0x034 
#define _OUTPUT_DATA_STATUS     0x038 
#define _PIN_DATA_STATUS     0x03c 
#define _MULTI_DRIVER_ENABLE    0x050 
#define _MULTI_DRIVER_DISABLE    0x054 
#define _MULTI_DRIVER_STATUS    0x058 
#define _PULL_UP_DISABLE     0x060 
#define _PULL_UP_ENABLE      0x064 
#define _PULL_UP_STATUS      0x068 
#define _PULL_DOWN_DISABLE     0x090 
#define _PULL_DOWN_ENABLE     0x094 
#define _PULL_DOWN_STATUS     0x098 

#define _DISABLE_WRITE_PROTECTION   0x50494F00 // Desable write protection 

#define LED_PIN         21 

int main(void) { 

    volatile void *gpio_addr; 
    volatile unsigned int *gpio_enable_addr; 
    volatile unsigned int *gpio_output_mode_addr; 
    volatile unsigned int *gpio_output_set_addr; 
    volatile unsigned int *gpio_output_clear_addr; 
    volatile unsigned int *gpio_data_status_addr; 
    volatile unsigned int *gpio_write_protection_addr; 

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


    gpio_addr = mmap(NULL, _MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PIO_OFFSET); 


    if(gpio_addr == MAP_FAILED){ 
     handle_error("mmap"); 
    } 


    gpio_write_protection_addr = gpio_addr + _PIOD_BANK_D + _WPMR_OFFSET; 

    gpio_enable_addr = gpio_addr + _PIOD_BANK_D + _PIO_ENABLE; 

    gpio_output_mode_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_ENABLE; 

    gpio_output_set_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_SET; 

    gpio_output_clear_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_CLEAR; 

    gpio_data_status_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_STATUS; 


    *gpio_write_protection_addr = _DISABLE_WRITE_PROTECTION; 

    *gpio_enable_addr = 1 << LED_PIN; 
    *gpio_output_mode_addr = 1 << LED_PIN; // Output 


    // If LED 
    if((*gpio_data_status_addr & (1<<LED_PIN)) > 0){ 
     *gpio_output_clear_addr = 1 << LED_PIN; 
    }else{ 
     *gpio_output_set_addr = 1 << LED_PIN; 
    } 

    return 0; 
} 

je devais mettre _PIO_OFFSET-0xFFFFF000, et ajouter à l'adresse de la valeur de la D Bank (0xA00), au lieu de 0xFFFFFA00 parce qu'il a donné lieu à mmap: Invalid argument. Je ne sais pas pourquoi ..

EDIT:
trouvé la solution avec le mmap example:

#define _PIO_OFFSET       0xFFFFFA00 // Instead of 0xFFFFF000 
#define _MAP_SIZE       0x1000 // 4096 
#define _MAP_MASK       (_MAP_SIZE - 1) 
#define _PA_OFFSET       _PIO_OFFSET & ~_MAP_MASK 

Et mmap:

gpio_addr = mmap(NULL, _MAP_SIZE + _PIO_OFFSET - _PA_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PA_OFFSET); 

Et pour l'attribution:

gpio_enable_addr = gpio_addr + _PIO_OFFSET - (_PA_OFFSET) + _PIO_ENABLE; 
1

Lisez le chapitre 5 de la fiche technique fourni en tant que lien. Il décrit les différentes mémoires et le mappage de la mémoire pour cet appareil. L'adresse que vous avez indiquée est en 32 bits, mais vous devez vous assurer de sa mise en correspondance. C'est là que le tableau sur p. 18 - en plus de se familiariser avec l'ensemble de la feuille de données de 1200 pages si vous voulez vraiment programmer ces appareils SAM à un niveau bas.

L'adresse que vous avez donné semble aussi être l'espace de mémoire PMC (contrôleur de gestion de l'alimentation) (selon la carte), donc je revoir cette section, chapitre 21.

+0

Merci pour votre aide. J'ai déjà vu ce chapitre, mais voir EDIT de mon post ci-dessus. – Tagadac

+1

Je n'ai aucune idée de la valeur 4096 .. prendrait plus de recherche pour comprendre cela. Mais maintenant, les appels de travail: ( – TomServo

+1

En faisant cela '#include long sz = sysconf (_SC_PAGESIZE); \t printf ("% ld ", sz);' nous avons '4096'. Donc la taille de la page est 4096. – Tagadac