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:
hayati ayguen 2020-03-14 11:29:14 +01:00
parent bab05ceb97
commit 61bc2f1aff
6 changed files with 228 additions and 5 deletions

View File

@ -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
View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)

58
x_pigpio_clock.c Normal file
View File

@ -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;
}