mirror of https://github.com/joan2937/pigpio
added clock timing test
* pigpio.h/.c: added API function for the test: test duration 50 ms, tolerance 5% * pigpiod: added option '-T' to (de)activate test, default: ON * added independent test program x_pigpio_clock, testing both clocks * amended README * Makefile: added targets 'test' and 'test-really' Signed-off-by: hayati ayguen <h_ayguen@web.de>
This commit is contained in:
parent
bab05ceb97
commit
61bc2f1aff
48
Makefile
48
Makefile
|
@ -25,7 +25,9 @@ OBJ3 = pigpiod_if2.o command.o
|
|||
|
||||
LIB = $(LIB1) $(LIB2) $(LIB3)
|
||||
|
||||
ALL = $(LIB) x_pigpio x_pigpiod_if x_pigpiod_if2 pig2vcd pigpiod pigs
|
||||
TESTS = x_pigpio x_pigpiod_if x_pigpiod_if2 x_pigpio_clock
|
||||
|
||||
ALL = $(LIB) $(TESTS) pig2vcd pigpiod pigs
|
||||
|
||||
LL1 = -L. -lpigpio -pthread -lrt
|
||||
|
||||
|
@ -44,6 +46,47 @@ all: $(ALL)
|
|||
|
||||
lib: $(LIB)
|
||||
|
||||
test: $(TESTS) pigpiod
|
||||
$(warning 'make test' requires 'sudo')
|
||||
@echo "*** WARNING ************************************************"
|
||||
@echo "* *"
|
||||
@echo "* Most tests make extensive use of gpio 25 (pin 22). *"
|
||||
@echo "* Ensure that either nothing or just a LED is connected to *"
|
||||
@echo "* gpio 25 before running any of the tests. *"
|
||||
@echo "* *"
|
||||
@echo "************************************************************"
|
||||
@echo ""
|
||||
@echo "when prepared, run 'sudo make test-really'"
|
||||
@echo ""
|
||||
@echo "killing any running pigpiod"
|
||||
-kill $(shell cat /var/run/pigpio.pid) 2>/dev/null
|
||||
sleep 1
|
||||
@echo ""
|
||||
@echo "running test(s), which don't need any gpio pin"
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpio_clock
|
||||
|
||||
|
||||
test-really: $(TESTS) pigpiod
|
||||
$(warning 'make test' requires 'sudo')
|
||||
echo "************************************************************"
|
||||
echo "* Some tests are statistical in nature and so may on *"
|
||||
echo "* occasion fail. Repeated failures on the same test or *"
|
||||
echo "* many failures in a group of tests indicate a problem. *"
|
||||
echo "************************************************************"
|
||||
@echo "killing any running pigpiod"
|
||||
-kill $(shell cat /var/run/pigpio.pid) 2>/dev/null
|
||||
sleep 1
|
||||
@echo ""
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpio_clock
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpio
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./pigpiod
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpiod_if # test the C I/F to the pigpio daemon
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpiod_if2 # test the C I/F to the pigpio daemon
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigpio.py # test the Python I/F to the pigpio daemon
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pigs # test the socket I/F to the pigpio daemon
|
||||
export LD_LIBRARY_PATH=$$(pwd); ./x_pipe # test the pipe I/F to the pigpio daemon
|
||||
|
||||
|
||||
pigpio.o: pigpio.c pigpio.h command.h custom.cext
|
||||
$(CC) $(CFLAGS) -fpic -c -o pigpio.o pigpio.c
|
||||
|
||||
|
@ -65,6 +108,9 @@ x_pigpiod_if: x_pigpiod_if.o $(LIB2)
|
|||
x_pigpiod_if2: x_pigpiod_if2.o $(LIB3)
|
||||
$(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL3)
|
||||
|
||||
x_pigpio_clock: x_pigpio_clock.o $(LIB1)
|
||||
$(CC) -o x_pigpio_clock x_pigpio_clock.o $(LL1)
|
||||
|
||||
pigpiod: pigpiod.o $(LIB1)
|
||||
$(CC) -o pigpiod pigpiod.o $(LL1)
|
||||
$(STRIP) pigpiod
|
||||
|
|
13
README
13
README
|
@ -15,7 +15,15 @@ Enter the following two commands (in this order)
|
|||
make
|
||||
sudo make install
|
||||
|
||||
This will install
|
||||
|
||||
Optionally, enter following command(s) after 'make'
|
||||
|
||||
sudo make test
|
||||
sudo make test-really
|
||||
|
||||
|
||||
|
||||
The first two commands will install
|
||||
|
||||
o the library (libpigpio.so) in /usr/local/lib
|
||||
o the library (libpigpiod_if.so) in /usr/local/lib
|
||||
|
@ -43,8 +51,9 @@ TEST (optional)
|
|||
* many failures in a group of tests indicate a problem. *
|
||||
************************************************************
|
||||
|
||||
To test the library do
|
||||
To test the installed library do
|
||||
|
||||
sudo ./x_pigpio_clock
|
||||
sudo ./x_pigpio
|
||||
|
||||
To test the pigpio daemon do
|
||||
|
|
55
pigpio.c
55
pigpio.c
|
@ -9688,6 +9688,61 @@ int gpioWaveTxStart(unsigned wave_mode)
|
|||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpioTestClockTiming(unsigned duration_millis, float *ratio)
|
||||
{
|
||||
gpioPulse_t pulse[2];
|
||||
uint32_t t0, t1, diffTick, expectedDelta;
|
||||
int k, ret, wave_id;
|
||||
float local_ratio;
|
||||
|
||||
if (ratio)
|
||||
*ratio = 0.0F;
|
||||
|
||||
CHECK_INITED;
|
||||
|
||||
gpioWaveClear();
|
||||
|
||||
for ( k = 0; k < 2; ++k ) {
|
||||
pulse[k].gpioOn = 0;
|
||||
pulse[k].gpioOff = 0;
|
||||
pulse[k].usDelay = 500U * duration_millis;
|
||||
}
|
||||
|
||||
ret = gpioWaveAddNew();
|
||||
if (ret)
|
||||
SOFT_ERROR(ret, "error at gpioWaveAddNew() in gpioTestClockTiming()");
|
||||
|
||||
ret = gpioWaveAddGeneric(2, pulse);
|
||||
if (ret != 2)
|
||||
SOFT_ERROR(ret, "error at gpioWaveAddGeneric() in gpioTestClockTiming()");
|
||||
|
||||
wave_id = gpioWaveCreate();
|
||||
if (wave_id < 0)
|
||||
SOFT_ERROR(wave_id, "error at gpioWaveCreate() in gpioTestClockTiming()");
|
||||
|
||||
ret = gpioWaveTxSend(wave_id, PI_WAVE_MODE_ONE_SHOT );
|
||||
if (ret <= 0)
|
||||
SOFT_ERROR(ret, "error at gpioWaveTxSend() in gpioTestClockTiming()");
|
||||
|
||||
t0 = gpioTick();
|
||||
while ( gpioWaveTxBusy() )
|
||||
gpioDelay(500);
|
||||
t1 = gpioTick();
|
||||
|
||||
gpioWaveClear();
|
||||
|
||||
diffTick = t1 - t0;
|
||||
expectedDelta = 2 * pulse[0].usDelay;
|
||||
|
||||
local_ratio = (float)(diffTick) / (float)(expectedDelta);
|
||||
if (ratio)
|
||||
*ratio = local_ratio;
|
||||
return ( (1.0F - PI_DEFAULT_CLK_TEST_TOLERANCE) < local_ratio
|
||||
&& (1.0F + PI_DEFAULT_CLK_TEST_TOLERANCE) > local_ratio ) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)
|
||||
{
|
||||
rawCbs_t *p=NULL;
|
||||
|
|
12
pigpio.h
12
pigpio.h
|
@ -2000,6 +2000,15 @@ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
|
|||
D*/
|
||||
|
||||
|
||||
/*F*/
|
||||
int gpioTestClockTiming(unsigned duration_millis, float *ratio);
|
||||
/*D
|
||||
This functions tests clock timing - as used e.g. in [*gpioWaveTxSend*].
|
||||
|
||||
Returns 0 if OK, negative values indicate error.
|
||||
On Success, the measured ratio is written into the pointer argument.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode);
|
||||
/*D
|
||||
|
@ -6481,6 +6490,9 @@ after this command is issued.
|
|||
#define PI_DEFAULT_BUFFER_MILLIS 120
|
||||
#define PI_DEFAULT_CLK_MICROS 5
|
||||
#define PI_DEFAULT_CLK_PERIPHERAL PI_CLOCK_PCM
|
||||
#define PI_DEFAULT_CLK_TEST_PERIPHERAL 1
|
||||
#define PI_DEFAULT_CLK_TEST_DURATION_MS 50
|
||||
#define PI_DEFAULT_CLK_TEST_TOLERANCE 0.05
|
||||
#define PI_DEFAULT_IF_FLAGS 0
|
||||
#define PI_DEFAULT_FOREGROUND 0
|
||||
#define PI_DEFAULT_DMA_CHANNEL 14
|
||||
|
|
47
pigpiod.c
47
pigpiod.c
|
@ -54,6 +54,7 @@ This program starts the pigpio library as a daemon.
|
|||
static unsigned bufferSizeMilliseconds = PI_DEFAULT_BUFFER_MILLIS;
|
||||
static unsigned clockMicros = PI_DEFAULT_CLK_MICROS;
|
||||
static unsigned clockPeripheral = PI_DEFAULT_CLK_PERIPHERAL;
|
||||
static unsigned testClockPeripheral = PI_DEFAULT_CLK_TEST_PERIPHERAL;
|
||||
static unsigned ifFlags = PI_DEFAULT_IF_FLAGS;
|
||||
static int foreground = PI_DEFAULT_FOREGROUND;
|
||||
static unsigned DMAprimaryChannel = PI_DEFAULT_DMA_NOT_SET;
|
||||
|
@ -107,6 +108,7 @@ void usage()
|
|||
" -p value, socket port, 1024-32000, default 8888\n" \
|
||||
" -s value, sample rate, 1, 2, 4, 5, 8, or 10, default 5\n" \
|
||||
" -t value, clock peripheral, 0=PWM 1=PCM, default PCM\n" \
|
||||
" -T value test clock peripheral, 0=OFF 1=ON, default ON\n" \
|
||||
" -v, -V, display pigpio version and exit\n" \
|
||||
" -x mask, GPIO which may be updated, default board GPIO\n" \
|
||||
"EXAMPLE\n" \
|
||||
|
@ -163,7 +165,7 @@ static void initOpts(int argc, char *argv[])
|
|||
uint32_t addr;
|
||||
int64_t mask;
|
||||
|
||||
while ((opt = getopt(argc, argv, "a:b:c:d:e:fgkln:mp:s:t:x:vV")) != -1)
|
||||
while ((opt = getopt(argc, argv, "a:b:c:d:e:fgkln:mp:s:t:T:x:vV")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
@ -263,6 +265,13 @@ static void initOpts(int argc, char *argv[])
|
|||
else fatal("invalid -t option (%d)", i);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
i = getNum(optarg, &err);
|
||||
if ((i >= 0) && (i <= 1))
|
||||
testClockPeripheral = i;
|
||||
else fatal("invalid -T option (%d)", i);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
case 'V':
|
||||
printf("%d\n", PIGPIO_VERSION);
|
||||
|
@ -304,15 +313,45 @@ void terminate(int signum)
|
|||
}
|
||||
|
||||
|
||||
static void clockSkewWarning(int retClockTest, float ratio)
|
||||
{
|
||||
if (retClockTest < 0)
|
||||
fprintf(stderr, "gpioTestClockTiming() measurement failed!\n");
|
||||
else if (retClockTest) {
|
||||
fprintf(stderr, "*** WARNING ***: %s clock is skewed! measured clock ratio is %.3f\n"
|
||||
, (clockPeripheral ? "PCM":"PWM"), ratio);
|
||||
if (clockPeripheral)
|
||||
fprintf(stderr, "PCM clock might interfere with sound output. try using PWM clock (option '-t 0')\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pid_t pid;
|
||||
int flags;
|
||||
int flags, retClockTest = 0;
|
||||
float ratio = 1.0F;
|
||||
|
||||
/* check command line parameters */
|
||||
|
||||
initOpts(argc, argv);
|
||||
|
||||
if (testClockPeripheral) {
|
||||
|
||||
/* partially configure library and start library for testing */
|
||||
gpioCfgBufferSize(bufferSizeMilliseconds);
|
||||
gpioCfgClock(clockMicros, clockPeripheral, 0);
|
||||
gpioCfgDMAchannels(DMAprimaryChannel, DMAsecondaryChannel);
|
||||
if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");
|
||||
|
||||
/* do the test - before forking, that stderr output isn't from daemon process */
|
||||
retClockTest = gpioTestClockTiming( PI_DEFAULT_CLK_TEST_DURATION_MS, &ratio );
|
||||
clockSkewWarning(retClockTest, ratio);
|
||||
|
||||
/* free all resources */
|
||||
gpioTerminate();
|
||||
}
|
||||
|
||||
if (!foreground) {
|
||||
/* Fork off the parent process */
|
||||
|
||||
|
@ -393,6 +432,10 @@ int main(int argc, char **argv)
|
|||
gpioSetSignalFunc(SIGHUP, terminate);
|
||||
gpioSetSignalFunc(SIGTERM, terminate);
|
||||
|
||||
/* repeat clock warning for log */
|
||||
if (testClockPeripheral)
|
||||
clockSkewWarning(retClockTest, ratio);
|
||||
|
||||
/* sleep forever */
|
||||
|
||||
while (1)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* use local header for testing */
|
||||
#include "pigpio.h"
|
||||
|
||||
#define DELAY_MS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret, testClock;
|
||||
float ratio;
|
||||
unsigned cfgMicros, cfgPeripheral;
|
||||
|
||||
testClock = -1; /* -1: test both configurations; 0: test PWM; 1: test PCM */
|
||||
|
||||
if ( 1 < argc ) {
|
||||
if (!strcmp(argv[1], "pcm"))
|
||||
testClock = 1;
|
||||
else if (!strcmp(argv[1], "pwm"))
|
||||
testClock = 0;
|
||||
else
|
||||
testClock = atoi(argv[1]);
|
||||
if (testClock)
|
||||
testClock = 1;
|
||||
}
|
||||
|
||||
for ( cfgPeripheral = 0; cfgPeripheral < 2; ++cfgPeripheral ) {
|
||||
if ( !( testClock == -1 || testClock == cfgPeripheral ) )
|
||||
continue;
|
||||
|
||||
cfgMicros = 5;
|
||||
fprintf(stdout, "testing %s clock\n", (cfgPeripheral ? "PCM" : "PWM") );
|
||||
|
||||
gpioCfgClock(cfgMicros, cfgPeripheral, 0);
|
||||
if (gpioInitialise() < 0)
|
||||
{
|
||||
fprintf(stderr, "pigpio initialisation failed.\n");
|
||||
return (cfgPeripheral+1)*10;
|
||||
}
|
||||
|
||||
ret = gpioTestClockTiming(DELAY_MS, &ratio);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error at gpioTestClockTiming()\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
gpioTerminate();
|
||||
|
||||
fprintf(stdout, " measured clock ratio = %.3f\n", ratio);
|
||||
fprintf(stdout, " %s: clock is %s\n", (ret ? "FAIL" : "PASS" ), (ret ? "skewed!" : "OK" ));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue