@@ -623,6 +623,106 @@ ZTEST(spi_loopback, test_spi_word_size_32)
623
623
sizeof (buffer_tx_32 ), & spec_copies [4 ], 32 );
624
624
}
625
625
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
+
626
726
#if (CONFIG_SPI_ASYNC )
627
727
static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER (async_sig );
628
728
static struct k_poll_event async_evt =
0 commit comments