mardi 4 juin 2019

Chapitre 60 : utilisation du timer à l'aide d'un driver spécifique Linux


Dans le chapitre 25, j’avais déjà donné un programme assembleur qui utilisait le timer du BCM2835 mais ce programme devait être lancé par sudo pour autoriser le mapping en mémoire des registres du timer.
Après plusieurs recherches, j’ai trouvé une solution pour éviter le lancement par sudo sur le site : https://mindplusplus.wordpress.com/2013/08/09/accessing-the-raspberry-pis-1mhz-timer-via-kernel-driver/
Et qui va en plus simplifier la lecture car il n’est plus nécessaire d’effectuer le mapping.
Il s’agit de mettre en place un driver spécifique Linux qui autorisera la lecture du registre du Timer. Mais hélas, nous n’allons pas écrire ce driver en assembleur, nous allons nous contenter de récupérer le source C, de créer les objets particuliers grâce au Makefile donné par le même site.En effet, la compilation doit s’effectuer avec des contraintes particulières de création de ce type de module.

 Ensuite nous écrirons un programme en assembleur pour tester le timer au travers de ce driver.
Tout d’abord la compilation du programme C nécessite la mise en place du package : raspberrypi-kernel-headers avec la commande : sudo apt-get install raspberrypi-kernel-headers après avoir mis à jour votre raspberry avec les commandes update habituelles (En effet le package doit être au même niveau de version que le kernel).
Puis il faut créer sur votre raspberry le répertoire : bcm2708_usec et récupérer sur le site le programme source et le makeFile en faisant bien attention de ne pas modifier les noms bcm2708_usec.c et Makefile (attention à la majuscule).
Remarque : pour les curieux, voir les discussions en anglais sur le nommage des bcm !!!
Suivant le modèle de votre raspberry, modifier dans le source bcm2708_usec.c, l’adresse de TIMER_PAGE_BASE soit  0x3F003000 pour le pi2 et 3 soit 0x20003000 pour le pi1.
Se placer dans le répertoire bcm2708_usec et lancer la construction des objets en tapant make.
Corriger les erreurs éventuelles !!!! et vérifier la présence du module objet bcm2708_usec.ko.
Maintenant il faut activer et déclarer ce nouveau module dans le système linux par
sudo /sbin/insmod ./bcm2708_usec.ko
puis
sudo /bin/mknod -m 444 /dev/bcm2708_usec c 240 0
Remarque : en cas d’erreur vous pouvez désinstaller le module par la commande :
sudo /sbin/rmmod ./bcm2708_usec.ko
Pour vérifier vous pouvez lancer la commande mais il faudra la tuer par un control-C :
od -t u8 /dev/bcm2708_usec

Si tout va bien, il vous reste à récupérer mon programme assembleur testTimerSp.s pour voir l’utilisation du timer.
Dans ce programme, nous commençons par ouvrir ce nouveau driver par le call system OPEN en lui passant le nom /dev/bcm2708_usec et nous récupérons comme tout fichier unix, le File Descriptor.
Avec celui ci nous nous contentons de lire le contenu du registre du Timer par le call system READ une première fois, puis de mettre en attente le programme une seconde avec le call system SLEEP, de relire le contenu du timer et d’afficher la différence des 2 lectures. Nous terminons par l’appel système CLOSE pour fermer le driver.
L’exécution s’effectue sans avoir besoin de taper sudo nom-du-programme et l’affichage indique bien une valeur autour de 1000000, ce qui correspond bien au nombre de microsecondes contenues dans une seconde.
La valeur calculée est supérieure car l’appel systeme SLEEP nécessite quelques microsecondes pour s’exécuter !!
Curieusement, le résultat n’est pas toujours identique, et je ne suis pas arrivé à expliquer pourquoi (multitaches ? mémoire 1er niveau ?, interruptions ?).

Dans ce deuxième programme, nous allons mesurer le temps d’exécution de sous routines. Il effectue 8 mesures (8 pour faciliter la division en utilisant le décalage de 3 bits à droite) de l’exécution d’un million de sous routines.
Pour cela après l’ouverture du driver bcm2708_usec, nous appelons la routine chrono en lui passant le File-Descriptor récupéré lors de l’ouverture précédente dans r0 et l’adresse de la sous routine à mesurer dans r1.
Dans la routine chrono, nous trouvons une boucle qui  effectue 8 mesures de temps et qui se décompose en une lecture du compteur du timer par l’appel système Read, l’exécution d’une boucle qui appelle 1 million de fois la sous routine à mesurer puis qui lit une deuxième fois le compteur du timer. Puis elle calcule la différence et affiche le résultat.
A la fin de cette boucle, nous affichons la moyenne des mesures car les résultats de chaque mesure ne sont pas identiques.
A l’exécution, nous remarquons pour la première routine des temps très variables !! C’est pourquoi nous exécutons une deuxième fois la mesure de la sous routine vide en fin du programme. Cela nous donne une valeur de référence qui permet calculer les temps internes des autres sous-routines.

Remarque 1 : Il doit être possible de copier et modifier le programme C pour effectuer des accès à d’autres parties du périphérique du raspberry.

Remarque 2 : maintenant les sources des programmes de ce blog sont stockés sur GITHUB  et non plus sur le drive de Google pour des facilités de consultation et d'extraction.

Remarque 3 : à chaque maj de Raspbian, vous devez recompiler le module C et le réactiver en effectuant les mêmes manipulations.

Aucun commentaire:

Enregistrer un commentaire