c linux linux-kernel posix xenomai

El hilo periódico falla en tiempo real en Xenomai



linux linux-kernel (1)

Como siempre, el diablo está en los detalles.

He habilitado la opción -Wall en gcc, que muestra todas las advertencias. Resultó que los encabezados de pthread_ * no se cargaron correctamente, lo que me impidió ver que el primer argumento de pthread_setschedparam era incorrecto, y se suponía que era un hilo y no un hilo.

Estoy creando un hilo periódico que genera una señal cuadrada en una salida analógica. Estoy usando Posix Skin y Analogy de la API de Xenomai.

Probé el rendimiento en tiempo real de mi código usando un osciloscopio y observando la latencia en la señal cuadrada (cuya frecuencia es de 1 kHz). Se supone que debo alcanzar <100us de latencia. Sin embargo, la señal es fuertemente (> latencia de 250us) perturbada por señales de interrupción comunes, como mover el mouse, iniciar un nuevo programa, etc.

Las banderas en mi archivo MAKE se configuran como tales:

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

y este es el código:

#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); }

Sospecho fuertemente (al mirar el programador de Xenomai) que mi programa de alguna manera ingresa al modo secundario. Traté de eliminar las declaraciones "afirmar", así como los printf''s relevantes, pero esto no fue exitoso. ¿Alguna de idea de cómo arreglarlo?