mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-05 04:05:54 +02:00
Made communication with CNTR board more robust. Added documentation.
- cntr/README: description of the counter board and its application - cntr/fw/common/crc32.c: variant of CRC32-IEEE802.3 shared by firmware and measurement application - cntr/fw/cntr/ep0.c (my_setup), cntr/tools/cntr/cntr.c (get_sample): protect the counter value with a CRC and an one's complement copy - cntr/fw/include/cntr/ep0.h: oops, wasn't checked into repository - cntr/tools/cntr/cntr.c: added section titles - cntr/tools/cntr/cntr.c (measure): show communication statistics at the end - cntr/tools/cntr/cntr.c (measure, usage, main): new option -d to enable reporting of communication errors - cntr/tools/cntr/cntr.c (set_stop, measure): let user stop measurement with SIGINT - cntr/tools/cntr/cntr.c (measure): get multiple "first samples" and keep the one with the shortest round-trip time - cntr/tools/cntr/cntr.c (measure): changed unit "ppk" (1/1000) to percent (1/100) - cntr/tools/cntr/cntr.c (usage, main): command-line argument is now the accuracy goal, while the system clock deviation is set with the new option -c - TODO: some more things to do
This commit is contained in:
parent
4d49921b9b
commit
c7303e4ac1
22
TODO
22
TODO
@ -105,10 +105,30 @@ Things not done yet
|
|||||||
|
|
||||||
- measure duty cycle
|
- measure duty cycle
|
||||||
|
|
||||||
- display activity on clock input and duty cycle
|
- use the LED to display activity on clock input and duty cycle
|
||||||
|
|
||||||
- consider using a comparator and a DAC to allow for programmable logic levels
|
- consider using a comparator and a DAC to allow for programmable logic levels
|
||||||
|
|
||||||
- evaluate termination resistance
|
- evaluate termination resistance
|
||||||
|
|
||||||
- document circuit design
|
- document circuit design
|
||||||
|
|
||||||
|
- record beats between 16 bit counter polls and use them for the estimate
|
||||||
|
of lost cycles (2*1 is way too optimistic)
|
||||||
|
|
||||||
|
- include system clock resolution in accuracy calculation
|
||||||
|
|
||||||
|
- consider running shorter sliding windows to estimate drift
|
||||||
|
|
||||||
|
- consider detecting unusual half-periods
|
||||||
|
|
||||||
|
- consider using a reversed USB connector, to avoid having to cross D+/D- and,
|
||||||
|
worse, VBUS and GND
|
||||||
|
|
||||||
|
- test input performance by counting a source that emits a known number of
|
||||||
|
cycles
|
||||||
|
|
||||||
|
- consider using historical margins to sanity-check the current margin (if any
|
||||||
|
old.max < curr.min or old.min > curr.max, we have a problem) and to further
|
||||||
|
narrow the effective margin, thus achieving faster convergence. We would have
|
||||||
|
to consider temperature drift of the frequency source in this case.
|
||||||
|
66
cntr/README
Normal file
66
cntr/README
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
Arbitrary-precision counter
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Theory of operation
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The arbitrary-precision counter counts clock cycles of a frequency
|
||||||
|
source that is assumed to be free from drift. It compares the count
|
||||||
|
with the host's system clock. If the system clock is synchronized with
|
||||||
|
an accurate NTP reference, measurements with arbitrarily high accuracy
|
||||||
|
can be obtained.
|
||||||
|
|
||||||
|
In practice, this is limited by the the frequency source's drift and
|
||||||
|
the time one is willing to wait. If NTP maintains the system time
|
||||||
|
with an accuracy of +/- 100 ms, obtaining measurements with an
|
||||||
|
accuracy of +/- 1 ppm would take about 28 hours.
|
||||||
|
|
||||||
|
Additional error sources, such as the round-trip time when requesting
|
||||||
|
a sample from the microcontroller, are also considered in the accuracy
|
||||||
|
calculation.
|
||||||
|
|
||||||
|
The counter consists of a board based on a C8051F320 microcontroller
|
||||||
|
and the control software on the host. The microcontroller counts
|
||||||
|
events in a free-running 16 bit counter that is regularly read and
|
||||||
|
extended to 32 bits. The 32 bit counter is periodically queried by
|
||||||
|
the host.
|
||||||
|
|
||||||
|
The microcontroller's counter can count at a frequency of up to 3 MHz.
|
||||||
|
(SYSCLK/4)
|
||||||
|
|
||||||
|
In order to protect against transmission errors not detected by USB's
|
||||||
|
CRC, which are occur relatively often, each packet is protected by a
|
||||||
|
CRC-32 and an inverted copy of the payload. Corrupted packets are
|
||||||
|
rejected by the host.
|
||||||
|
|
||||||
|
The 32 bit counter wraps around at most once very 21.8 ms. The 32 bit
|
||||||
|
counter wraps around at most every 1431 s. The host extends the 32 bit
|
||||||
|
counter to 64 bits, and calculates frequency and accuracy from the
|
||||||
|
count and the run time of the measurement application.
|
||||||
|
|
||||||
|
|
||||||
|
Performing a measurement
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
To perform a measurement, connect the CNTR board's probe input to the
|
||||||
|
clock source and then run the "cntr" application on the host. An
|
||||||
|
accuracy goal (in ppm) can be specified on the command line (see
|
||||||
|
below).
|
||||||
|
|
||||||
|
The host polls the microcontroller every 100 ms and displays the run
|
||||||
|
time (in seconds), the measured frequency, and the accuracy achieved
|
||||||
|
so far.
|
||||||
|
|
||||||
|
Measurements can be stopped by pressing ^C or by specifying an
|
||||||
|
accuracy goal. At the end, the total number of events counted and
|
||||||
|
communication statistics are displayed.
|
||||||
|
|
||||||
|
|
||||||
|
Updating the firmware
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The protocol revision and the build date of the firmware of the CNTR
|
||||||
|
board can be queried with "cntr -i".
|
||||||
|
|
||||||
|
To update the firmware, run
|
||||||
|
cntr -r && sleep 1 && dfu-util -d 0x20b7:0xcb72 -D cntr.bin
|
@ -22,7 +22,6 @@
|
|||||||
#include "cntr/ep0.h"
|
#include "cntr/ep0.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
#define debug(...)
|
#define debug(...)
|
||||||
#define error(...)
|
#define error(...)
|
||||||
|
|
||||||
@ -61,9 +60,13 @@ static __xdata uint8_t buf[128];
|
|||||||
#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
|
#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
|
||||||
|
|
||||||
|
|
||||||
|
/* crc32() */
|
||||||
|
#include "cntr/crc32.c"
|
||||||
|
|
||||||
|
|
||||||
static __bit my_setup(struct setup_request *setup) __reentrant
|
static __bit my_setup(struct setup_request *setup) __reentrant
|
||||||
{
|
{
|
||||||
unsigned tmp;
|
uint32_t tmp;
|
||||||
uint8_t size, i;
|
uint8_t size, i;
|
||||||
|
|
||||||
switch (setup->bmRequestType | setup->bRequest << 8) {
|
switch (setup->bmRequestType | setup->bRequest << 8) {
|
||||||
@ -102,7 +105,18 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
buf[1] = cntr[1];
|
buf[1] = cntr[1];
|
||||||
buf[2] = cntr[2];
|
buf[2] = cntr[2];
|
||||||
buf[3] = cntr[3];
|
buf[3] = cntr[3];
|
||||||
usb_send(&ep0, buf, 4, NULL, NULL);
|
tmp = (uint32_t) buf[0] | ((uint32_t) buf[1] << 8) |
|
||||||
|
((uint32_t) buf[2] << 16) | ((uint32_t) buf[3] << 24);
|
||||||
|
tmp = crc32(tmp, 0xffffffff);
|
||||||
|
buf[4] = tmp;
|
||||||
|
buf[5] = tmp >> 8;
|
||||||
|
buf[6] = tmp >> 16;
|
||||||
|
buf[7] = tmp >> 24;
|
||||||
|
buf[8] = ~cntr[0];
|
||||||
|
buf[9] = ~cntr[1];
|
||||||
|
buf[10] = ~cntr[2];
|
||||||
|
buf[11] = ~cntr[3];
|
||||||
|
usb_send(&ep0, buf, 12, NULL, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
62
cntr/fw/include/cntr/ep0.h
Normal file
62
cntr/fw/include/cntr/ep0.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* include/cntr/ep0.h - EP0 extension protocol
|
||||||
|
*
|
||||||
|
* Written 2008-2010 by Werner Almesberger
|
||||||
|
* Copyright 2008-2010 Werner Almesberger
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef EP0_H
|
||||||
|
#define EP0_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Direction bRequest wValue wIndex wLength
|
||||||
|
*
|
||||||
|
* ->host CNTR_ID - - 3
|
||||||
|
* ->host CNTR_BUILD - - #bytes
|
||||||
|
* host-> CNTR_RESET - - 0
|
||||||
|
*
|
||||||
|
* ->host CNTR_READ - 0 12
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EP0 protocol:
|
||||||
|
*
|
||||||
|
* 0.0 initial release
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EP0CNTR_MAJOR 0 /* EP0 protocol, major revision */
|
||||||
|
#define EP0CNTR_MINOR 0 /* EP0 protocol, minor revision */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bmRequestType:
|
||||||
|
*
|
||||||
|
* D7 D6..5 D4...0
|
||||||
|
* | | |
|
||||||
|
* direction (0 = host->dev)
|
||||||
|
* type (2 = vendor)
|
||||||
|
* recipient (0 = device)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define CNTR_TO_DEV(req) (0x40 | (req) << 8)
|
||||||
|
#define CNTR_FROM_DEV(req) (0xc0 | (req) << 8)
|
||||||
|
|
||||||
|
|
||||||
|
enum cntr_requests {
|
||||||
|
CNTR_ID = 0x00,
|
||||||
|
CNTR_BUILD,
|
||||||
|
CNTR_RESET,
|
||||||
|
CNTR_READ = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void ep0_init(void);
|
||||||
|
|
||||||
|
#endif /* !EP0_H */
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
@ -28,6 +29,20 @@
|
|||||||
#define BUF_SIZE 256
|
#define BUF_SIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
static int debug = 0;
|
||||||
|
static int verbose = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- CRC, shared with firmware ----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* crc32() */
|
||||||
|
|
||||||
|
#include "cntr/crc32.c"
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- reset ------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static void reset_cntr(usb_dev_handle *dev)
|
static void reset_cntr(usb_dev_handle *dev)
|
||||||
{
|
{
|
||||||
@ -41,6 +56,9 @@ static void reset_cntr(usb_dev_handle *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- identify ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static void identify_cntr(usb_dev_handle *dev)
|
static void identify_cntr(usb_dev_handle *dev)
|
||||||
{
|
{
|
||||||
const struct usb_device *device = usb_device(dev);
|
const struct usb_device *device = usb_device(dev);
|
||||||
@ -71,19 +89,32 @@ static void identify_cntr(usb_dev_handle *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- measurements ------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
struct sample {
|
struct sample {
|
||||||
double t0, t1;
|
double t0, t1;
|
||||||
uint64_t cntr;
|
uint64_t cntr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void get_sample(usb_dev_handle *dev, struct sample *s)
|
static unsigned packets = 0, crc_errors = 0, inv_errors = 0;
|
||||||
|
static volatile int stop = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void set_stop(int sig)
|
||||||
|
{
|
||||||
|
stop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_sample(usb_dev_handle *dev, struct sample *s)
|
||||||
{
|
{
|
||||||
static uint32_t last = 0, high = 0;
|
static uint32_t last = 0, high = 0;
|
||||||
struct timeval t0, t1;
|
struct timeval t0, t1;
|
||||||
int res;
|
int res, bad;
|
||||||
uint8_t buf[4];
|
uint8_t buf[12];
|
||||||
uint32_t cntr;
|
uint32_t cntr, inv, crc, expect;
|
||||||
|
|
||||||
gettimeofday(&t0, NULL);
|
gettimeofday(&t0, NULL);
|
||||||
res = usb_control_msg(dev, FROM_DEV, CNTR_READ, 0, 0,
|
res = usb_control_msg(dev, FROM_DEV, CNTR_READ, 0, 0,
|
||||||
@ -93,27 +124,73 @@ static void get_sample(usb_dev_handle *dev, struct sample *s)
|
|||||||
fprintf(stderr, "CNTR_READ: %s\n", usb_strerror());
|
fprintf(stderr, "CNTR_READ: %s\n", usb_strerror());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
packets++;
|
||||||
cntr = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
cntr = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||||
|
crc = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
|
||||||
|
inv = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
|
||||||
|
expect = crc32(cntr, ~0);
|
||||||
|
bad = 0;
|
||||||
|
if (crc != expect) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "\nCRC error (count 0x%08x->0x%08x "
|
||||||
|
"CRC 0x%08x/0x%08x)\n",
|
||||||
|
(unsigned) last, (unsigned) cntr, (unsigned) crc,
|
||||||
|
(unsigned) expect);
|
||||||
|
bad = 1;
|
||||||
|
crc_errors++;
|
||||||
|
}
|
||||||
|
if (cntr != (inv ^ 0xffffffff)) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ninverted counter error (0x%08x->0x%08x, "
|
||||||
|
"inv 0x%08x)\n",
|
||||||
|
(unsigned) last, (unsigned) cntr, (unsigned) inv);
|
||||||
|
bad = 1;
|
||||||
|
inv_errors++;
|
||||||
|
}
|
||||||
|
if (bad)
|
||||||
|
return 0;
|
||||||
if (last > cntr)
|
if (last > cntr)
|
||||||
high++;
|
high++;
|
||||||
last = cntr;
|
last = cntr;
|
||||||
s->t0 = t0.tv_sec+t0.tv_usec/1000000.0;
|
s->t0 = t0.tv_sec+t0.tv_usec/1000000.0;
|
||||||
s->t1 = t1.tv_sec+t1.tv_usec/1000000.0;
|
s->t1 = t1.tv_sec+t1.tv_usec/1000000.0;
|
||||||
s->cntr = (uint64_t) high << 32 | cntr;
|
s->cntr = (uint64_t) high << 32 | cntr;
|
||||||
|
if (debug)
|
||||||
|
printf("0x%llx 0x%lx\n",
|
||||||
|
(unsigned long long ) s->cntr, (unsigned long) cntr);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void measure(usb_dev_handle *dev, double clock_dev_s)
|
static void measure(usb_dev_handle *dev, double clock_dev_s, double error_goal)
|
||||||
{
|
{
|
||||||
struct sample start, now;
|
struct sample start, now;
|
||||||
uint64_t dc;
|
uint64_t dc;
|
||||||
double dt, f, error;
|
double dt, f, error;
|
||||||
char *f_exp, error_exp;
|
char *f_exp, *error_exp;
|
||||||
|
int i;
|
||||||
|
|
||||||
get_sample(dev, &start);
|
signal(SIGINT, set_stop);
|
||||||
while (1) {
|
|
||||||
|
/*
|
||||||
|
* The round-trip time for getting the first sample is one of the
|
||||||
|
* error terms. The smaller we can make it, the better. Thus, we try a
|
||||||
|
* few times to improve our first result.
|
||||||
|
*/
|
||||||
|
while (!get_sample(dev, &start));
|
||||||
|
for (i = 0; i != 10; i++) {
|
||||||
|
while (!get_sample(dev, &now));
|
||||||
|
if (now.t1-now.t0 < start.t1-start.t0) {
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "improve %g -> %g\n",
|
||||||
|
start.t1-start.t0, now.t1-now.t0);
|
||||||
|
start = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!stop) {
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
get_sample(dev, &now);
|
while (!get_sample(dev, &now));
|
||||||
dc = now.cntr-start.cntr;
|
dc = now.cntr-start.cntr;
|
||||||
dt = now.t0-start.t0;
|
dt = now.t0-start.t0;
|
||||||
f = dc/dt;
|
f = dc/dt;
|
||||||
@ -133,40 +210,54 @@ static void measure(usb_dev_handle *dev, double clock_dev_s)
|
|||||||
error += (start.t1-start.t0)/dt;/* start sample read */
|
error += (start.t1-start.t0)/dt;/* start sample read */
|
||||||
error += (now.t1-now.t0)/dt; /* last sample read */
|
error += (now.t1-now.t0)/dt; /* last sample read */
|
||||||
error += clock_dev_s/dt; /* system clock deviation */
|
error += clock_dev_s/dt; /* system clock deviation */
|
||||||
if (error > 1) {
|
if (error >= 1) {
|
||||||
printf("\r(wait) ");
|
printf("\r(wait) ");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (dc && error <= error_goal)
|
||||||
|
stop = 1;
|
||||||
|
|
||||||
error_exp = 'k';
|
error_exp = "%";
|
||||||
error *= 1000.0; /* ppm */
|
error *= 100.0;
|
||||||
if (error < 1.0) {
|
if (error < 0.1) {
|
||||||
error_exp = 'm'; /* ppm */
|
error_exp = " ppm";
|
||||||
error *= 1000.0;
|
error *= 10000.0;
|
||||||
}
|
if (error < 1.0) {
|
||||||
if (error < 1.0) {
|
error_exp = " ppb";
|
||||||
error_exp = 'b'; /* ppb */
|
error *= 1000.0;
|
||||||
error *= 1000.0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\r%6.1f %1.9f %sHz %3.3f pp%c ",
|
printf("\r%6.1f %1.9f %sHz %3.3f%s ",
|
||||||
dt, f, f_exp, error, error_exp);
|
dt, f, f_exp, error, error_exp);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
printf(
|
||||||
|
"\n%llu counts, %u packets, %u CRC error%s, %u invert error%s\n",
|
||||||
|
(unsigned long long) (now.cntr-start.cntr),
|
||||||
|
packets, crc_errors, crc_errors == 1 ? "" : "s",
|
||||||
|
inv_errors, inv_errors == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- command-line parsing ---------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s [clock_dev_s]\n"
|
"usage: %s [-c clock_dev] [-d] [-v] [accuracy_ppm]\n"
|
||||||
"%6s %s -i\n"
|
"%6s %s -i\n"
|
||||||
"%6s %s r\n\n"
|
"%6s %s -r\n\n"
|
||||||
" clock_dev_s is the maximum deviation of the system clock, in seconds\n"
|
" accuracy_ppm stop when specified accuracy is reached (default: never\n"
|
||||||
" (default: %g s)\n"
|
" stop)\n"
|
||||||
|
" -c clock_dev maximum deviation of the system clock, in seconds\n"
|
||||||
|
" (default: %g s)\n"
|
||||||
|
" -d debug mode. Print counter values.\n"
|
||||||
" -i identify the CNTR board\n"
|
" -i identify the CNTR board\n"
|
||||||
" -r reset the CNTR board\n"
|
" -r reset the CNTR board\n"
|
||||||
|
" -v verbose reporting of communication errors\n"
|
||||||
, name, "", name, "", name, DEFAULT_CLOCK_DEV_S);
|
, name, "", name, "", name, DEFAULT_CLOCK_DEV_S);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -177,10 +268,19 @@ int main(int argc, char *const *argv)
|
|||||||
usb_dev_handle *dev;
|
usb_dev_handle *dev;
|
||||||
int c, identify = 0, reset = 0;
|
int c, identify = 0, reset = 0;
|
||||||
double clock_dev_s = DEFAULT_CLOCK_DEV_S;
|
double clock_dev_s = DEFAULT_CLOCK_DEV_S;
|
||||||
|
double error_goal = 0;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "ir")) != EOF)
|
while ((c = getopt(argc, argv, "c:dir")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'c':
|
||||||
|
clock_dev_s = strtod(argv[optind], &end);
|
||||||
|
if (*end)
|
||||||
|
usage(*argv);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
debug = 1;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
identify = 1;
|
identify = 1;
|
||||||
break;
|
break;
|
||||||
@ -190,12 +290,14 @@ int main(int argc, char *const *argv)
|
|||||||
default:
|
default:
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
}
|
}
|
||||||
|
if (identify && reset)
|
||||||
|
usage(*argv);
|
||||||
|
|
||||||
switch (argc-optind) {
|
switch (argc-optind) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
clock_dev_s = strtod(argv[optind], &end);
|
error_goal = strtod(argv[optind], &end)/1000000.0;
|
||||||
if (*end)
|
if (*end)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
break;
|
break;
|
||||||
@ -219,7 +321,7 @@ int main(int argc, char *const *argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
measure(dev, clock_dev_s);
|
measure(dev, clock_dev_s, error_goal);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user