1 /*
2 * Copyright (c) 2017 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(spi_loopback);
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/printk.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <assert.h>
16 #include <zephyr/ztest.h>
17
18 #include <zephyr/drivers/spi.h>
19
20 #define SPI_FAST_DEV DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback_fast)
21 #define SPI_SLOW_DEV DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback_slow)
22
23 #if CONFIG_SPI_LOOPBACK_MODE_LOOP
24 #define MODE_LOOP SPI_MODE_LOOP
25 #else
26 #define MODE_LOOP 0
27 #endif
28
29 #ifdef CONFIG_SPI_LOOPBACK_16BITS_FRAMES
30 #define FRAME_SIZE (16)
31 #define FRAME_SIZE_STR ", frame size = 16"
32 #else
33 #define FRAME_SIZE (8)
34 #define FRAME_SIZE_STR ", frame size = 8"
35 #endif /* CONFIG_SPI_LOOPBACK_16BITS_FRAMES */
36
37 #ifdef CONFIG_DMA
38
39 #ifdef CONFIG_NOCACHE_MEMORY
40 #define DMA_ENABLED_STR ", DMA enabled"
41 #else /* CONFIG_NOCACHE_MEMORY */
42 #define DMA_ENABLED_STR ", DMA enabled (without CONFIG_NOCACHE_MEMORY)"
43 #endif
44
45 #else /* CONFIG_DMA */
46
47 #define DMA_ENABLED_STR
48 #endif /* CONFIG_DMA */
49
50 #define SPI_OP(frame_size) SPI_OP_MODE_MASTER | SPI_MODE_CPOL | MODE_LOOP | \
51 SPI_MODE_CPHA | SPI_WORD_SET(frame_size) | SPI_LINES_SINGLE
52
53 static struct spi_dt_spec spi_fast = SPI_DT_SPEC_GET(SPI_FAST_DEV, SPI_OP(FRAME_SIZE), 0);
54 static struct spi_dt_spec spi_slow = SPI_DT_SPEC_GET(SPI_SLOW_DEV, SPI_OP(FRAME_SIZE), 0);
55
56 /* to run this test, connect MOSI pin to the MISO of the SPI */
57
58 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
59 #define BUF_SIZE 18
60 #define BUF2_SIZE 36
61
62 #if CONFIG_NOCACHE_MEMORY
63 #define __NOCACHE __attribute__((__section__(".nocache")))
64 #elif defined(CONFIG_DT_DEFINED_NOCACHE)
65 #define __NOCACHE __attribute__((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME)))
66 #else /* CONFIG_NOCACHE_MEMORY */
67 #define __NOCACHE
68 #endif /* CONFIG_NOCACHE_MEMORY */
69
70 static const char tx_data[BUF_SIZE] = "0123456789abcdef-\0";
71 static __aligned(32) char buffer_tx[BUF_SIZE] __used __NOCACHE;
72 static __aligned(32) char buffer_rx[BUF_SIZE] __used __NOCACHE;
73 static const char tx2_data[BUF2_SIZE] = "Thequickbrownfoxjumpsoverthelazydog\0";
74 static __aligned(32) char buffer2_tx[BUF2_SIZE] __used __NOCACHE;
75 static __aligned(32) char buffer2_rx[BUF2_SIZE] __used __NOCACHE;
76
77 /*
78 * We need 5x(buffer size) + 1 to print a comma-separated list of each
79 * byte in hex, plus a null.
80 */
81 static uint8_t buffer_print_tx[BUF_SIZE * 5 + 1];
82 static uint8_t buffer_print_rx[BUF_SIZE * 5 + 1];
83
84 static uint8_t buffer_print_tx2[BUF2_SIZE * 5 + 1];
85 static uint8_t buffer_print_rx2[BUF2_SIZE * 5 + 1];
86
to_display_format(const uint8_t * src,size_t size,char * dst)87 static void to_display_format(const uint8_t *src, size_t size, char *dst)
88 {
89 size_t i;
90
91 for (i = 0; i < size; i++) {
92 sprintf(dst + 5 * i, "0x%02x,", src[i]);
93 }
94 }
95
96 /* test transferring different buffers on the same dma channels */
spi_complete_multiple(struct spi_dt_spec * spec)97 static int spi_complete_multiple(struct spi_dt_spec *spec)
98 {
99 struct spi_buf tx_bufs[2];
100 const struct spi_buf_set tx = {
101 .buffers = tx_bufs,
102 .count = ARRAY_SIZE(tx_bufs)
103 };
104
105 tx_bufs[0].buf = buffer_tx;
106 tx_bufs[0].len = BUF_SIZE;
107
108 tx_bufs[1].buf = buffer2_tx;
109 tx_bufs[1].len = BUF2_SIZE;
110
111
112 struct spi_buf rx_bufs[2];
113 const struct spi_buf_set rx = {
114 .buffers = rx_bufs,
115 .count = ARRAY_SIZE(rx_bufs)
116 };
117
118 rx_bufs[0].buf = buffer_rx;
119 rx_bufs[0].len = BUF_SIZE;
120
121 rx_bufs[1].buf = buffer2_rx;
122 rx_bufs[1].len = BUF2_SIZE;
123
124 int ret;
125
126 LOG_INF("Start complete multiple");
127
128 ret = spi_transceive_dt(spec, &tx, &rx);
129 if (ret) {
130 LOG_ERR("Code %d", ret);
131 zassert_false(ret, "SPI transceive failed");
132 return ret;
133 }
134
135 if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
136 to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
137 to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
138 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
139 LOG_ERR(" vs: %s", buffer_print_rx);
140 zassert_false(1, "Buffer contents are different");
141 return -1;
142 }
143
144 if (memcmp(buffer2_tx, buffer2_rx, BUF2_SIZE)) {
145 to_display_format(buffer2_tx, BUF2_SIZE, buffer_print_tx2);
146 to_display_format(buffer2_rx, BUF2_SIZE, buffer_print_rx2);
147 LOG_ERR("Buffer 2 contents are different: %s", buffer_print_tx2);
148 LOG_ERR(" vs: %s", buffer_print_rx2);
149 zassert_false(1, "Buffer 2 contents are different");
150 return -1;
151 }
152
153 LOG_INF("Passed");
154
155 return 0;
156 }
157
spi_complete_loop(struct spi_dt_spec * spec)158 static int spi_complete_loop(struct spi_dt_spec *spec)
159 {
160 const struct spi_buf tx_bufs[] = {
161 {
162 .buf = buffer_tx,
163 .len = BUF_SIZE,
164 },
165 };
166 const struct spi_buf rx_bufs[] = {
167 {
168 .buf = buffer_rx,
169 .len = BUF_SIZE,
170 },
171 };
172 const struct spi_buf_set tx = {
173 .buffers = tx_bufs,
174 .count = ARRAY_SIZE(tx_bufs)
175 };
176 const struct spi_buf_set rx = {
177 .buffers = rx_bufs,
178 .count = ARRAY_SIZE(rx_bufs)
179 };
180
181 int ret;
182
183 LOG_INF("Start complete loop");
184
185 ret = spi_transceive_dt(spec, &tx, &rx);
186 if (ret) {
187 LOG_ERR("Code %d", ret);
188 zassert_false(ret, "SPI transceive failed");
189 return ret;
190 }
191
192 if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
193 to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
194 to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
195 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
196 LOG_ERR(" vs: %s", buffer_print_rx);
197 zassert_false(1, "Buffer contents are different");
198 return -1;
199 }
200
201 LOG_INF("Passed");
202
203 return 0;
204 }
205
spi_null_tx_buf(struct spi_dt_spec * spec)206 static int spi_null_tx_buf(struct spi_dt_spec *spec)
207 {
208 static const uint8_t EXPECTED_NOP_RETURN_BUF[BUF_SIZE] = { 0 };
209
210 (void)memset(buffer_rx, 0x77, BUF_SIZE);
211
212 const struct spi_buf tx_bufs[] = {
213 /* According to documentation, when sending NULL tx buf -
214 * NOP frames should be sent on MOSI line
215 */
216 {
217 .buf = NULL,
218 .len = BUF_SIZE,
219 },
220 };
221 const struct spi_buf rx_bufs[] = {
222 {
223 .buf = buffer_rx,
224 .len = BUF_SIZE,
225 },
226 };
227 const struct spi_buf_set tx = {
228 .buffers = tx_bufs,
229 .count = ARRAY_SIZE(tx_bufs)
230 };
231 const struct spi_buf_set rx = {
232 .buffers = rx_bufs,
233 .count = ARRAY_SIZE(rx_bufs)
234 };
235
236 int ret;
237
238 LOG_INF("Start null tx");
239
240 ret = spi_transceive_dt(spec, &tx, &rx);
241 if (ret) {
242 LOG_ERR("Code %d", ret);
243 zassert_false(ret, "SPI transceive failed");
244 return ret;
245 }
246
247
248 if (memcmp(buffer_rx, EXPECTED_NOP_RETURN_BUF, BUF_SIZE)) {
249 to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
250 LOG_ERR("Rx Buffer should contain NOP frames but got: %s",
251 buffer_print_rx);
252 zassert_false(1, "Buffer not as expected");
253 return -1;
254 }
255
256 LOG_INF("Passed");
257
258 return 0;
259 }
260
spi_rx_half_start(struct spi_dt_spec * spec)261 static int spi_rx_half_start(struct spi_dt_spec *spec)
262 {
263 const struct spi_buf tx_bufs[] = {
264 {
265 .buf = buffer_tx,
266 .len = BUF_SIZE,
267 },
268 };
269 const struct spi_buf rx_bufs[] = {
270 {
271 .buf = buffer_rx,
272 .len = 8,
273 },
274 };
275 const struct spi_buf_set tx = {
276 .buffers = tx_bufs,
277 .count = ARRAY_SIZE(tx_bufs)
278 };
279 const struct spi_buf_set rx = {
280 .buffers = rx_bufs,
281 .count = ARRAY_SIZE(rx_bufs)
282 };
283 int ret;
284
285 LOG_INF("Start half start");
286
287 (void)memset(buffer_rx, 0, BUF_SIZE);
288
289 ret = spi_transceive_dt(spec, &tx, &rx);
290 if (ret) {
291 LOG_ERR("Code %d", ret);
292 zassert_false(ret, "SPI transceive failed");
293 return -1;
294 }
295
296 if (memcmp(buffer_tx, buffer_rx, 8)) {
297 to_display_format(buffer_tx, 8, buffer_print_tx);
298 to_display_format(buffer_rx, 8, buffer_print_rx);
299 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
300 LOG_ERR(" vs: %s", buffer_print_rx);
301 zassert_false(1, "Buffer contents are different");
302 return -1;
303 }
304
305 LOG_INF("Passed");
306
307 return 0;
308 }
309
spi_rx_half_end(struct spi_dt_spec * spec)310 static int spi_rx_half_end(struct spi_dt_spec *spec)
311 {
312 const struct spi_buf tx_bufs[] = {
313 {
314 .buf = buffer_tx,
315 .len = BUF_SIZE,
316 },
317 };
318 const struct spi_buf rx_bufs[] = {
319 {
320 .buf = NULL,
321 .len = 8,
322 },
323 {
324 .buf = buffer_rx,
325 .len = 8,
326 },
327 };
328 const struct spi_buf_set tx = {
329 .buffers = tx_bufs,
330 .count = ARRAY_SIZE(tx_bufs)
331 };
332 const struct spi_buf_set rx = {
333 .buffers = rx_bufs,
334 .count = ARRAY_SIZE(rx_bufs)
335 };
336 int ret;
337
338 if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
339 LOG_INF("Skip half end");
340 return 0;
341 }
342
343 LOG_INF("Start half end");
344
345 (void)memset(buffer_rx, 0, BUF_SIZE);
346
347 ret = spi_transceive_dt(spec, &tx, &rx);
348 if (ret) {
349 LOG_ERR("Code %d", ret);
350 zassert_false(ret, "SPI transceive failed");
351 return -1;
352 }
353
354 if (memcmp(buffer_tx + 8, buffer_rx, 8)) {
355 to_display_format(buffer_tx + 8, 8, buffer_print_tx);
356 to_display_format(buffer_rx, 8, buffer_print_rx);
357 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
358 LOG_ERR(" vs: %s", buffer_print_rx);
359 zassert_false(1, "Buffer contents are different");
360 return -1;
361 }
362
363 LOG_INF("Passed");
364
365 return 0;
366 }
367
spi_rx_every_4(struct spi_dt_spec * spec)368 static int spi_rx_every_4(struct spi_dt_spec *spec)
369 {
370 const struct spi_buf tx_bufs[] = {
371 {
372 .buf = buffer_tx,
373 .len = BUF_SIZE,
374 },
375 };
376 const struct spi_buf rx_bufs[] = {
377 {
378 .buf = NULL,
379 .len = 4,
380 },
381 {
382 .buf = buffer_rx,
383 .len = 4,
384 },
385 {
386 .buf = NULL,
387 .len = 4,
388 },
389 {
390 .buf = buffer_rx + 4,
391 .len = 4,
392 },
393 };
394 const struct spi_buf_set tx = {
395 .buffers = tx_bufs,
396 .count = ARRAY_SIZE(tx_bufs)
397 };
398 const struct spi_buf_set rx = {
399 .buffers = rx_bufs,
400 .count = ARRAY_SIZE(rx_bufs)
401 };
402 int ret;
403
404 if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
405 LOG_INF("Skip every 4");
406 return 0;
407 }
408
409 if (IS_ENABLED(CONFIG_DSPI_MCUX_EDMA)) {
410 LOG_INF("Skip every 4");
411 return 0;
412 }
413
414 LOG_INF("Start every 4");
415
416 (void)memset(buffer_rx, 0, BUF_SIZE);
417
418 ret = spi_transceive_dt(spec, &tx, &rx);
419 if (ret) {
420 LOG_ERR("Code %d", ret);
421 zassert_false(ret, "SPI transceive failed");
422 return -1;
423 }
424
425 if (memcmp(buffer_tx + 4, buffer_rx, 4)) {
426 to_display_format(buffer_tx + 4, 4, buffer_print_tx);
427 to_display_format(buffer_rx, 4, buffer_print_rx);
428 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
429 LOG_ERR(" vs: %s", buffer_print_rx);
430 zassert_false(1, "Buffer contents are different");
431 return -1;
432 } else if (memcmp(buffer_tx + 12, buffer_rx + 4, 4)) {
433 to_display_format(buffer_tx + 12, 4, buffer_print_tx);
434 to_display_format(buffer_rx + 4, 4, buffer_print_rx);
435 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
436 LOG_ERR(" vs: %s", buffer_print_rx);
437 zassert_false(1, "Buffer contents are different");
438 return -1;
439 }
440
441 LOG_INF("Passed");
442
443 return 0;
444 }
445
spi_rx_bigger_than_tx(struct spi_dt_spec * spec)446 static int spi_rx_bigger_than_tx(struct spi_dt_spec *spec)
447 {
448 const uint32_t tx_buf_size = 8;
449
450 BUILD_ASSERT(tx_buf_size < BUF_SIZE,
451 "Transmit buffer is expected to be smaller than the receive buffer");
452
453 const struct spi_buf tx_bufs[] = {
454 {
455 .buf = buffer_tx,
456 .len = tx_buf_size,
457 },
458 };
459 const struct spi_buf rx_bufs[] = {
460 {
461 .buf = buffer_rx,
462 .len = BUF_SIZE,
463 }
464 };
465 const struct spi_buf_set tx = {
466 .buffers = tx_bufs,
467 .count = ARRAY_SIZE(tx_bufs)
468 };
469 const struct spi_buf_set rx = {
470 .buffers = rx_bufs,
471 .count = ARRAY_SIZE(rx_bufs)
472 };
473 int ret;
474
475 if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
476 LOG_INF("Skip rx bigger than tx");
477 return 0;
478 }
479
480 LOG_INF("Start rx bigger than tx");
481
482 (void)memset(buffer_rx, 0xff, BUF_SIZE);
483
484 ret = spi_transceive_dt(spec, &tx, &rx);
485 if (ret) {
486 LOG_ERR("Code %d", ret);
487 zassert_false(ret, "SPI transceive failed");
488 return -1;
489 }
490
491 if (memcmp(buffer_tx, buffer_rx, tx_buf_size)) {
492 to_display_format(buffer_tx, tx_buf_size, buffer_print_tx);
493 to_display_format(buffer_rx, tx_buf_size, buffer_print_rx);
494 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
495 LOG_ERR(" vs: %s", buffer_print_rx);
496 zassert_false(1, "Buffer contents are different");
497 return -1;
498 }
499
500 const uint8_t all_zeroes_buf[BUF_SIZE] = {0};
501
502 if (memcmp(all_zeroes_buf, buffer_rx + tx_buf_size, BUF_SIZE - tx_buf_size)) {
503 to_display_format(
504 buffer_rx + tx_buf_size, BUF_SIZE - tx_buf_size, buffer_print_tx);
505
506 to_display_format(
507 all_zeroes_buf, BUF_SIZE - tx_buf_size, buffer_print_rx);
508
509 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
510 LOG_ERR(" vs: %s", buffer_print_rx);
511 zassert_false(1, "Buffer contents are different");
512 return -1;
513 }
514
515 LOG_INF("Passed");
516
517 return 0;
518 }
519
520 #if (CONFIG_SPI_ASYNC)
521 static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
522 static struct k_poll_event async_evt =
523 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
524 K_POLL_MODE_NOTIFY_ONLY,
525 &async_sig);
526 static K_SEM_DEFINE(caller, 0, 1);
527 K_THREAD_STACK_DEFINE(spi_async_stack, STACK_SIZE);
528 static int result = 1;
529
spi_async_call_cb(void * p1,void * p2,void * p3)530 static void spi_async_call_cb(void *p1,
531 void *p2,
532 void *p3)
533 {
534 ARG_UNUSED(p1);
535 ARG_UNUSED(p2);
536 ARG_UNUSED(p3);
537
538 struct k_poll_event *evt = p1;
539 struct k_sem *caller_sem = p2;
540 int ret;
541
542 LOG_DBG("Polling...");
543
544 while (1) {
545 ret = k_poll(evt, 1, K_MSEC(2000));
546 zassert_false(ret, "one or more events are not ready");
547
548 result = evt->signal->result;
549 k_sem_give(caller_sem);
550
551 /* Reinitializing for next call */
552 evt->signal->signaled = 0U;
553 evt->state = K_POLL_STATE_NOT_READY;
554 }
555 }
556
spi_async_call(struct spi_dt_spec * spec)557 static int spi_async_call(struct spi_dt_spec *spec)
558 {
559 const struct spi_buf tx_bufs[] = {
560 {
561 .buf = buffer_tx,
562 .len = BUF_SIZE,
563 },
564 {
565 .buf = buffer2_tx,
566 .len = BUF2_SIZE,
567 },
568 };
569 const struct spi_buf rx_bufs[] = {
570 {
571 .buf = buffer_rx,
572 .len = BUF_SIZE,
573 },
574 {
575 .buf = buffer2_rx,
576 .len = BUF2_SIZE,
577 },
578 };
579 const struct spi_buf_set tx = {
580 .buffers = tx_bufs,
581 .count = ARRAY_SIZE(tx_bufs)
582 };
583 const struct spi_buf_set rx = {
584 .buffers = rx_bufs,
585 .count = ARRAY_SIZE(rx_bufs)
586 };
587 int ret;
588
589 LOG_INF("Start async call");
590 memset(buffer_rx, 0, sizeof(buffer_rx));
591 memset(buffer2_rx, 0, sizeof(buffer2_rx));
592
593 ret = spi_transceive_signal(spec->bus, &spec->config, &tx, &rx, &async_sig);
594 if (ret == -ENOTSUP) {
595 LOG_DBG("Not supported");
596 return 0;
597 }
598
599 if (ret) {
600 LOG_ERR("Code %d", ret);
601 zassert_false(ret, "SPI transceive failed");
602 return -1;
603 }
604
605 k_sem_take(&caller, K_FOREVER);
606
607 if (result) {
608 LOG_ERR("Call code %d", ret);
609 zassert_false(result, "SPI transceive failed");
610 return -1;
611 }
612
613 if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
614 to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
615 to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
616 LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
617 LOG_ERR(" vs: %s", buffer_print_rx);
618 zassert_false(1, "Buffer contents are different");
619 return -1;
620 }
621
622 if (memcmp(buffer2_tx, buffer2_rx, BUF2_SIZE)) {
623 to_display_format(buffer2_tx, BUF2_SIZE, buffer_print_tx2);
624 to_display_format(buffer2_rx, BUF2_SIZE, buffer_print_rx2);
625 LOG_ERR("Buffer 2 contents are different: %s", buffer_print_tx2);
626 LOG_ERR(" vs: %s", buffer_print_rx2);
627 zassert_false(1, "Buffer 2 contents are different");
628 return -1;
629 }
630
631 LOG_INF("Passed");
632
633 return 0;
634 }
635 #endif
636
spi_resource_lock_test(struct spi_dt_spec * lock_spec,struct spi_dt_spec * try_spec)637 static int spi_resource_lock_test(struct spi_dt_spec *lock_spec,
638 struct spi_dt_spec *try_spec)
639 {
640 lock_spec->config.operation |= SPI_LOCK_ON;
641
642 if (spi_complete_loop(lock_spec)) {
643 return -1;
644 }
645
646 if (spi_release_dt(lock_spec)) {
647 LOG_ERR("Deadlock now?");
648 zassert_false(1, "SPI release failed");
649 return -1;
650 }
651
652 if (spi_complete_loop(try_spec)) {
653 return -1;
654 }
655
656 return 0;
657 }
658
ZTEST(spi_loopback,test_spi_loopback)659 ZTEST(spi_loopback, test_spi_loopback)
660 {
661 #if (CONFIG_SPI_ASYNC)
662 struct k_thread async_thread;
663 k_tid_t async_thread_id;
664 #endif
665
666 LOG_INF("SPI test on buffers TX/RX %p/%p" FRAME_SIZE_STR DMA_ENABLED_STR,
667 buffer_tx,
668 buffer_rx);
669
670 #if (CONFIG_SPI_ASYNC)
671 async_thread_id = k_thread_create(&async_thread,
672 spi_async_stack, STACK_SIZE,
673 spi_async_call_cb,
674 &async_evt, &caller, NULL,
675 K_PRIO_COOP(7), 0, K_NO_WAIT);
676 #endif
677 zassert_true(spi_is_ready_dt(&spi_slow), "Slow spi lookback device is not ready");
678
679 LOG_INF("SPI test slow config");
680
681 if (spi_complete_multiple(&spi_slow) ||
682 spi_complete_loop(&spi_slow) ||
683 spi_null_tx_buf(&spi_slow) ||
684 spi_rx_half_start(&spi_slow) ||
685 spi_rx_half_end(&spi_slow) ||
686 spi_rx_every_4(&spi_slow) ||
687 spi_rx_bigger_than_tx(&spi_slow)
688 #if (CONFIG_SPI_ASYNC)
689 || spi_async_call(&spi_slow)
690 #endif
691 ) {
692 goto end;
693 }
694
695 zassert_true(spi_is_ready_dt(&spi_fast), "Fast spi lookback device is not ready");
696
697 LOG_INF("SPI test fast config");
698
699 if (spi_complete_multiple(&spi_fast) ||
700 spi_complete_loop(&spi_fast) ||
701 spi_null_tx_buf(&spi_fast) ||
702 spi_rx_half_start(&spi_fast) ||
703 spi_rx_half_end(&spi_fast) ||
704 spi_rx_every_4(&spi_fast) ||
705 spi_rx_bigger_than_tx(&spi_fast)
706 #if (CONFIG_SPI_ASYNC)
707 || spi_async_call(&spi_fast)
708 #endif
709 ) {
710 goto end;
711 }
712
713 if (spi_resource_lock_test(&spi_slow, &spi_fast)) {
714 goto end;
715 }
716
717 LOG_INF("All tx/rx passed");
718 end:
719 #if (CONFIG_SPI_ASYNC)
720 k_thread_abort(async_thread_id);
721 #else
722 ;
723 #endif
724 }
725
spi_loopback_setup(void)726 static void *spi_loopback_setup(void)
727 {
728 memset(buffer_tx, 0, sizeof(buffer_tx));
729 memcpy(buffer_tx, tx_data, sizeof(tx_data));
730 memset(buffer2_tx, 0, sizeof(buffer2_tx));
731 memcpy(buffer2_tx, tx2_data, sizeof(tx2_data));
732 return NULL;
733 }
734
735 ZTEST_SUITE(spi_loopback, NULL, spi_loopback_setup, NULL, NULL, NULL);
736