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