Comment fonctionne l'adressage des E / S mappées en mémoire?


29

Comment fonctionne l'adressage des E / S mappées en mémoire?

J'essaie de comprendre un exemple fourni I2S: Quelqu'un l'a fait fonctionner? .

Configuration des horloges:

#define BCM2708_PERI_BASE        0x20000000
#define CLOCK_BASE               (BCM2708_PERI_BASE + 0x101000) /* Clocks */

Il mappe d'abord le code comme ça ...

clk_map = (unsigned char *)mmap(
      (caddr_t)clk_mem,
      MAP_BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      CLOCK_BASE
   );

Ensuite, il fait quelque chose ...

 // Always use volatile pointer!
   clk = (volatile unsigned *)clk_map;

Et quand il est référencé, il y a ces ajouts étranges de 0x26 et 0x27, de quoi s'agit-il?

 printf("Disabling I2S clock\n");
 *(clk+0x26) = 0x5A000000;
 *(clk+0x27) = 0x5A000000;

 usleep(10);

 printf("Confiure I2S clock\n");
 *(clk+0x26) = 0x5A000001;
 *(clk+0x27) = 0x5A000000 | 3<<12 | 1<<9; // divider: 3.125==0b11.001

 usleep(10);
 printf("Enabling I2S clock\n");
 *(clk+0x26) = 0x5A000011;

En regardant la fiche technique, je peux voir où ils ont certaines de ces valeurs, comme l'adresse de base, mais j'ai du mal à comprendre les autres. Où est-ce CLOCK_BASEdéterminé et que se passe-t-il?


1
C'est probablement le mieux adapté pour StackOverflow. Bien que cela concerne le RPi, vous aurez plus de chances d'y obtenir des réponses aux questions de programmation.
Jivings

4
Peut-être, mais je pense que c'est une question plus générale liée à la programmation Pi combinant l'interprétation de la fiche technique et du matériel Pi. voyons s'il obtient de bonnes informations.
Dog Ears

D'accord. Voyons comment ça se passe :)
Jivings

1
Je ne pense pas que cela fonctionnerait trop bien sur Stack Overflow - c'est assez spécialisé et attirerait probablement plus d'experts ici.
Flexo

Réponses:


18

Sur un ordinateur, vous écrivez à une «adresse mémoire» spécifiée. Cette adresse est reconnue par le système comme une adresse matérielle et le matériel approprié reçoit ou envoie la valeur appropriée.

La plupart des systèmes matériels ont de nombreux registres différents qui peuvent être définis ou lus. Certains pourraient en avoir quelques-uns, certains pourraient en avoir beaucoup. Ces registres seront regroupés dans une plage continue. Un pointeur de base pointe vers le premier de la plage et vous écrivez, par exemple, sur le deuxième port avec base_pointer + 1. Ce n'est pas nécessaire, vous pouvez écrire directement sur un pointeur, mais l'utilisation d'un décalage facilite la tâche.

Le Raspberry Pi reconnaît une vaste gamme de registres matériels à l'adresse 0x20000000. Une gamme de registres qui contrôlent les systèmes d'horloge est accessible à partir de BCM2708_PERI_BASE + 0x101000. Les registres qui contrôlent l'horloge I2S sont les 38e et 39e registres de ce bloc, écrits en utilisant BCM2708_PERI_BASE + 0x101000 + 0x26 et 0x27

Cependant, vous ne pouvez pas simplement modifier les valeurs d'horloge, vous devez désactiver l'horloge, modifier les valeurs et la redémarrer.

Si cette réponse est trop basique, mes excuses. Dans ce cas, votre question est vraiment hardcore, bonne chance. Vous pourriez trouver ce lien utile

Mise à jour: pourquoi utiliser mmap et ne pas écrire directement dans la mémoire?

Lorsqu'un programme exécute les adresses mémoire qu'il pense ne pas avoir de vraies adresses, elles sont mappées à des adresses réelles par le gestionnaire de mémoire. Cela empêche un programme de pouvoir en affecter un autre. Deux processus peuvent parfaitement lire et écrire sur leur propre adresse 1234, et le gestionnaire de mémoire gardera les deux emplacements complètement séparés.

Les ports matériels, cependant, sont à des adresses physiques absolues. Mais vous ne pouvez pas leur écrire directement parce que le gestionnaire de mémoire prendra votre adresse et la mappera à votre zone de mémoire personnelle.

Sous Linux / dev / mem est un « fichier de périphérique de caractères qui est une image de la mémoire principale de l'ordinateur »

Si vous l'ouvrez comme un fichier, vous pouvez y lire et y écrire comme un fichier. Dans l'exemple fourni mem_fd est un descripteur de fichier résultant de l'ouverture de / dev / mem

Un autre système qui peut vous faciliter la vie est la possibilité de mapper un fichier en mémoire et d'y écrire comme de la mémoire. Donc, si vous avez un fichier dans lequel vous souhaitez lire ou écrire différents bits spécifiques, au lieu de déplacer le pointeur de fichier en arrière et en avant, vous pouvez le mapper vers un emplacement en mémoire, puis y écrire directement comme s'il s'agissait de mémoire.

Ainsi, dans cet exemple, le code crée un handle vers la mémoire physique, comme s'il s'agissait d'un fichier sur le disque, puis demande au système de le traiter comme s'il s'agissait de mémoire. Un peu compliqué, mais nécessaire pour contourner le gestionnaire de mémoire virtuelle et écrire sur une adresse physique réelle. La valeur 0x20000000, semble-t-il, est un peu un hareng rouge. Le code propose cette adresse à titre indicatif, le système n'a pas à mapper / dev / mem ici, bien qu'il le fasse probablement. Normalement, la valeur null serait transmise et le système mapperait le descripteur de fichier à l'adresse qu'il jugeait la meilleure.

Maintenant, la mémoire physique est mappée à la mémoire virtuelle des processus, et les lectures et écritures vont là où vous vous attendez.

Les références:

http://www.kernel.org/doc/man-pages/online/pages/man2/mmap.2.html

http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=8496&p=104359

https://superuser.com/questions/71389/what-is-dev-mem


J'ai encore quelques questions: pourquoi font-ils mmap? Pourquoi ne pas accéder directement à la mémoire?
Alex Chamberlain

@AlexChamberlain Parce que le code s'exécute sur Linux, vous ne pouvez donc pas accéder directement à la mémoire car chaque processus obtient son propre espace mémoire virtuel. Cependant, on peut ouvrir et mmap / dev / mem pour accéder directement à la mémoire physique
nos

1

@AlexChamberlain cela est dû à la structure du système d'exploitation. Vous pouvez vous en passer mmapmais la pagination est déclarée, donc pas d'accès direct. En mode noyau, vous pouvez vous passer mmap, par exemple, d'insérer votre pilote en tant que module noyau sans avoir besoin de mmap. En outre, dans le cas le plus simple du système d'exploitation, où aucune mémoire de table de pages n'est utilisée, vous pouvez accéder sans mmapnon plus, par ex. accès direct à l'adresse physique.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.