La cartographie physique de l'appareil à un pointeur dans l'espace Utilisateur

Nous avons un système intégré où un mappés en mémoire de l'appareil est connecté, et un CPU ARM fonctionne avec Linux. L'appareil est situé à l'adresse 0x40400000 et occupe un mégaoctet (et pour la plupart il n'est pas soutenu par une mémoire réelle, mais l'espace d'adressage est mappé à l'appareil de toute façon). Actuellement, nous ne pas avoir un pilote de périphérique de ce dispositif.

Dans l'appareil il est en lecture seule s'inscrire (appelé CID) à l'adresse 0x404f0704. Ce registre contient la valeur CID = 0x404. Je suis en train de lire ce registre à partir d'un programme en cours d'exécution sur le BRAS.

Cherchant sur le net, j'ai appris à propos de l' mmap() fonction qui est censé me permet d'accéder à une adresse physique à partir de l'espace utilisateur. Donc, en essayant de suivre les quelques exemples que j'ai trouvé, j'ai écrit le test suivant:


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

int main(void)
{
    void          *pdev = (void *) 0x40400000;
    size_t         ldev = (1024*1024);
    int           *pu;
    int  volatile *pcid;
    int  volatile  cid;

    pu = mmap(pdev, ldev, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
    if (pu == MAP_FAILED)
        errx(1, "mmap failure");

    pcid = (int *) (((void *) pu) + 0xf0704);

    printf("pu    = %08p\n", pu);
    printf("pcid  = %08p\n", pcid);

    cid = *pcid;
    printf("CID   = %x\n", cid);

    munmap(pu, ldev);

    return (EXIT_SUCCESS);
}
 

De la compilation avec les BRAS de la croix-compilateur:

a-gcc -O0 -g3 -o mmap-test.elf mmap-test.c

Je ne peux pas obtenir le résultat escompté. Ce que je vois, c'est que:

pu   = 0x40400000
pcid = 0x404f0704
CID  = 0

à la place de l'

CID  = 404

Ce qui me manque /faire de mal ici?


Mise à JOUR:

J'ai trouvé un autre programme de démonstration et à la suite de son code, j'ai pu obtenir mon code de travail:


int main(void)
{
    off_t          dev_base = 0x40400000;
    size_t         ldev = (1024 * 1024);
    unsigned long  mask = (1024 * 1024)-1;
    int           *pu;
    void          *mapped_base;
    void          *mapped_dev_base;
    int  volatile *pcid;
    int  volatile  cid;
    int            memfd;

    memfd = open("/dev/mem", O_RDWR | O_SYNC);
    mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK);
    if (mapped_base == MAP_FAILED)
        errx(1, "mmap failure");
    mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
    pu = mapped_dev_base;

    pcid = (int *) (((void *) pu) + 0xf0704);

    printf("pu    = %08p\n", pu);
    printf("pcid  = %08p\n", pcid);

    cid = *pcid;
    printf("CID   = %x\n", cid);

    munmap(mapped_base, ldev);
    close(memfd);

    return (EXIT_SUCCESS);
}
 

Encore, je ne suis pas sûr pourquoi, la 1ère version n'a pas de travail. Ma compréhension est qu'une fois que vous utilisez MAP_ANONYMOUS vous n'avez pas besoin d'un descripteur de fichier pour la cartographie. Aussi, j'ai évidemment erronée de la addr argument (pepi dans ma 1ère version) à l'adresse physique. Si je suis maintenant, c'est en fait l'adresse virtuelle.

InformationsquelleAutor ysap | 2012-10-10