Sur Raspberry Pi, qui est censé être utilisé sous Linux, le programme de l'utilisateur s'exécute naturellement sous le planificateur du système d'exploitation. Par conséquent, il est très difficile d'écrire un programme à durée limitée. En termes simples, je ne suis pas doué pour traiter quelque chose exactement à intervalles réguliers. Dans un tel cas, il s'agit d'une interruption de minuterie ou d'une interrogation d'horloge, mais je pense qu'il existe de nombreux cas où vous souhaitez utiliser ce dernier compte tenu de la faible surcharge et de la simplicité du contexte. À ce moment-là, diverses interruptions interfèrent. J'ai pensé que ce serait bien si je pouvais interdire de simples interruptions temporaires, et j'ai essayé diverses choses, alors j'ai écrit un article. C'est le DI / EI du Z80 qui est familier au vieil homme.
J'ai écrit un programme (décrit plus tard) qui interroge «gettimeofday ()» et fonctionne dans un cycle de 100 US. Voici les résultats (cycle mesuré) pour le cas standard et lorsque les interruptions sont désactivées.
comment c'est? C'est évident en un coup d'œil. Si vous désactivez les interruptions, vous pouvez contrôler différents horaires. Par exemple, Télécommande infrarouge. (Remarque: bien sûr, la désactivation des interruptions a de nombreux effets secondaires. Réduisez le temps de désactivation.)
Selon le manuel du SoC BCM2835 / 2837 de Raspberry Pi, il semble y avoir «registre de désactivation d'interruption» et «registre d'activation d'interruption», alors frappez-les directement. C'est le familier / dev / mem
dans GPIO pour mmap ()
.
mmap ()
pour pouvoir accéder directement à l'adresse physique.Et c'est tout. En termes de Z80, 2-3 est "DI" et 5 est "EI".
Il s'agit du code utilisé pour créer les données du graphique ci-dessus. Veuillez changer la partie de #define PERI_BASE PI? _PERI_BASE
en fonction de votre Raspberry Pi.
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/time.h>
#define BLOCK_SIZE (4 * 1024)
#define PI2_PERI_BASE 0x3f000000
#define PI1_PERI_BASE 0x20000000
#define PERI_BASE PI1_PERI_BASE // Raspberry 0/1 or 2/3
//Temps spécifié(us)Attendez en interrogeant
inline static void waitUs(struct timeval tv_zero, int until_us) {
struct timeval tv;
int us;
while (1) {
gettimeofday(&tv, NULL);
us = (tv.tv_sec - tv_zero.tv_sec) * 1000000 + (tv.tv_usec - tv_zero.tv_usec);
if (us >= until_us) break;
}
}
int main() {
int mem_fd;
char *map;
int i;
int us_next;
struct timeval tv0, tv1;
int dt[10000];
int irq1, irq2, irq3; //Sauvegardons les informations d'interruption(Enfin écrivez à irqen)
volatile unsigned int *irqen1;
volatile unsigned int *irqen2;
volatile unsigned int *irqen3;
volatile unsigned int *irqdi1;
volatile unsigned int *irqdi2;
volatile unsigned int *irqdi3;
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0) return -1;
map = (char*) mmap(NULL,
BLOCK_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
mem_fd,
PERI_BASE + 0xb000
);
if (map == MAP_FAILED) return -1;
irqen1 = (volatile unsigned int *) (map + 0x210);
irqen2 = (volatile unsigned int *) (map + 0x214);
irqen3 = (volatile unsigned int *) (map + 0x218);
irqdi1 = (volatile unsigned int *) (map + 0x21c);
irqdi2 = (volatile unsigned int *) (map + 0x220);
irqdi3 = (volatile unsigned int *) (map + 0x224);
gettimeofday(&tv0, NULL);
irq1 = *irqen1;
irq2 = *irqen2;
irq3 = *irqen3;
//Désactivez toutes les interruptions sur les 3 lignes suivantes
*irqdi1 = 0xffffffff;
*irqdi2 = 0xffffffff;
*irqdi3 = 0xffffffff;
for (i = 0, us_next = 100; i < 10000; i++, us_next += 100) {
waitUs(tv0, us_next);
gettimeofday(&tv1, NULL);
dt[i] = (tv1.tv_usec - tv0.tv_usec) + (tv1.tv_sec - tv0.tv_sec) * 1000000;
}
//Restaurez l'indicateur d'autorisation d'interruption sur les trois lignes suivantes.
*irqen1 = irq1;
*irqen2 = irq2;
*irqen3 = irq3;
//Affichage des résultats
for (i = 1; i < 10000; i++) {
printf("%d\n", dt[i] - dt[i - 1]);
}
return 0;
}
Recommended Posts