J'expérimente avec quelques tests de synchronisation de la gigue en basculant une ligne GPIO et en observant la forme d'onde sur un oscilloscope. Mon noyau est compilé avec PREEMPT_RT
. J'espérais que changer le planificateur pour le processus à SCHED_FIFO
permettrait de réduire la gigue, mais cela ne semble pas avoir fait beaucoup de différence. Le code est ci-dessous. Est-ce que je fais quelque chose de mal en essayant d'obtenir des performances en temps réel à partir de ce code?Voyant les performances en temps réel pauvres sur test de bascule GPIO Linux en utilisant SCHED_FIFO
// Program to test Linux timing jitter by driving GPIO output via sysfs interface.
// In this variant, the scheduler is changed to SCHED_FIFO.
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
int main() {
char buf[128];
struct sched_param schedp;
const int pin = GPIO_TO_PIN(1, 24);
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open export for writing!\n");
return(-1);
}
int bytes_written = snprintf(buf, sizeof buf, "%d", pin);
write(fd, buf, bytes_written);
close(fd);
snprintf(buf, sizeof buf, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(buf, O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open gpio direction for writing!\n");
return(-1);
}
if (write(fd, "out", 3) == -1) {
fprintf(stderr, "Failed to set direction!\n");
return(-1);
}
snprintf(buf, sizeof buf, "/sys/class/gpio/gpio%d/value", pin);
fd = open(buf, O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open gpio value for writing!\n");
return(-1);
}
// Change scheduler to SCHED_FIFO.
schedp.sched_priority = 99;
if (sched_setscheduler(0, SCHED_FIFO, &schedp)) {
perror("sched_setscheduler");
}
while (1) {
if (write(fd, "1", 1) != 1) {
fprintf(stderr, "Failed to write value!\n");
return(-1);
}
usleep(500);
if (write(fd, "0", 1) != 1) {
fprintf(stderr, "Failed to write value!\n");
return(-1);
}
usleep(500);
}
close(fd);
return 0;
}
D'une manière générale, oui, il est faux d'attendre des performances RT du code en mode utilisateur. Combien de gigue attendez-vous et combien voyez-vous? –
Je vois une gigue de 10% dans le carré lorsque le système est inactif, mais si je cours des commandes alors je peux parfois le voir ne pas basculer pendant quelques ms. Je pensais que le point de l'ajout PREEMPT_RT était de sorte que vous puissiez faire du code temps réel dans l'espace utilisateur? – user43995
@ user43995 Un peu. Linux n'est pas un système d'exploitation en temps réel, donc il n'y a toujours pas de garantie. De plus, par défaut, 5% de seconde peuvent toujours être utilisés par des tâches de priorité inférieure et préempter votre tâche "en temps réel" (voir https://www.kernel.org/doc/Documentation/scheduler/sched-rt-group). SMS). Vous serez également lié par le taux de tick du noyau, mais avec le taux de tick 1000Hz habituel, qui ne pourrait représenter que 1ms. – nos