Le thread périodique échoue en temps réel dans Xenomai

Je crée un thread périodique qui émet un signal carré sur une sortie analogique. J’utilise Posix Skin et Analogy à partir de l’API Xenomai.

J’ai testé les performances en temps réel de mon code à l’aide d’un oscilloscope et en examinant la latence du signal carré (dont la fréquence est de 1 kHz). Je suis censé atteindre une latence inférieure à 100us. Cependant, le signal est fortement (> 250us de latence) perturbé par des signaux d’interruption communs, comme le déplacement de la souris, le démarrage d’un nouveau programme, etc.

Les drapeaux de mon makefile sont configurés comme suit:

gcc -I/usr/xenomai/include -D_GNU_SOURCE -D_REENTRANT -D__XENO__ -I/usr/xenomai/include/posix main_posix.c -Xlinker -rpath -Xlinker /usr/xenomai/lib -Wl,@/usr/xenomai/lib/posix.wrappers -L/usr/xenomai/lib -lpthread_rt -lxenomai -lpthread -lrt -lanalogy -lrtdm -o main_posix 

et voici le code:

 #define PERIOD 1e6 #define FILENAME "analogy0" #define ANALOG_SUBD 1 #define CHANNEL 0 #define SCAN_SIZE 2 #define DELAI 5 static char *filename = FILENAME; static int idx_subd = ANALOG_SUBD; static int idx_chan = CHANNEL; static int valueUp = 450000; static int valueDown = 98500; void *TaskCode(void *arg) { unsigned char sgnl = 0; unsigned long overruns_r = 0; a4l_desc_t dsc = { .sbdata = NULL }; a4l_chinfo_t *chinfo; int err = 0; unsigned int scan_size = SCAN_SIZE; err = a4l_open(&dsc, filename); if (err < 0) { fprintf(stderr, "insn_write: a4l_open %s failed (err=%d)\n", filename, err); return NULL; } while(1) { pthread_wait_np( &overruns_r ); if(sgnl) err = a4l_sync_write(&dsc, idx_subd, CHAN(idx_chan), 0, &valueUp, scan_size); else err = a4l_sync_write(&dsc, idx_subd, CHAN(idx_chan), 0, &valueDown, scan_size); if (err < 0) { fprintf(stderr, "insn_write: a4l_sync_write failed (err=%d)\n", err); goto out_insn_write; } sgnl = (sgnl + 1) % 2; } out_insn_write: if (dsc.sbdata != NULL) free(dsc.sbdata); a4l_close(&dsc); return NULL; } int main(void) { mlockall( MCL_CURRENT | MCL_FUTURE ); pthread_t thread; int rc, i; int prio = 99; struct timespec rqtp, rmtp; rqtp.tv_sec = 0; rqtp.tv_nsec = PERIOD; struct sched_param sparam; sparam.sched_priority = 99; rc = pthread_create(&thread, NULL, TaskCode, NULL); assert(0 == rc); rc = pthread_setschedparam(&thread, SCHED_FIFO, &sparam); assert(0 == rc); rc = clock_gettime( CLOCK_REALTIME, &rmtp ); assert(0 == rc); rmtp.tv_sec = rmtp.tv_sec + DELAI; rc = pthread_make_periodic_np(thread, &rmtp, &rqtp); if(rc == ETIMEDOUT) printf("Début dépassé \n"); else if(rc == ESRCH) printf("Thread invalide \n"); assert(0 == rc); rc = pthread_join(thread, NULL); exit(EXIT_SUCCESS); } 

Je soupçonne fortement (en regardant le planificateur Xenomai) que mon programme entre en mode secondaire. J’ai essayé de supprimer les déclarations “assert” ainsi que les printf pertinents, mais cela n’a pas abouti. Toute idée de comment résoudre ce problème?

    Comme toujours, le diable est dans les détails.

    J’ai activé l’option -Wall dans gcc, qui affiche tous les avertissements. Il s’est avéré que les en-têtes de pthread_ * n’étaient pas chargés correctement, ce qui m’a empêché de constater que le premier argument de pthread_setschedparam était erroné et qu’il était supposé être thread et non & thread.