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.
Vous devez vous connecter pour publier un commentaire.
Mmap est la fonction qui travaille généralement avec des adresses virtuelles. Lorsque vous appelez
mmap(... MAP_ANONYMOUS)
(oummap
de/dev/zero
fichier), il vous donnera une certaine quantité de mémoire virtuelle, rempli de zéro. Adresse retournée sera l'adresse de la mémoire virtuelle.Vous pouvez mmap certains fichier (sans MAP_ANONYMOUS) et mmap sera carte contenu du fichier dans certaines virtuel de la mémoire.
Appareil MMIO est situé dans la mémoire Physique; tout processus peut utiliser l'adresse virtuelle 0x40400000; mais ils seront mappés (traduit) gratuit à un certain nombre de page physique par la MMU (memory management unit). Vous ne pouvez pas demander OS pour certains, la mémoire virtuelle et s'attendre à ce que se sera mmaped de gamme des appareils (il sera variante de l'enfer).
Mais il y a un spécial de périphérique /dev/mem, qui peut être utilisé comme Fichier contenant tous les fichiers de la mémoire physique.
Lorsque vous
mmap
s /dev/mem vous êtes en train de demander de l'OS pour créer une nouvelle cartographie de certains de mémoire virtuelle en a demandé physique.Dans votre invocation de mmap:
vous demander de carte mémoire physique de la gamme
[0x40400000 .. 0x4050000-1]
(un mégaoctet; non compris les octets 0x40500000) en quelques mégaoctets de mémoire virtuelle (son adresse de départ est retourné par mmap).