1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 
9 #include <zephyr/drivers/adc.h>
10 #include <zephyr/drivers/dma.h>
11 #include <zephyr/drivers/counter.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/ztest.h>
14 
15 /* Invalid value that is not supposed to be written by the driver. It is used
16  * to mark the sample buffer entries as empty. If needed, it can be overridden
17  * for a particular board by providing a specific definition above.
18  */
19 #if !defined(INVALID_ADC_VALUE)
20 #define INVALID_ADC_VALUE SHRT_MIN
21 #endif
22 
23 #if CONFIG_NOCACHE_MEMORY
24 #define __NOCACHE	__attribute__((__section__(".nocache")))
25 #else /* CONFIG_NOCACHE_MEMORY */
26 #define __NOCACHE
27 #endif /* CONFIG_NOCACHE_MEMORY */
28 
29 #define BUFFER_SIZE  6
30 #ifdef CONFIG_TEST_USERSPACE
31 static ZTEST_BMEM int16_t m_sample_buffer[BUFFER_SIZE];
32 #else
33 static __aligned(32) int16_t m_sample_buffer[BUFFER_SIZE] __NOCACHE;
34 #endif
35 
36 #define DT_SPEC_AND_COMMA(node_id, prop, idx) ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
37 
38 #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
39 /* Data of ADC io-channels specified in devicetree. */
40 static const struct adc_dt_spec adc_channels[] = {
41 	DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, DT_SPEC_AND_COMMA)
42 };
43 static const int adc_channels_count = ARRAY_SIZE(adc_channels);
44 #else
45 #error "Unsupported board."
46 #endif
47 
get_adc_device(void)48 const struct device *get_adc_device(void)
49 {
50 	if (!adc_is_ready_dt(&adc_channels[0])) {
51 		printk("ADC device is not ready\n");
52 		return NULL;
53 	}
54 
55 	return adc_channels[0].dev;
56 }
57 
58 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(test_counter)) && \
59 	defined(CONFIG_COUNTER)
init_counter(void)60 static void init_counter(void)
61 {
62 	int err;
63 	const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(test_counter));
64 	struct counter_top_cfg top_cfg = { .callback = NULL,
65 					   .user_data = NULL,
66 					   .flags = 0 };
67 
68 	zassert_true(device_is_ready(dev), "Counter device is not ready");
69 
70 	counter_start(dev);
71 	top_cfg.ticks = counter_us_to_ticks(dev, CONFIG_ADC_API_SAMPLE_INTERVAL_US);
72 	err = counter_set_top_value(dev, &top_cfg);
73 	zassert_equal(0, err, "%s: Counter failed to set top value (err: %d)",
74 		      dev->name, err);
75 }
76 #endif
77 
init_adc(void)78 static void init_adc(void)
79 {
80 	int i, ret;
81 
82 	zassert_true(adc_is_ready_dt(&adc_channels[0]), "ADC device is not ready");
83 
84 	for (i = 0; i < adc_channels_count; i++) {
85 		ret = adc_channel_setup_dt(&adc_channels[i]);
86 		zassert_equal(ret, 0, "Setting up of channel %d failed with code %d", i, ret);
87 	}
88 
89 	for (i = 0; i < BUFFER_SIZE; ++i) {
90 		m_sample_buffer[i] = INVALID_ADC_VALUE;
91 	}
92 
93 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(test_counter)) && \
94 	defined(CONFIG_COUNTER)
95 	init_counter();
96 #endif
97 }
98 
check_samples(int expected_count)99 static void check_samples(int expected_count)
100 {
101 	int i;
102 
103 	TC_PRINT("Samples read: ");
104 	for (i = 0; i < BUFFER_SIZE; i++) {
105 		int16_t sample_value = m_sample_buffer[i];
106 
107 		TC_PRINT("0x%04hx ", sample_value);
108 		if (i < expected_count) {
109 			zassert_not_equal(INVALID_ADC_VALUE, sample_value,
110 				"[%u] should be filled", i);
111 		} else {
112 			zassert_equal(INVALID_ADC_VALUE, sample_value,
113 				"[%u] should be empty", i);
114 		}
115 	}
116 	TC_PRINT("\n");
117 }
118 
119 /*
120  * test_adc_sample_one_channel
121  */
test_task_one_channel(void)122 static int test_task_one_channel(void)
123 {
124 	int ret;
125 	struct adc_sequence sequence = {
126 		.buffer = m_sample_buffer,
127 		.buffer_size = sizeof(m_sample_buffer),
128 	};
129 
130 	init_adc();
131 	(void)adc_sequence_init_dt(&adc_channels[0], &sequence);
132 
133 	ret = adc_read_dt(&adc_channels[0], &sequence);
134 	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
135 
136 	check_samples(1);
137 
138 	return TC_PASS;
139 }
140 
ZTEST_USER(adc_basic,test_adc_sample_one_channel)141 ZTEST_USER(adc_basic, test_adc_sample_one_channel)
142 {
143 	zassert_true(test_task_one_channel() == TC_PASS);
144 }
145 
146 /*
147  * test_adc_sample_multiple_channels
148  */
test_task_multiple_channels(void)149 static int test_task_multiple_channels(void)
150 {
151 	int ret;
152 	struct adc_sequence sequence = {
153 		.buffer      = m_sample_buffer,
154 		.buffer_size = sizeof(m_sample_buffer),
155 	};
156 
157 	init_adc();
158 	(void)adc_sequence_init_dt(&adc_channels[0], &sequence);
159 
160 	for (int i = 1; i < adc_channels_count; i++) {
161 		sequence.channels |= BIT(adc_channels[i].channel_id);
162 	}
163 
164 	ret = adc_read_dt(&adc_channels[0], &sequence);
165 	if (ret == -ENOTSUP) {
166 		ztest_test_skip();
167 	}
168 	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
169 
170 	check_samples(adc_channels_count);
171 
172 	return TC_PASS;
173 }
174 
ZTEST_USER(adc_basic,test_adc_sample_two_channels)175 ZTEST_USER(adc_basic, test_adc_sample_two_channels)
176 {
177 	if (adc_channels_count > 1) {
178 		zassert_true(test_task_multiple_channels() == TC_PASS);
179 	} else {
180 		ztest_test_skip();
181 	}
182 }
183 
184 /*
185  * test_adc_asynchronous_call
186  */
187 #if defined(CONFIG_ADC_ASYNC)
188 struct k_poll_signal async_sig;
189 
test_task_asynchronous_call(void)190 static int test_task_asynchronous_call(void)
191 {
192 	int ret;
193 	const struct adc_sequence_options options = {
194 		.extra_samplings = 4,
195 		/* Start consecutive samplings as fast as possible. */
196 		.interval_us     = CONFIG_ADC_API_SAMPLE_INTERVAL_US,
197 	};
198 	struct adc_sequence sequence = {
199 		.options     = &options,
200 		.buffer      = m_sample_buffer,
201 		.buffer_size = sizeof(m_sample_buffer),
202 	};
203 	struct k_poll_event  async_evt =
204 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
205 					 K_POLL_MODE_NOTIFY_ONLY,
206 					 &async_sig);
207 	init_adc();
208 
209 	(void)adc_sequence_init_dt(&adc_channels[0], &sequence);
210 
211 	ret = adc_read_async(adc_channels[0].dev, &sequence, &async_sig);
212 	zassert_equal(ret, 0, "adc_read_async() failed with code %d", ret);
213 
214 	ret = k_poll(&async_evt, 1, K_MSEC(1000));
215 	zassert_equal(ret, 0, "k_poll failed with error %d", ret);
216 
217 	check_samples(1 + options.extra_samplings);
218 
219 	return TC_PASS;
220 }
221 #endif /* defined(CONFIG_ADC_ASYNC) */
222 
ZTEST_USER(adc_basic,test_adc_asynchronous_call)223 ZTEST_USER(adc_basic, test_adc_asynchronous_call)
224 {
225 #if defined(CONFIG_ADC_ASYNC)
226 	zassert_true(test_task_asynchronous_call() == TC_PASS);
227 #else
228 	ztest_test_skip();
229 #endif /* defined(CONFIG_ADC_ASYNC) */
230 }
231 
232 /*
233  * test_adc_sample_with_interval
234  */
235 static uint32_t my_sequence_identifier = 0x12345678;
236 static void *user_data = &my_sequence_identifier;
237 
sample_with_interval_callback(const struct device * dev,const struct adc_sequence * sequence,uint16_t sampling_index)238 static enum adc_action sample_with_interval_callback(const struct device *dev,
239 						     const struct adc_sequence *sequence,
240 						     uint16_t sampling_index)
241 {
242 	if (sequence->options->user_data != &my_sequence_identifier) {
243 		user_data = sequence->options->user_data;
244 		return ADC_ACTION_FINISH;
245 	}
246 
247 	TC_PRINT("%s: sampling %d\n", __func__, sampling_index);
248 	return ADC_ACTION_CONTINUE;
249 }
250 
test_task_with_interval(void)251 static int test_task_with_interval(void)
252 {
253 	int ret;
254 	const struct adc_sequence_options options = {
255 		.interval_us     = 100 * 1000UL,
256 		.callback        = sample_with_interval_callback,
257 		.user_data       = user_data,
258 		.extra_samplings = 4,
259 	};
260 	struct adc_sequence sequence = {
261 		.options     = &options,
262 		.buffer      = m_sample_buffer,
263 		.buffer_size = sizeof(m_sample_buffer),
264 	};
265 
266 	init_adc();
267 
268 	(void)adc_sequence_init_dt(&adc_channels[0], &sequence);
269 
270 	ret = adc_read_dt(&adc_channels[0], &sequence);
271 	if (ret == -ENOTSUP) {
272 		ztest_test_skip();
273 	}
274 	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
275 
276 	zassert_equal(user_data, sequence.options->user_data,
277 		"Invalid user data: %p, expected: %p",
278 		user_data, sequence.options->user_data);
279 
280 	check_samples(1 + options.extra_samplings);
281 
282 	return TC_PASS;
283 }
284 
ZTEST(adc_basic,test_adc_sample_with_interval)285 ZTEST(adc_basic, test_adc_sample_with_interval)
286 {
287 	zassert_true(test_task_with_interval() == TC_PASS);
288 }
289 
290 /*
291  * test_adc_repeated_samplings
292  */
293 static uint8_t m_samplings_done;
repeated_samplings_callback(const struct device * dev,const struct adc_sequence * sequence,uint16_t sampling_index)294 static enum adc_action repeated_samplings_callback(const struct device *dev,
295 						   const struct adc_sequence *sequence,
296 						   uint16_t sampling_index)
297 {
298 	++m_samplings_done;
299 	TC_PRINT("%s: done %d\n", __func__, m_samplings_done);
300 	if (m_samplings_done == 1U) {
301 		check_samples(MIN(adc_channels_count, 2));
302 
303 		/* After first sampling continue normally. */
304 		return ADC_ACTION_CONTINUE;
305 	} else {
306 		check_samples(2 * MIN(adc_channels_count, 2));
307 
308 		/*
309 		 * The second sampling is repeated 9 times (the samples are
310 		 * written in the same place), then the sequence is finished
311 		 * prematurely.
312 		 */
313 		if (m_samplings_done < 10) {
314 			return ADC_ACTION_REPEAT;
315 		} else {
316 			return ADC_ACTION_FINISH;
317 		}
318 	}
319 }
320 
test_task_repeated_samplings(void)321 static int test_task_repeated_samplings(void)
322 {
323 	int ret;
324 	const struct adc_sequence_options options = {
325 		.callback        = repeated_samplings_callback,
326 		/*
327 		 * This specifies that 3 samplings are planned. However,
328 		 * the callback function above is constructed in such way
329 		 * that the first sampling is done normally, the second one
330 		 * is repeated 9 times, and then the sequence is finished.
331 		 * Hence, the third sampling will not take place.
332 		 */
333 		.extra_samplings = 2,
334 		/* Start consecutive samplings as fast as possible. */
335 		.interval_us     = CONFIG_ADC_API_SAMPLE_INTERVAL_US,
336 	};
337 	struct adc_sequence sequence = {
338 		.options     = &options,
339 		.buffer      = m_sample_buffer,
340 		.buffer_size = sizeof(m_sample_buffer),
341 	};
342 
343 	init_adc();
344 	(void)adc_sequence_init_dt(&adc_channels[0], &sequence);
345 
346 	if (adc_channels_count > 1) {
347 		sequence.channels |=  BIT(adc_channels[1].channel_id);
348 	}
349 
350 	ret = adc_read_dt(&adc_channels[0], &sequence);
351 	if (ret == -ENOTSUP) {
352 		ztest_test_skip();
353 	}
354 	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
355 
356 	return TC_PASS;
357 }
358 
ZTEST(adc_basic,test_adc_repeated_samplings)359 ZTEST(adc_basic, test_adc_repeated_samplings)
360 {
361 	zassert_true(test_task_repeated_samplings() == TC_PASS);
362 }
363 
364 /*
365  * test_adc_invalid_request
366  */
test_task_invalid_request(void)367 static int test_task_invalid_request(void)
368 {
369 	int ret;
370 	struct adc_sequence sequence = {
371 		.channels    = BIT(adc_channels[0].channel_id),
372 		.buffer      = m_sample_buffer,
373 		.buffer_size = sizeof(m_sample_buffer),
374 		.resolution  = 0, /* intentionally invalid value */
375 	};
376 
377 	init_adc();
378 
379 	ret = adc_read_dt(&adc_channels[0], &sequence);
380 	zassert_not_equal(ret, 0, "adc_read() unexpectedly succeeded");
381 
382 #if defined(CONFIG_ADC_ASYNC)
383 	ret = adc_read_async(adc_channels[0].dev, &sequence, &async_sig);
384 	zassert_not_equal(ret, 0, "adc_read_async() unexpectedly succeeded");
385 #endif
386 
387 	/*
388 	 * Make the sequence parameters valid, now the request should succeed.
389 	 */
390 	sequence.resolution = adc_channels[0].resolution;
391 
392 	ret = adc_read_dt(&adc_channels[0], &sequence);
393 	zassert_equal(ret, 0, "adc_read() failed with code %d", ret);
394 
395 	check_samples(1);
396 
397 	return TC_PASS;
398 }
399 
ZTEST_USER(adc_basic,test_adc_invalid_request)400 ZTEST_USER(adc_basic, test_adc_invalid_request)
401 {
402 	zassert_true(test_task_invalid_request() == TC_PASS);
403 }
404