@@ -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 )
627727static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER (async_sig );
628728static struct k_poll_event async_evt =
0 commit comments