Skip to content

Commit

Permalink
drivertest/adc : support cmocka_driver_adc
Browse files Browse the repository at this point in the history
Signed-off-by: xucheng5 <[email protected]>
  • Loading branch information
xucheng5 committed Aug 11, 2023
1 parent 3c674fb commit 3ec3ae5
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
5 changes: 5 additions & 0 deletions testing/drivertest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ MAINSRC += drivertest_watchdog.c
PROGNAME += cmocka_driver_watchdog
endif

ifneq ($(CONFIG_ADC),)
MAINSRC += drivertest_adc.c
PROGNAME += cmocka_driver_adc
endif

ifneq ($(CONFIG_I2C)$(CONFIG_SPI),)
ifneq ($(CONFIG_SENSORS_BMI160),)
MAINSRC += drivertest_i2c_spi.c
Expand Down
233 changes: 233 additions & 0 deletions testing/drivertest/drivertest_adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/****************************************************************************
* apps/testing/drivertest/drivertest_adc.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <sys/time.h>
#include <stdlib.h>

#include <cmocka.h>
#include <nuttx/analog/adc.h>
#include <nuttx/analog/ioctl.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define OPTARG_TO_VALUE(value, type, base) \
do { \
FAR char* ptr; \
value = (type)strtoul(optarg, &ptr, base); \
if (*ptr != '\0') { \
printf("Parameter error: -%c %s\n", ch, optarg); \
adc_help(argv[0]); \
} \
} while (0)

/****************************************************************************
* Private Function Prototypes
****************************************************************************/

struct adc_state_s
{
char devpath[PATH_MAX]; /* device to adc device path */
int adc_diff; /* adc value difference */
int duration; /* duration of sampling adc in seconds */
bool soft_trigger; /* soft trigger : true or false */
};

/****************************************************************************
* Private Functions
****************************************************************************/

static void adc_help(FAR char *process_name)
{
printf("Usage: %s [OPTIONS]\n", process_name);
printf(" -p adc device path , default : /dev/adc0\n");
printf(" -d sample adc changes over set-up value. default : 200\n");
printf(" -t duration of adc test [second] , default: 10s\n");
printf(" -m adc conversion method, 1 -- soft trigger, "
"0 -- interrupt , default: 1\n");
exit(-1);
}

/****************************************************************************
* Name: parse_commandline
****************************************************************************/

static void parse_commandline(FAR struct adc_state_s *adc_state, int argc,
FAR char **argv)
{
int ch;
int converted;

while ((ch = getopt(argc, argv, "p:d:m:t:h")) != ERROR)
{
switch (ch)
{
case 'p':
strlcpy(adc_state->devpath, optarg, sizeof(adc_state->devpath));
adc_state->devpath[sizeof(adc_state->devpath) - 1] = '\0';
break;
case 'd':
OPTARG_TO_VALUE(converted, int, 10);
if (converted < 0 || converted > 5000)
{
printf("sample adc value changes over: %d\n", converted);
adc_help(argv[0]);
}

adc_state->adc_diff = (uint8_t)converted;
break;
case 't':
OPTARG_TO_VALUE(converted, int, 10);
if (converted < 1 || converted > INT_MAX)
{
printf("Duty out of range: %d\n", converted);
adc_help(argv[0]);
}

adc_state->duration = (int)converted;
break;
case 'm':
OPTARG_TO_VALUE(converted, uint8_t, 10);
adc_state->soft_trigger = converted ? true : false;
break;
case '?':
printf("Unsupported option: %s\n", optarg);

case 'h':
adc_help(argv[0]);
break;
}
}
}

int32_t adc_read_one_sample(int fd, bool soft_trigger)
{
struct adc_msg_s sample;
int ret;
int nbytes;

/* software trigger to start one ADC conversion */

if (soft_trigger)
{
ret = ioctl(fd, ANIOC_TRIGGER, 0);
assert_return_code(ret, OK);
}

/* Read one samples */

nbytes = read(fd, &sample, sizeof(struct adc_msg_s));

/* Handle unexpected return values */

assert_true(nbytes == sizeof(struct adc_msg_s));

return sample.am_data;
}

/****************************************************************************
* Name: test_case_adc
****************************************************************************/

static void test_case_adc(FAR void** state)
{
int fd;
bool succ = false;
int32_t value1;
int32_t value2;
struct timeval tv1;
struct timeval tv2;
struct timeval res;
FAR struct adc_state_s *adc_state;
adc_state = (FAR struct adc_state_s *)*state;

/* Open the ADC device for reading */

fd = open(adc_state->devpath, O_RDONLY);
assert_true(fd > 0);

value1 = adc_read_one_sample(fd, adc_state->soft_trigger);

/* ADC sample value should be changed in duration [seconds] */

gettimeofday(&tv1, NULL);
while (true)
{
value2 = adc_read_one_sample(fd, adc_state->soft_trigger);
if (abs(value2 - value1) > adc_state->adc_diff)
{
succ = true;
break;
}

gettimeofday(&tv2, NULL);
timersub(&tv2, &tv1, &res);
if (res.tv_sec >= adc_state->duration)
{
printf("adc test timed out\n");
break;
}

usleep(adc_state->soft_trigger ? 1000000 : 200000);
}

close(fd);
assert_true(succ);
}

/****************************************************************************
* drivertest_adc_main
****************************************************************************/

int main(int argc, FAR char *argv[])
{
/* Initialize the state data */

struct adc_state_s adc_state = {
.devpath = "/dev/adc0",
.adc_diff = 200,
.duration = 10,
.soft_trigger = true,
};

parse_commandline(&adc_state, argc, argv);

const struct CMUnitTest tests[] = {
cmocka_unit_test_prestate(test_case_adc, &adc_state),
};

return cmocka_run_group_tests(tests, NULL, NULL);
}

0 comments on commit 3ec3ae5

Please sign in to comment.