test: add adc_dma test application

add adc_dma test application
enable periodic_trigger flag for adc edma

enable for frdm_k64f and frdm_k82f

Signed-off-by: Hake Huang <hake.huang@oss.nxp.com>
diff --git a/tests/drivers/adc/adc_dma/CMakeLists.txt b/tests/drivers/adc/adc_dma/CMakeLists.txt
new file mode 100644
index 0000000..1a6c349
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/CMakeLists.txt
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: Apache-2.0
+
+cmake_minimum_required(VERSION 3.13.1)
+
+find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
+project(adc_dma)
+
+FILE(GLOB app_sources src/*.c)
+target_sources(app PRIVATE ${app_sources})
diff --git a/tests/drivers/adc/adc_dma/boards/frdm_k64f.conf b/tests/drivers/adc/adc_dma/boards/frdm_k64f.conf
new file mode 100644
index 0000000..5692079
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/boards/frdm_k64f.conf
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2020, NXP
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA=y
diff --git a/tests/drivers/adc/adc_dma/boards/frdm_k64f.overlay b/tests/drivers/adc/adc_dma/boards/frdm_k64f.overlay
new file mode 100644
index 0000000..c7ad87d
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/boards/frdm_k64f.overlay
@@ -0,0 +1,12 @@
+/*
+* Copyright (c) 2020, NXP
+*
+* SPDX-License-Identifier: Apache-2.0
+*/
+&adc0 {
+	clk-source = <0>;
+	hw-trigger-src = <4>;
+	continuous-convert;
+	high-speed;
+	periodic-trigger;
+};
diff --git a/tests/drivers/adc/adc_dma/boards/frdm_k82f.conf b/tests/drivers/adc/adc_dma/boards/frdm_k82f.conf
new file mode 100644
index 0000000..5692079
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/boards/frdm_k82f.conf
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2020, NXP
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA=y
diff --git a/tests/drivers/adc/adc_dma/boards/frdm_k82f.overlay b/tests/drivers/adc/adc_dma/boards/frdm_k82f.overlay
new file mode 100644
index 0000000..c7ad87d
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/boards/frdm_k82f.overlay
@@ -0,0 +1,12 @@
+/*
+* Copyright (c) 2020, NXP
+*
+* SPDX-License-Identifier: Apache-2.0
+*/
+&adc0 {
+	clk-source = <0>;
+	hw-trigger-src = <4>;
+	continuous-convert;
+	high-speed;
+	periodic-trigger;
+};
diff --git a/tests/drivers/adc/adc_dma/prj.conf b/tests/drivers/adc/adc_dma/prj.conf
new file mode 100644
index 0000000..c44105b
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/prj.conf
@@ -0,0 +1,10 @@
+CONFIG_ZTEST=y
+
+CONFIG_ADC=y
+CONFIG_ADC_ASYNC=y
+CONFIG_ADC_LOG_LEVEL_INF=y
+CONFIG_HEAP_MEM_POOL_SIZE=1024
+CONFIG_TEST_USERSPACE=y
+CONFIG_DMA=y
+CONFIG_COUNTER=y
+CONFIG_ADC_MCUX_ADC16_HW_TRIGGER=y
diff --git a/tests/drivers/adc/adc_dma/src/main.c b/tests/drivers/adc/adc_dma/src/main.c
new file mode 100644
index 0000000..942db23
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/src/main.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#include <zephyr.h>
+#include <ztest.h>
+
+extern void test_adc_sample_one_channel(void);
+extern void test_adc_sample_two_channels(void);
+extern void test_adc_asynchronous_call(void);
+extern void test_adc_sample_with_interval(void);
+extern void test_adc_repeated_samplings(void);
+extern void test_adc_invalid_request(void);
+extern const struct device *get_adc_device(void);
+extern const struct device *get_count_device(void);
+extern struct k_poll_signal async_sig;
+
+void test_main(void)
+{
+	k_object_access_grant(get_adc_device(), k_current_get());
+	k_object_access_grant(get_count_device(), k_current_get());
+#ifdef CONFIG_ADC_ASYNC
+	k_object_access_grant(&async_sig, k_current_get());
+	k_poll_signal_init(&async_sig);
+	k_thread_system_pool_assign(k_current_get());
+#endif
+
+	ztest_test_suite(adc_dma_test,
+			 ztest_user_unit_test(test_adc_sample_one_channel),
+			 ztest_user_unit_test(test_adc_sample_two_channels),
+			 ztest_user_unit_test(test_adc_asynchronous_call),
+			 ztest_unit_test(test_adc_sample_with_interval),
+			 ztest_unit_test(test_adc_repeated_samplings),
+			 ztest_user_unit_test(test_adc_invalid_request));
+	ztest_run_test_suite(adc_dma_test);
+}
diff --git a/tests/drivers/adc/adc_dma/src/test_adc.c b/tests/drivers/adc/adc_dma/src/test_adc.c
new file mode 100644
index 0000000..f6f43af
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/src/test_adc.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2020, NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#include <drivers/adc.h>
+#include <drivers/counter.h>
+#include <zephyr.h>
+#include <ztest.h>
+
+#if defined(CONFIG_BOARD_FRDM_K64F)
+
+#define ADC_DEVICE_NAME DT_LABEL(DT_INST(0, nxp_kinetis_adc16))
+#define ADC_RESOLUTION 12
+#define ADC_GAIN ADC_GAIN_1
+#define ADC_REFERENCE ADC_REF_INTERNAL
+#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
+#define ADC_1ST_CHANNEL_ID 26
+
+#elif defined(CONFIG_BOARD_FRDM_K82F)
+
+#define ADC_DEVICE_NAME DT_LABEL(DT_INST(0, nxp_kinetis_adc16))
+#define ADC_RESOLUTION 12
+#define ADC_GAIN ADC_GAIN_1
+#define ADC_REFERENCE ADC_REF_INTERNAL
+#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
+#define ADC_1ST_CHANNEL_ID 26
+
+#endif
+
+#define HW_TRIGGER_INTERVAL (2U)
+/* for DMA HW trigger interval need large than HW trigger interval*/
+#define SAMPLE_INTERVAL_US (10000U)
+
+#define BUFFER_SIZE 24
+static ZTEST_BMEM int16_t m_sample_buffer[BUFFER_SIZE];
+static ZTEST_BMEM int16_t m_sample_buffer2[2][BUFFER_SIZE];
+static int current_buf_inx;
+
+static const struct adc_channel_cfg m_1st_channel_cfg = {
+	.gain = ADC_GAIN,
+	.reference = ADC_REFERENCE,
+	.acquisition_time = ADC_ACQUISITION_TIME,
+	.channel_id = ADC_1ST_CHANNEL_ID,
+#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
+	.input_positive = ADC_1ST_CHANNEL_INPUT,
+#endif
+};
+#if defined(ADC_2ND_CHANNEL_ID)
+static const struct adc_channel_cfg m_2nd_channel_cfg = {
+	.gain = ADC_GAIN,
+	.reference = ADC_REFERENCE,
+	.acquisition_time = ADC_ACQUISITION_TIME,
+	.channel_id = ADC_2ND_CHANNEL_ID,
+#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
+	.input_positive = ADC_2ND_CHANNEL_INPUT,
+#endif
+};
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+
+const struct device *get_adc_device(void)
+{
+	return device_get_binding(ADC_DEVICE_NAME);
+}
+
+const struct device *get_count_device(void)
+{
+	char *dev_name = DT_LABEL(DT_NODELABEL(pit0));
+
+	return device_get_binding(dev_name);
+}
+
+static void init_pit(void)
+{
+	char *dev_name = DT_LABEL(DT_NODELABEL(pit0));
+	int err;
+	const struct device *dev;
+	struct counter_top_cfg top_cfg = { .callback = NULL,
+					   .user_data = NULL,
+					   .flags = 0 };
+
+	dev = device_get_binding(dev_name);
+	zassert_not_null(dev, "Unable to get counter device %s", dev_name);
+
+	counter_start(dev);
+	top_cfg.ticks = counter_us_to_ticks(dev, HW_TRIGGER_INTERVAL);
+	err = counter_set_top_value(dev, &top_cfg);
+	zassert_equal(0, err, "%s: Counter failed to set top value (err: %d)",
+		      dev_name, err);
+}
+
+static void stop_pit(void)
+{
+	char *dev_name = DT_LABEL(DT_NODELABEL(pit0));
+	const struct device *dev;
+
+	dev = device_get_binding(dev_name);
+	zassert_not_null(dev, "Unable to get counter device %s", dev_name);
+	counter_stop(dev);
+}
+
+static const struct device *init_adc(void)
+{
+	int ret;
+	const struct device *adc_dev = device_get_binding(ADC_DEVICE_NAME);
+
+	zassert_not_null(adc_dev, "Cannot get ADC device");
+
+	ret = adc_channel_setup(adc_dev, &m_1st_channel_cfg);
+	zassert_equal(ret, 0,
+		      "Setting up of the first channel failed with code %d",
+		      ret);
+
+#if defined(ADC_2ND_CHANNEL_ID)
+	ret = adc_channel_setup(adc_dev, &m_2nd_channel_cfg);
+	zassert_equal(ret, 0,
+		      "Setting up of the second channel failed with code %d",
+		      ret);
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+
+	(void)memset(m_sample_buffer, 0, sizeof(m_sample_buffer));
+
+	init_pit();
+
+	return adc_dev;
+}
+
+static void check_samples(int expected_count)
+{
+	int i;
+
+	TC_PRINT("Samples read: ");
+	for (i = 0; i < BUFFER_SIZE; i++) {
+		int16_t sample_value = m_sample_buffer[i];
+
+		TC_PRINT("0x%04x ", sample_value);
+		if (i && i % 10 == 0) {
+			TC_PRINT("\n");
+		}
+	}
+	TC_PRINT("%d sampled\n", BUFFER_SIZE);
+}
+
+static void check_samples2(int expected_count)
+{
+	int i;
+
+	TC_PRINT("Samples read: ");
+	for (i = 0; i < BUFFER_SIZE; i++) {
+		int16_t sample_value = m_sample_buffer2[current_buf_inx][i];
+
+		TC_PRINT("0x%04x ", sample_value);
+		if (i && i % 10 == 0) {
+			TC_PRINT("\n");
+		}
+	}
+	TC_PRINT("%d sampled\n", BUFFER_SIZE);
+}
+
+/*
+ * test_adc_sample_one_channel
+ */
+static int test_task_one_channel(void)
+{
+	int ret;
+	const struct adc_sequence sequence = {
+		.channels = BIT(ADC_1ST_CHANNEL_ID),
+		.buffer = m_sample_buffer,
+		.buffer_size = sizeof(m_sample_buffer),
+		.resolution = ADC_RESOLUTION,
+	};
+
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	ret = adc_read(adc_dev, &sequence);
+	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
+
+	check_samples(1);
+
+	return TC_PASS;
+}
+
+void test_adc_sample_one_channel(void)
+{
+	zassert_true(test_task_one_channel() == TC_PASS, NULL);
+}
+
+/*
+ * test_adc_sample_two_channels
+ */
+#if defined(ADC_2ND_CHANNEL_ID)
+static int test_task_two_channels(void)
+{
+	int ret;
+	const struct adc_sequence sequence = {
+		.channels = BIT(ADC_1ST_CHANNEL_ID) | BIT(ADC_2ND_CHANNEL_ID),
+		.buffer = m_sample_buffer,
+		.buffer_size = sizeof(m_sample_buffer),
+		.resolution = ADC_RESOLUTION,
+	};
+
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	ret = adc_read(adc_dev, &sequence);
+	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
+
+	check_samples(2);
+
+	return TC_PASS;
+}
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+
+void test_adc_sample_two_channels(void)
+{
+#if defined(ADC_2ND_CHANNEL_ID)
+	zassert_true(test_task_two_channels() == TC_PASS, NULL);
+#else
+	ztest_test_skip();
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+}
+
+/*
+ * test_adc_asynchronous_call
+ */
+#if defined(CONFIG_ADC_ASYNC)
+struct k_poll_signal async_sig;
+
+static int test_task_asynchronous_call(void)
+{
+	int ret;
+	const struct adc_sequence_options options = {
+		.extra_samplings = 4,
+		/* Start consecutive samplings as fast as possible. */
+		.interval_us = HW_TRIGGER_INTERVAL,
+	};
+	const struct adc_sequence sequence = {
+		.options = &options,
+		.channels = BIT(ADC_1ST_CHANNEL_ID),
+		.buffer = m_sample_buffer,
+		.buffer_size = sizeof(m_sample_buffer),
+		.resolution = ADC_RESOLUTION,
+	};
+	struct k_poll_event async_evt = K_POLL_EVENT_INITIALIZER(
+		K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig);
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	ret = adc_read_async(adc_dev, &sequence, &async_sig);
+	zassert_equal(ret, 0, "adc_read_async() failed with code %d", ret);
+
+	ret = k_poll(&async_evt, 1, K_MSEC(1000));
+	zassert_equal(ret, 0, "k_poll failed with error %d", ret);
+
+	check_samples(1 + options.extra_samplings);
+
+	return TC_PASS;
+}
+#endif /* defined(CONFIG_ADC_ASYNC) */
+
+void test_adc_asynchronous_call(void)
+{
+#if defined(CONFIG_ADC_ASYNC)
+	zassert_true(test_task_asynchronous_call() == TC_PASS, NULL);
+#else
+	ztest_test_skip();
+#endif /* defined(CONFIG_ADC_ASYNC) */
+}
+
+/*
+ * test_adc_sample_with_interval
+ */
+static enum adc_action
+sample_with_interval_callback(const struct device *dev,
+			      const struct adc_sequence *sequence,
+			      uint16_t sampling_index)
+{
+	struct adc_sequence *seq = (struct adc_sequence *)sequence;
+	int _inx = current_buf_inx;
+
+	memcpy(m_sample_buffer, m_sample_buffer2[_inx],
+	       sizeof(m_sample_buffer));
+	current_buf_inx = (current_buf_inx == 0) ? 1 : 0;
+	seq->buffer = m_sample_buffer2[current_buf_inx];
+	return ADC_ACTION_CONTINUE;
+}
+
+static int test_task_with_interval(void)
+{
+	int ret;
+	int count = 2;
+	int64_t time_stamp;
+	int64_t milliseconds_spent;
+
+	const struct adc_sequence_options options = {
+		.interval_us = 500UL, /*make this double to sample time*/
+		.callback = sample_with_interval_callback,
+		.extra_samplings = 1,
+	};
+	const struct adc_sequence sequence = {
+		.options = &options,
+		.channels = BIT(ADC_1ST_CHANNEL_ID),
+		.buffer = m_sample_buffer2[0],
+		.buffer_size = sizeof(m_sample_buffer2[0]),
+		.resolution = ADC_RESOLUTION,
+	};
+
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	current_buf_inx = 0;
+
+	while (count--) {
+		time_stamp = k_uptime_get();
+		ret = adc_read(adc_dev, &sequence);
+		milliseconds_spent = k_uptime_delta(&time_stamp);
+		printk("now spend = %lldms\n", milliseconds_spent);
+		zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
+	}
+	check_samples2(1 + options.extra_samplings);
+	return TC_PASS;
+}
+
+void test_adc_sample_with_interval(void)
+{
+	zassert_true(test_task_with_interval() == TC_PASS, NULL);
+}
+
+/*
+ * test_adc_repeated_samplings
+ */
+static uint8_t m_samplings_done;
+static enum adc_action
+repeated_samplings_callback(const struct device *dev,
+			    const struct adc_sequence *sequence,
+			    uint16_t sampling_index)
+{
+	++m_samplings_done;
+	TC_PRINT("%s: done %d\n", __func__, m_samplings_done);
+	if (m_samplings_done == 1U) {
+#if defined(ADC_2ND_CHANNEL_ID)
+		check_samples(2);
+#else
+		check_samples(1);
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+
+		/* After first sampling continue normally. */
+		return ADC_ACTION_CONTINUE;
+	}
+#if defined(ADC_2ND_CHANNEL_ID)
+	check_samples(4);
+#else
+	check_samples(2);
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+
+	/*
+	 * The second sampling is repeated 9 times (the samples are
+	 * written in the same place), then the sequence is finished
+	 * prematurely.
+	 */
+	if (m_samplings_done < 10) {
+		return ADC_ACTION_REPEAT;
+	} else {
+		return ADC_ACTION_FINISH;
+	}
+
+}
+
+static int test_task_repeated_samplings(void)
+{
+	int ret;
+	const struct adc_sequence_options options = {
+		.callback = repeated_samplings_callback,
+		/*
+		 * This specifies that 3 samplings are planned. However,
+		 * the callback function above is constructed in such way
+		 * that the first sampling is done normally, the second one
+		 * is repeated 9 times, and then the sequence is finished.
+		 * Hence, the third sampling will not take place.
+		 */
+		.extra_samplings = 2,
+		/* Start consecutive samplings as fast as possible. */
+		/* but the interval shall be larger than the HW trigger*/
+		.interval_us = SAMPLE_INTERVAL_US,
+	};
+	const struct adc_sequence sequence = {
+		.options = &options,
+#if defined(ADC_2ND_CHANNEL_ID)
+		.channels = BIT(ADC_1ST_CHANNEL_ID) | BIT(ADC_2ND_CHANNEL_ID),
+#else
+		.channels = BIT(ADC_1ST_CHANNEL_ID),
+#endif /* defined(ADC_2ND_CHANNEL_ID) */
+		.buffer = m_sample_buffer,
+		.buffer_size = sizeof(m_sample_buffer),
+		.resolution = ADC_RESOLUTION,
+	};
+
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	ret = adc_read(adc_dev, &sequence);
+	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
+
+	return TC_PASS;
+}
+
+void test_adc_repeated_samplings(void)
+{
+	zassert_true(test_task_repeated_samplings() == TC_PASS, NULL);
+}
+
+/*
+ * test_adc_invalid_request
+ */
+static int test_task_invalid_request(void)
+{
+	int ret;
+	struct adc_sequence sequence = {
+		.channels = BIT(ADC_1ST_CHANNEL_ID),
+		.buffer = m_sample_buffer,
+		.buffer_size = sizeof(m_sample_buffer),
+		.resolution = 0, /* intentionally invalid value */
+	};
+
+	const struct device *adc_dev = init_adc();
+
+	if (!adc_dev) {
+		return TC_FAIL;
+	}
+
+	ret = adc_read(adc_dev, &sequence);
+	zassert_not_equal(ret, 0, "adc_read() unexpectedly succeeded");
+
+#if defined(CONFIG_ADC_ASYNC)
+	ret = adc_read_async(adc_dev, &sequence, &async_sig);
+	zassert_not_equal(ret, 0, "adc_read_async() unexpectedly succeeded");
+#endif
+
+	/*
+	 * Make the sequence parameters valid, now the request should succeed.
+	 */
+	sequence.resolution = ADC_RESOLUTION;
+
+	ret = adc_read(adc_dev, &sequence);
+	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
+
+	check_samples(1);
+
+	return TC_PASS;
+}
+
+void test_adc_invalid_request(void)
+{
+	zassert_true(test_task_invalid_request() == TC_PASS, NULL);
+}
diff --git a/tests/drivers/adc/adc_dma/testcase.yaml b/tests/drivers/adc/adc_dma/testcase.yaml
new file mode 100644
index 0000000..2b3b1ee
--- /dev/null
+++ b/tests/drivers/adc/adc_dma/testcase.yaml
@@ -0,0 +1,6 @@
+common:
+  tags: adc dma trigger
+tests:
+  drivers.adc-dma:
+    depends_on: adc dma pit
+    platform_allow: frdm_k82f frdm_k64f