summaryrefslogtreecommitdiffstats
path: root/cli.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-09 07:12:44 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-09 07:12:44 +0100
commit1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4 (patch)
tree42e3705aa8b20fc7f03025cb83ae2f928350174d /cli.c
parentc3812d3569aa98e23953eea323d980912580e659 (diff)
downloadpcitool-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.gz
pcitool-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.bz2
pcitool-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.xz
pcitool-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.zip
Initial support of event streaming in cli
Diffstat (limited to 'cli.c')
-rw-r--r--cli.c221
1 files changed, 194 insertions, 27 deletions
diff --git a/cli.c b/cli.c
index fdfc78f..cfe59dd 100644
--- a/cli.c
+++ b/cli.c
@@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200112L
+#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
@@ -241,14 +242,15 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" -a [fifo|dma]<bits> - Access type and bits per word (default: 32)\n"
" -e <l|b> - Endianess Little/Big (default: host)\n"
" -o <file> - Append output to file (default: stdout)\n"
-" -t <timeout> - Timeout in microseconds\n"
+" -t <timeout|unlimited> - Timeout in microseconds\n"
"\n"
" Event Options:\n"
" --event <evt> - Specifies event for trigger and grab modes\n"
" --data <type> - Data type to request for the events\n"
-" --run-time <us> - Grab/trigger events during the specified time\n"
-" --trigger-rate <tps> - Generate tps triggers per second\n"
-" --trigger-time <us> - Specifies delay between triggers in microseconds\n"
+" --run-time <us> - Limit time to grab/trigger events\n"
+" -t <timeout|unlimited> - Timeout to stop if no events triggered\n"
+" --trigger-rate <tps> - Generate tps triggers per second\n"
+" --trigger-time <us> - Specifies delay between triggers (us)\n"
" -s <num|unlimited> - Number of events to grab and trigger\n"
" --format [type] - Specifies how event data should be stored\n"
" raw - Just write all events sequentially\n"
@@ -1072,19 +1074,41 @@ typedef struct {
pcilib_event_data_type_t data;
FILE *output;
+ pcilib_timeout_t timeout;
size_t run_time;
size_t trigger_time;
+ size_t max_triggers;
+
+ int event_pending; /**< Used to detect that we have read previously triggered event */
+ int trigger_thread_started; /**< Indicates that trigger thread is ready and we can't procced to start event recording */
+ int started; /**< Indicates that recording is started */
int run_flag;
+
+ struct timeval last_frame;
+ size_t trigger_count;
+ size_t frame_count;
+ size_t broken_count;
+
+ struct timeval stop_time;
} GRABContext;
int GrabCallback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) {
-/* int err;
+ int err;
void *data;
size_t size, written;
GRABContext *ctx = (GRABContext*)user;
pcilib_t *handle = ctx->handle;
+
+ gettimeofday(&ctx->last_frame, NULL);
+
+ ctx->event_pending = 0;
+ ctx->frame_count++;
+
+ if (info->flags&PCILIB_EVENT_INFO_FLAG_BROKEN) ctx->broken_count++;
+
+/*
FILE *o = ctx->output;
data = pcilib_get_data(handle, ctx->event, ctx->data, &size);
@@ -1109,47 +1133,171 @@ int raw_data(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event
// printf("%i\n", event_id);
}
+
void *Trigger(void *user) {
+ struct timeval start;
+
GRABContext *ctx = (GRABContext*)user;
+ size_t trigger_time = ctx->trigger_time;
+ size_t max_triggers = ctx->max_triggers;
- pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL);
- usleep(3000);
- pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL);
+ ctx->trigger_thread_started = 1;
+ ctx->event_pending = 1;
+ while (!ctx->started);
+
+ gettimeofday(&start, NULL);
+ do {
+ pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL);
+ if ((++ctx->trigger_count == max_triggers)&&(max_triggers)) break;
+
+ if (trigger_time) {
+ pcilib_add_timeout(&start, trigger_time);
+ if ((ctx->stop_time.tv_sec)&&(pcilib_timecmp(&start, &ctx->stop_time)>0)) break;
+ pcilib_sleep_until_deadline(&start);
+ } else {
+ while ((ctx->event_pending)&&(ctx->run_flag)) usleep(10);
+ ctx->event_pending = 1;
+ }
+ } while (ctx->run_flag);
+
+ ctx->trigger_thread_started = 0;
+
return NULL;
}
-int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, const char *data_type, size_t num, size_t run_time, size_t trigger_time, PARTITION partition, FORMAT format, size_t buffer_size, FILE *ofile) {
+void *Monitor(void *user) {
+ struct timeval deadline;
+
+ GRABContext *ctx = (GRABContext*)user;
+ pcilib_timeout_t timeout = ctx->timeout;
+
+ if (timeout == PCILIB_TIMEOUT_INFINITE) timeout = 0;
+
+// while (!ctx->started);
+
+ if (timeout) {
+ memcpy(&deadline, &ctx->last_frame, sizeof(struct timeval));
+ pcilib_add_timeout(&deadline, timeout);
+ }
+
+ while (ctx->run_flag) {
+ if (timeout) {
+ if (pcilib_calc_time_to_deadline(&deadline) == 0) {
+ memcpy(&deadline, &ctx->last_frame, sizeof(struct timeval));
+ pcilib_add_timeout(&deadline, timeout);
+
+ if (pcilib_calc_time_to_deadline(&deadline) == 0) {
+ pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY);
+ break;
+ }
+ }
+ }
+
+ usleep(100000);
+ }
+
+ return NULL;
+}
+
+int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, const char *data_type, size_t num, size_t run_time, size_t trigger_time, pcilib_timeout_t timeout, PARTITION partition, FORMAT format, size_t buffer_size, FILE *ofile) {
int err;
GRABContext ctx;
void *data = NULL;
size_t size, written;
+ pthread_t monitor_thread;
pthread_t trigger_thread;
+ pthread_attr_t attr;
+ struct sched_param sched;
+
+ struct timeval start, end;
+ pcilib_event_flags_t flags;
ctx.handle = handle;
ctx.output = ofile;
ctx.event = PCILIB_EVENT0;
ctx.run_time = run_time;
- ctx.trigger_time = trigger_time;
+ ctx.timeout = timeout;
+ ctx.frame_count = 0;
+
+ ctx.started = 0;
+ ctx.trigger_thread_started = 0;
ctx.run_flag = 1;
- // ignoring event for now
- pcilib_configure_autostop(handle, 2, 1000000);//PCILIB_TIMEOUT_TRIGGER);
+ memset(&ctx.stop_time, 0, sizeof(struct timeval));
+
+// printf("Limits: %lu %lu %lu\n", num, run_time, timeout);
+ pcilib_configure_autostop(handle, num, run_time);//PCILIB_TIMEOUT_TRIGGER);
pcilib_configure_rawdata_callback(handle, &raw_data, NULL);
+
+ flags = PCILIB_EVENT_FLAGS_DEFAULT;
+ // PCILIB_EVENT_FLAG_RAW_DATA_ONLY
+
+ if (grab_mode&GRAB_MODE_TRIGGER) {
+ if (!trigger_time) {
+ // Otherwise, we will trigger next event after previous one is read
+ if (((grab_mode&GRAB_MODE_GRAB) == 0)&&((flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)==0)) trigger_time = PCILIB_TRIGGER_TIMEOUT;
+ }
+
+ ctx.max_triggers = num;
+ ctx.trigger_count = 0;
+ ctx.trigger_time = trigger_time;
+
+ // We don't really care if RT priority is imposible
+ pthread_attr_init(&attr);
+ if (!pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
+ sched.sched_priority = sched_get_priority_min(SCHED_FIFO);
+ pthread_attr_setschedparam(&attr, &sched);
+ }
+
+ // Start triggering thread and wait until it is schedulled
+ if (pthread_create(&trigger_thread, &attr, Trigger, (void*)&ctx))
+ Error("Error spawning trigger thread");
+
+ while (!ctx.trigger_thread_started) usleep(10);
+ }
+
+ gettimeofday(&start, NULL);
+
+ if (grab_mode&GRAB_MODE_GRAB) {
+ err = pcilib_start(handle, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
+ if (err) Error("Failed to start event engine, error %i", err);
+ }
+
+ ctx.started = 1;
+
+ if (run_time) {
+ ctx.stop_time.tv_usec = start.tv_usec + run_time%1000000;
+ if (ctx.stop_time.tv_usec > 999999) {
+ ctx.stop_time.tv_usec -= 1000000;
+ __sync_synchronize();
+ ctx.stop_time.tv_sec = start.tv_sec + 1 + run_time / 1000000;
+ } else {
+ __sync_synchronize();
+ ctx.stop_time.tv_sec = start.tv_sec + run_time / 1000000;
+ }
+ }
+
+ memcpy(&ctx.last_frame, &start, sizeof(struct timeval));
+ if (pthread_create(&monitor_thread, NULL, Monitor, (void*)&ctx))
+ Error("Error spawning monitoring thread");
- err = pcilib_start(handle, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
- if (err) Error("Failed to start event engine, error %i", err);
+ if (grab_mode&GRAB_MODE_GRAB) {
+ err = pcilib_stream(handle, &GrabCallback, &ctx);
+ if (err) Error("Error streaming events, error %i", err);
+ }
- if (pthread_create(&trigger_thread, NULL, Trigger, (void*)&ctx))
- Error("Error starting trigger thread");
+ ctx.run_flag = 0;
-// sleep(1);
- err = pcilib_stream(handle, &GrabCallback, &ctx);
- if (err) Error("Error streaming events, error %i", err);
+ if (grab_mode&GRAB_MODE_TRIGGER) {
+ while (ctx.trigger_thread_started) usleep(10);
+ }
- pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT);
+ if (grab_mode&GRAB_MODE_GRAB) {
+ pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT);
+ }
/*
err = pcilib_grab(handle, PCILIB_EVENTS_ALL, &size, &data, PCILIB_TIMEOUT_TRIGGER);
@@ -1157,8 +1305,14 @@ int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, con
Error("Grabbing event is failed");
}
*/
- ctx.run_flag = 0;
- pthread_join(trigger_thread, NULL);
+
+ pthread_join(monitor_thread, NULL);
+
+ if (grab_mode&GRAB_MODE_TRIGGER) {
+ pthread_join(trigger_thread, NULL);
+ }
+
+ // print information
return 0;
}
@@ -1675,6 +1829,7 @@ int main(int argc, char **argv) {
int size_set = 0;
int timeout_set = 0;
+ int run_time_set = 0;
while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) {
extern int optind;
@@ -1887,7 +2042,7 @@ int main(int argc, char **argv) {
if (strcasecmp(optarg, "unlimited"))
Usage(argc, argv, "Invalid size is specified (%s)", optarg);
else
- size = (size_t)-1;
+ size = 0;//(size_t)-1;
size_set = 1;
break;
@@ -1903,7 +2058,10 @@ int main(int argc, char **argv) {
break;
case OPT_TIMEOUT:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1))
- Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
+ if (strcasecmp(optarg, "unlimited"))
+ Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
+ else
+ timeout = PCILIB_TIMEOUT_INFINITE;
timeout_set = 1;
break;
case OPT_OUTPUT:
@@ -1921,7 +2079,11 @@ int main(int argc, char **argv) {
break;
case OPT_RUN_TIME:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &run_time) != 1))
- Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
+ if (strcasecmp(optarg, "unlimited"))
+ Usage(argc, argv, "Invalid run-time is specified (%s)", optarg);
+ else
+ run_time = 0;
+ run_time_set = 1;
break;
case OPT_TRIGGER_TIME:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1))
@@ -1931,7 +2093,7 @@ int main(int argc, char **argv) {
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &ztmp) != 1))
Usage(argc, argv, "Invalid trigger-rate is specified (%s)", optarg);
- trigger_time = 1000000 / ztmp + (1000000 % ztmp)?1:0;
+ trigger_time = (1000000 / ztmp) + ((1000000 % ztmp)?1:0);
break;
case OPT_BUFFER:
if (optarg) num_offset = optarg;
@@ -2099,6 +2261,11 @@ int main(int argc, char **argv) {
else if (!strcmp(fsname, "raw")) partition = PARTITION_RAW;
}
}
+
+ if (!timeout_set) {
+ if (run_time) timeout = PCILIB_TIMEOUT_INFINITE;
+ else timeout = PCILIB_EVENT_TIMEOUT;
+ }
}
if (mode != MODE_GRAB) {
@@ -2167,7 +2334,7 @@ int main(int argc, char **argv) {
pcilib_reset(handle);
break;
case MODE_GRAB:
- TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, partition, format, buffer, ofile);
+ TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, timeout, partition, format, buffer, ofile);
break;
case MODE_LIST_DMA:
ListDMA(handle, fpga_device, model_info);