3

アナログ出力で方形信号を出力する周期的なスレッドを作成しています。Xenomai API の Posix スキンとアナロジーを使用しています。

オシロスコープを使用してコードのリアルタイム パフォーマンスをテストし、方形信号 (周波数は 1kHz) のレイテンシを調べました。100us 未満のレイテンシを達成することになっています。ただし、信号は、マウスの移動、新しいプログラムの開始などの一般的な割り込み信号によって大きく乱されます (>250us レイテンシ)。

私のmakefileのフラグは次のように設定されています:

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

これはコードです:

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

(Xenomai スケジューラを見て) 私のプログラムが何らかの理由でセカンダリ モードに入っているのではないかと強く疑っています。「assert」ステートメントと関連する printf ステートメントを削除しようとしましたが、うまくいきませんでした。それを修正する方法はありますか?

4

1 に答える 1

2

いつものように、悪魔は細部に宿ります。

gcc で -Wall オプションを有効にすると、すべての警告が表示されます。pthread_* のヘッダーが正しく読み込まれていないことが判明したため、pthread_setschedparam の最初の引数が間違っていて、&thread ではなくスレッドであるはずだったことがわかりませんでした。

于 2013-05-22T09:34:17.657 に答える