Skip to content

Commit a627399

Browse files
decsnykartben
authored andcommitted
tests: spi_loopback: Add test case of multithread
Add test cases for multithread access with both same spec and different specs to make sure nothing goes awry. Signed-off-by: Declan Snyder <[email protected]>
1 parent 972dac1 commit a627399

File tree

1 file changed

+100
-0
lines changed
  • tests/drivers/spi/spi_loopback/src

1 file changed

+100
-0
lines changed

tests/drivers/spi/spi_loopback/src/spi.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,106 @@ ZTEST(spi_loopback, test_spi_word_size_32)
623623
sizeof(buffer_tx_32), &spec_copies[4], 32);
624624
}
625625

626+
static K_THREAD_STACK_DEFINE(thread_stack[3], 512);
627+
static struct k_thread thread[3];
628+
629+
static K_SEM_DEFINE(thread_sem, 0, 3);
630+
static K_SEM_DEFINE(sync_sem, 0, 1);
631+
632+
static uint8_t __aligned(32) tx_buffer[3][32];
633+
static uint8_t __aligned(32) rx_buffer[3][32];
634+
635+
static void spi_transfer_thread(void *p1, void *p2, void *p3)
636+
{
637+
struct spi_dt_spec *spec = (struct spi_dt_spec *)p1;
638+
uint8_t *tx_buf_ptr = (uint8_t *)p2;
639+
uint8_t *rx_buf_ptr = (uint8_t *)p3;
640+
641+
/* Wait for all threads to be ready */
642+
k_sem_give(&thread_sem);
643+
k_sem_take(&sync_sem, K_FOREVER);
644+
645+
/* Perform SPI transfer */
646+
const struct spi_buf_set tx_bufs = {
647+
.buffers = &(struct spi_buf) {
648+
.buf = tx_buf_ptr,
649+
.len = 32,
650+
},
651+
.count = 1,
652+
};
653+
const struct spi_buf_set rx_bufs = {
654+
.buffers = &(struct spi_buf) {
655+
.buf = rx_buf_ptr,
656+
.len = 32,
657+
},
658+
.count = 1,
659+
};
660+
661+
zassert_equal(spi_transceive_dt(spec, &tx_bufs, &rx_bufs), 0,
662+
"SPI concurrent transfer failed");
663+
664+
zassert_mem_equal(tx_buf_ptr, rx_buf_ptr, 32,
665+
"SPI concurrent transfer data mismatch");
666+
}
667+
668+
/* Test case for concurrent SPI transfers */
669+
static void test_spi_concurrent_transfer_helper(struct spi_dt_spec **specs)
670+
{
671+
/* Create three threads */
672+
for (int i = 0; i < 3; i++) {
673+
memset(tx_buffer[i], 0xaa, sizeof(tx_buffer[i]));
674+
memset(rx_buffer[i], 0, sizeof(rx_buffer[i]));
675+
k_thread_create(&thread[i], thread_stack[i],
676+
K_THREAD_STACK_SIZEOF(thread_stack[i]),
677+
spi_transfer_thread, specs[i],
678+
tx_buffer[i], rx_buffer[i],
679+
K_PRIO_PREEMPT(10), 0, K_NO_WAIT);
680+
}
681+
682+
/* Wait for all threads to be ready */
683+
for (int i = 0; i < 3; i++) {
684+
k_sem_take(&thread_sem, K_FOREVER);
685+
}
686+
687+
/* Start all threads simultaneously */
688+
for (int i = 0; i < 3; i++) {
689+
k_sem_give(&sync_sem);
690+
}
691+
692+
/* Wait for threads to complete */
693+
for (int i = 0; i < 3; i++) {
694+
k_thread_join(&thread[i], K_FOREVER);
695+
}
696+
}
697+
698+
/* test for multiple threads accessing the driver / bus with the same spi_config */
699+
ZTEST(spi_loopback, test_spi_concurrent_transfer_same_spec)
700+
{
701+
struct spi_dt_spec *specs[3] = {
702+
loopback_specs[spec_idx],
703+
loopback_specs[spec_idx],
704+
loopback_specs[spec_idx]
705+
};
706+
test_spi_concurrent_transfer_helper(specs);
707+
}
708+
709+
/* test for multiple threads accessing the driver / bus with different spi_config
710+
* (different address of the config is what's important here
711+
*/
712+
ZTEST(spi_loopback, test_spi_concurrent_transfer_different_spec)
713+
{
714+
struct spi_dt_spec *specs[3] = {
715+
&spec_copies[0],
716+
&spec_copies[1],
717+
&spec_copies[2]
718+
};
719+
spec_copies[0] = *loopback_specs[spec_idx];
720+
spec_copies[1] = *loopback_specs[spec_idx];
721+
spec_copies[2] = *loopback_specs[spec_idx];
722+
723+
test_spi_concurrent_transfer_helper(specs);
724+
}
725+
626726
#if (CONFIG_SPI_ASYNC)
627727
static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
628728
static struct k_poll_event async_evt =

0 commit comments

Comments
 (0)