Приветствую!
Разрабатываю модуль на C для получения измерений с аналоговых входов L-502. Столкнулся со следующей проблемой: метод X502_Recv всегда выполняется около 4х секунд, вне зависимости от частоты АЦП и количества запрашиваемых отсчетов. Если передать таймаут меньше 4х секунд, то стабильно ничего не возвращается.
В целях дебага написал простой код, который с интервалом в 1 секунду вызывает X502_GetRecvReadyCount, и также получил весьма странные результаты.
Код:
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <x502api.h>
#include <l502api.h>
uint32_t calc_delay(struct timeval *start, struct timeval *stop) {
return (stop->tv_sec - start->tv_sec) * 1000000 + stop->tv_usec - start->tv_usec;
}
int main(int argc, char** argv) {
setlocale(LC_NUMERIC, "");
struct timeval start, stop;
uint64_t delta_us;
int32_t err;
// Получаем версию библиотеки
uint32_t ver = X502_GetLibraryVersion();
printf("Library version: %d.%d.%d\n", (ver >> 24)&0xFF, (ver>>16)&0xFF, (ver>>8)&0xFF);
// Получаем количество подключенных устройств по интерфейсу PCI
uint32_t devcnt = 0;
L502_GetDevRecordsList(NULL, 0, 0, &devcnt);
printf("Found %d PCI device(s)\n", devcnt);
// Выводим список найденных устройств
if (devcnt == 0) {
return 0;
}
// Выделяем память для массива для сохранения найденного количества записей
t_x502_devrec *devices = NULL;
devices = malloc(devcnt * sizeof(t_x502_devrec));
// Получаем записи о модулях L502
L502_GetDevRecordsList(&devices[0], devcnt, 0, NULL);
for (int i=0; i<devcnt; ++i) {
printf("Device %d: %s (SN: %s, Flags: %x)\n", i, devices[i].devname, devices[i].serial, devices[i].flags);
}
// Устанавливаем соединение
t_x502_hnd dev_hnd = X502_Create();
gettimeofday(&start, NULL);
err = X502_OpenByDevRecord(dev_hnd, &devices[0]);
gettimeofday(&stop, NULL);
printf("X502_OpenByDevRecord took %'d us\n", calc_delay(&start, &stop));
if (err != X502_ERR_OK) {
fprintf(stderr, "Error connecting to device: %s\n", X502_GetErrorString(err));
return 1;
}
printf("Successfully connected to device!\n");
// Освобождение ресурсов действительных записей из списка
X502_FreeDevRecordList(devices, devcnt);
// Очистка памяти самого массива
free(devices);
// Устанавливаем параметры логической таблицы АЦП
err = X502_SetLChannelCount(dev_hnd, 1);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error configuring ADC inputs: %s\n", X502_GetErrorString(err));
return 1;
}
err = X502_SetLChannel(dev_hnd, 0, 0, X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error configuring ADC inputs: %s\n", X502_GetErrorString(err));
return 1;
}
err = X502_SetMode(dev_hnd, X502_MODE_FPGA);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error setting mode: %s\n", X502_GetErrorString(err));
return 1;
}
// Устанавливаем частоту АЦП
double f_adc = 2000.0;
err = X502_SetAdcFreq(dev_hnd, &f_adc, NULL);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error setting ADC frequency: %s\n", X502_GetErrorString(err));
return 1;
}
// Записываем настройки
err = X502_Configure(dev_hnd, 0);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error configuring device: %s\n", X502_GetErrorString(err));
return 1;
}
// Разрешаем синхронные потоки
int streams = X502_STREAM_ADC;
err = X502_StreamsEnable(dev_hnd, streams);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error configuring input streams: %s\n", X502_GetErrorString(err));
return 1;
}
// Начинаем чтение данных
gettimeofday(&start, NULL);
err = X502_StreamsStart(dev_hnd);
gettimeofday(&stop, NULL);
printf("X502_StreamsStart took %'d us\n", calc_delay(&start, &stop));
if (err != X502_ERR_OK) {
fprintf(stderr, "Error during startup: %s\n", X502_GetErrorString(err));
return 1;
}
printf("Measurement started\n");
uint32_t rdy_cnt = 0;
for (int i=0; i < 10; ++i) {
err = X502_GetRecvReadyCount(dev_hnd, &rdy_cnt);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error during GetRecvReadyCount: %s\n", X502_GetErrorString(err));
return 1;
}
printf("ReadyCount: %d\n", rdy_cnt);
sleep(1);
}
gettimeofday(&start, NULL);
err = X502_StreamsStop(dev_hnd);
gettimeofday(&stop, NULL);
printf("X502_StreamsStop took %'d us\n", calc_delay(&start, &stop));
if (err != X502_ERR_OK) {
fprintf(stderr, "Error stopping measurement: %s\n", X502_GetErrorString(err));
return 1;
}
gettimeofday(&start, NULL);
err = X502_Close(dev_hnd);
if (err != X502_ERR_OK) {
fprintf(stderr, "Error closing connection: %s\n", X502_GetErrorString(err));
}
gettimeofday(&stop, NULL);
printf("X502_Close took %'d us\n", calc_delay(&start, &stop));
X502_Free(dev_hnd);
return 0;
}
Возвращает этот код следующее:
Library version: 1.1.34
Found 1 PCI device(s)
Device 0: L502 (SN: , Flags: 800400)
X502_OpenByDevRecord took 5105046 us
Successfully connected to device!
X502_StreamsStart took 1332647 us
Measurement started
ReadyCount: 0
ReadyCount: 0
ReadyCount: 0
ReadyCount: 0
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
X502_StreamsStop took 26249431 us
X502_Close took 26250668 us
Значение 17408 понятно: столько измерений будет выполнено за примерно 4 секунды при 2000Гц. Тот факт, что количество отсчетов далее не меняется, можно объяснить переполнением буфера. Но почему в течение первых 4х секунд буфер пуст, я так и не смог понять.
Попытки установить вручную шаг генерации прерываний при помощи X502_SetStreamStep ни к чему позитивному не привели.
Подскажите пожалуйста, в чем может быть причина такого поведения и куда еще можно покопать?