diff --git a/runtest/sanvito b/runtest/sanvito index 8c470d1b24b5e0547929ef093b1edaae5691d317..defcb5291d72880feac3ecd107139a56a2779fde 100755 --- a/runtest/sanvito +++ b/runtest/sanvito @@ -52,7 +52,7 @@ RS485_12 rs485pingpong -b 32 -r 4 -s 115200 -x 100 -o 1 -d /d RS485_34 rs485pingpong -b 32 -r 4 -s 115200 -x 100 -o 1 -d /dev/ttyUSB3 -n Touch touchmon -z -r /touch_tst_socket Ambient_Proximity ambprox.sh -AnalogIO aio.sh 3; +AnalogIO aio -e 0.4 -r 3 -i 5; Buzzer echo 1 >/sys/class/pwm/pwmchip3/pwm0/enable; usleep 100000; echo 0 >/sys/class/pwm/pwmchip3/pwm0/enable Wait sleep 0.9 diff --git a/testcases/aio/Makefile b/testcases/aio/Makefile index 2c2d4a464451fc38061a64cac3c56b57564fe558..25a49e5fab0bd887cf334428d28d0b02ebe748a0 100755 --- a/testcases/aio/Makefile +++ b/testcases/aio/Makefile @@ -9,11 +9,23 @@ TARGET=aio - top_srcdir ?= $(SYSROOT)/usr -all: +CFLAGS+= -I$(top_srcdir)/include -Wall -Werror +LOADLIBES+= -L$(top_srcdir)/lib -lltp -lm + +SRCS=$(TARGET).c + + +all: $(TARGET) + +$(TARGET): $(SRCS) @mkdir -p ../bin @cp *.sh ../bin/ + @$(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) -o ../bin/$@ clean: + rm -f $(TARGET) *.o *.bak *~ + + + diff --git a/testcases/aio/aio.c b/testcases/aio/aio.c new file mode 100644 index 0000000000000000000000000000000000000000..41ac318f86732f29d37a10e361e7a373d5e63067 --- /dev/null +++ b/testcases/aio/aio.c @@ -0,0 +1,438 @@ +/******************************************************************************/ +/* Copyright (C) 2018 Garz&Fricke GmbH */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* File: aio.c */ +/* */ +/* Description: This is a test for analog io on sanvito expansion board */ +/* */ +/* Total Tests: 1 */ +/* */ +/* Test Name: aio */ +/* */ +/* Test Assertion */ +/* & Strategy: */ +/* */ +/******************************************************************************/ + +/* Standard Include Files */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <math.h> +#include <libgen.h> + +/* Harness Specific Include Files. */ +#include "old/test.h" + +#include "config.h" + +/* Local Defines */ +#if !defined(TRUE) && !defined(FALSE) +#define TRUE 1 +#define FALSE 0 +#endif + +#if LTP_VERSION >= 20140115 +#define Tst_count tst_count +#endif + +/* Extern Global Variables */ +extern int Tst_count; /* counter for tst_xxx routines. */ +extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */ + +/* Global Variables */ +char *TCID = "aio "; /* test program identifier. */ +int TST_TOTAL = 1; /* total number of tests in this file. */ + +FILE *fd_in; /* file descriptor of the input device */ +FILE *fd_out; /* file descriptor of the output device */ +time_t t; /* used for the random generator */ + +double in_scale = 0.0f; /* scale factor for input values (read from IIO) */ +double out_scale = 0.0f; /* scale factor for output values (read from IIO) */ + +char *conf_iio_path = "/sys/bus/iio/devices/"; /* path to IIO devices */ +char *conf_indevice_name = "iio:device0/in_voltage_raw"; /* name of the standard input device */ +char *conf_outdevice_name = "iio:device1/out_voltage0_raw"; /* name of the standard output device */ +double conf_low = 0.0f; /* default minimum test-value */ +double conf_high = 20.0f; /* default maximum test-value */ +double conf_err = 0.4f; /* default error tolerance */ +int conf_dummy_reads = 3; /* default number of dummy reads before evaluating input */ +int conf_quiet = 0; /* quiet mode */ +int conf_verbose = 0; + + + + + +/* Extern Global Functions */ +/******************************************************************************/ +/* */ +/* Function: cleanup */ +/* */ +/* Description: Performs all one time clean up for this test on successful */ +/* completion, premature exit or failure. Closes all temporary */ +/* files, removes all temporary directories exits the test with */ +/* appropriate return code by calling tst_exit() function. */ +/* */ +/* Input: None. */ +/* */ +/* Output: None. */ +/* */ +/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ +/* On success - Exits calling tst_exit(). With '0' return code. */ +/* */ +/******************************************************************************/ +extern void cleanup() +{ + tst_exit(); +} + + +/* Local Functions */ + +/******************************************************************************/ +/* */ +/* Function: getscale */ +/* */ +/* Description: Reads scale value for an IIO device */ +/* */ +/* Input: device_name: name of IIO device to open */ +/* relative to conf_iio_path */ +/* scale_name: name of scale-file for IIO device */ +/* */ +/* Output: None. */ +/* */ +/* Return: On failure - -1.0. */ +/* On success - scale value. */ +/* */ +/******************************************************************************/ +double getscale(char *device_name, char *scale_name) +{ + char *name = NULL; + FILE *fd = NULL; + double scale = -1.0f; + + if (!device_name || !scale_name) { + tst_brkm(TBROK, cleanup, "Invalid IIO device"); + return scale; + } + + /* read input scale value */ + char *temp = strdup(device_name); + if (!temp) + goto error; + + char *iio_dev = dirname(temp); + name = calloc(sizeof(char), strlen(conf_iio_path)+strlen(iio_dev)+strlen(scale_name)+2); + if (!name) + goto error; + + sprintf(name, "%s%s/%s", conf_iio_path, iio_dev, scale_name); + fd = fopen(name, "r"); + if (!fd) + goto error; + + if (1 != fscanf(fd, "%lf", &scale)) + goto error; + +error: + if (fd) + fclose(fd); + if (name) + free(name); + if (temp) + free(temp); + if (scale < 0.0f) + tst_brkm(TBROK, cleanup, + "Unable to open the IIO device %s. Error: %d, %s", + device_name, errno, strerror(errno)); + return scale; +} + +/******************************************************************************/ +/* */ +/* Function: opendevice */ +/* */ +/* Description: Opens an IIO device for reading or writing */ +/* */ +/* Input: device_name: name of IIO device to open */ +/* relative to conf_iio_path */ +/* mode: see fopen() */ +/* */ +/* Output: None. */ +/* */ +/* Return: On failure - returns NULL. */ +/* On success - returns open FILE handle. */ +/* */ +/******************************************************************************/ +FILE *opendevice(char *device_name, const char *mode) +{ + char *name = NULL; + FILE *fd = NULL; + + if (!device_name || !mode) { + tst_brkm(TBROK, cleanup, "Invalid IIO device"); + return fd; + } + + name = calloc(sizeof(char), strlen(conf_iio_path)+strlen(device_name)+1); + if (!name) { + tst_brkm(TBROK, cleanup, + "Unable to open the IIO device %s. Error: %d, %s", + device_name, errno, strerror(errno)); + return fd; + } + sprintf(name, "%s%s", conf_iio_path, device_name); + fd = fopen(name, mode); + if (!fd) { + tst_brkm(TBROK, cleanup, + "Unable to open the IIO device %s. Error: %d, %s", + device_name, errno, strerror(errno)); + return fd; + } + free(name); + return fd; +} + +/******************************************************************************/ +/* */ +/* Function: setup */ +/* */ +/* Description: Performs all one time setup for this test. This function is */ +/* typically used to capture signals, create temporary dirs */ +/* and temporary files that may be used in the course of this */ +/* test. */ +/* */ +/* Input: None. */ +/* */ +/* Output: None. */ +/* */ +/* Return: On failure - Exits by calling cleanup(). */ +/* On success - Nothing. */ +/* */ +/******************************************************************************/ +void setup() +{ + /* read scale values */ + in_scale = getscale(conf_indevice_name, "in_voltage_scale"); + out_scale = getscale(conf_outdevice_name, "out_voltage_scale"); + + /* initialize the random generator */ + time(&t); + srand((int)t); +} + + +/******************************************************************************/ +/* */ +/* Function: test */ +/* */ +/* Description: This function controls the write and the read commands to the */ +/* i2c slave. The procedure is repeated twice as two registers */ +/* are tested. */ +/* */ +/* Input: None. */ +/* */ +/* Output: None. */ +/* */ +/* Return: On failure - returns -1. */ +/* On success - returns 0. */ +/* */ +/******************************************************************************/ +int test() +{ + int j; + + long high = (long) floor(conf_high / out_scale); + long low = (unsigned) ceil(conf_low / out_scale); + long range = high - low; + + double res = 0.0f; + int in_val = 0; + int out_val = rand() % range; + + // calculate expected value + double expect = ((double)out_val * out_scale) + conf_low; + + tst_resm(TINFO, "Write output %f * %f = %u", ((double)out_val * out_scale) + conf_low, out_scale, out_val); + + // write output value + // (we must open/close/sync file here or SysFS-IIO-API won't work properly) + fd_out = opendevice(conf_outdevice_name, "w"); + fprintf(fd_out, "%u", out_val); + fclose (fd_out); + sync(); + + for (j = 0; j < conf_dummy_reads; j++) + { + // read input value + // (we must open/close/sync file here or SysFS-IIO-API won't work properly) + fd_in = opendevice(conf_indevice_name, "r"); + fscanf(fd_in, "%u", &in_val); + fclose (fd_in); + + // calculate input value from read raw-value + res = ((double)in_val * in_scale) + conf_low; + tst_resm(TINFO, "Read input %u = %f * %f", in_val, res, in_scale); + } + + // check input value against expections + if ((res < (expect - conf_err)) || + (res > (expect + conf_err))) { + tst_resm(TINFO, "Input %f outside range %f +/- %f", res, expect, conf_err); + return -1; + } + + tst_resm(TINFO, "Input %f within range %f +/- %f", res, expect, conf_err); + return 0; +} + + +/******************************************************************************/ +/* */ +/* Function: help */ +/* */ +/* Description: This function is called when the test is started with */ +/* parameter -h. It displays all parameter options specifically */ +/* available for this test. */ +/* */ +/* Input: None. */ +/* */ +/* Output: None. */ +/* */ +/* Return: Nothing. */ +/* */ +/******************************************************************************/ +void help() +{ + printf(" -i s Select the input IIO-device and channel s (default: %s)\n", conf_indevice_name); + printf(" -o s Select the output IIO-device and channel s (default: %s)\n", conf_outdevice_name); + printf(" -d f Specifies minimum output value (default: %lf) \n", conf_low); + printf(" -u f Specifies maximum output value (default: %lf) \n", conf_high); + printf(" -e f Specifies maximum allowed absoulte error from input (default: %lf) \n", conf_err); + printf(" -r n Specifies number of dummy reads for input to settle (default: %u) \n", conf_dummy_reads); + printf(" -q Suppress info messages\n"); +} + +/******************************************************************************/ +/* */ +/* Function: main */ +/* */ +/* Description: Entry point to this test-case. It parses all the command line */ +/* inputs, calls the global setup and executes the test. It logs */ +/* the test status and results appropriately using the LTP API's */ +/* On successful completion or premature failure, cleanup() func */ +/* is called and test exits with an appropriate return code. */ +/* */ +/* Input: Command line parameters (see help()) */ +/* */ +/* Exit: On failure - Exits by calling cleanup(). */ +/* On success - exits with 0 exit value. */ +/* */ +/******************************************************************************/ +int main(int argc, char **argv) +{ + int opt_v = 0, opt_i = 0, opt_o = 0, opt_d = 0, opt_u = 0, opt_e = 0, opt_r = 0, opt_q = 0, ret = 0, lc; + char *str_i, *str_o, *str_d, *str_u, *str_e, *str_r; + + option_t options[] = { + {"i:", &opt_i, &str_i}, + {"o:", &opt_o, &str_o}, + {"d:", &opt_d, &str_d}, + {"u:", &opt_u, &str_u}, + {"e:", &opt_e, &str_e}, + {"r:", &opt_r, &str_r}, + {"v", &opt_v, NULL}, + {"q", &opt_q, NULL}, + {NULL, NULL, NULL} + }; + + /* parse options */ +#if LTP_VERSION > 20140115 + tst_parse_opts(argc, argv, options, &help); +#else + char *msg; + if((msg = parse_opts(argc, argv, options, &help)) != NULL) + tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); +#endif + + if (opt_i) + conf_indevice_name = str_i; + if (opt_o) + conf_outdevice_name = str_o; + + if (opt_d) { + if (sscanf(str_d, "%lf", &conf_low) != 1) + tst_resm(TWARN, + "double number for minimum value expected. Using default %f now.", conf_low); + } + if (opt_u) { + if (sscanf(str_u, "%lf", &conf_high) != 1) + tst_resm(TWARN, + "double number for maximum value expected. Using default %f now.", conf_high); + } + if (opt_e) { + if (sscanf(str_e, "%lf", &conf_err) != 1) + tst_resm(TWARN, + "double number for error value expected. Using default %f now.", conf_err); + } + + if (opt_r) { + if (sscanf(str_r, "%u", &conf_dummy_reads) != 1) + tst_resm(TWARN, + "Number for dummy reads expected. Using default %u now.", conf_dummy_reads); + } + + if (opt_q) + conf_quiet = 1; + if (opt_v){ + conf_verbose = 1; + conf_quiet = 0; + } + + /* do initialization */ + setup(); + + /* start the test */ + tst_resm(TINFO, + "Starting aio test. (in: %s, out: %s, err: %f reads: %u)", + conf_indevice_name, conf_outdevice_name, conf_err, conf_dummy_reads); + + /* perform the test */ + for (lc=0; TEST_LOOPING(lc) && ret == 0; lc++) + { + ret = test(); + if (!conf_quiet) + { + // In normal mode display each test result + if (ret != 0) + tst_resm(TFAIL, + "Input value outside error-tolerance. Test failed."); + else + tst_resm(TPASS, + "Input value within error-tolerance. Test passed."); + } + } + + if (conf_quiet) + { + // In quiet mode only display summary + if (ret != 0) + tst_resm(TFAIL, + "Input value outside error-tolerance. Test failed."); + else + tst_resm(TPASS, + "Input value within error-tolerance. Test passed."); + } + + cleanup(); + tst_exit(); +}