@@ -416,6 +416,24 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
416416 rt_tick_t timeout_tick = rt_tick_from_millisecond (timeout_ms );
417417#endif /* BSP_SPI_USING_IRQ */
418418
419+ #if defined(BSP_SPI_USING_DMA ) || defined(BSP_SPI_USING_INT )
420+ /*
421+ * Snapshot the call context once for the whole SPI message.
422+ *
423+ * The async route decision must stay stable across all chunks split from
424+ * one message. Re-evaluating scheduler/IRQ state per chunk could route
425+ * one logical SPI transfer through different async/polling policies.
426+ *
427+ * A thread switch or interrupt can happen while waiting for async transfer
428+ * completion, but execution still resumes in the same spixfer() call
429+ * context. Therefore, the route policy should follow this message-level
430+ * context instead of re-sampling a transient runtime state.
431+ */
432+ const rt_bool_t scheduler_available = rt_scheduler_is_available ();
433+ const rt_bool_t irq_disabled = rt_hw_interrupt_is_disabled ();
434+ const rt_bool_t async_allowed = (scheduler_available && !irq_disabled );
435+ #endif /* defined(BSP_SPI_USING_DMA) || defined(BSP_SPI_USING_INT) */
436+
419437 if (message -> cs_take && !(device -> config .mode & RT_SPI_NO_CS ) && (device -> cs_pin != PIN_NONE ))
420438 {
421439 if (device -> config .mode & RT_SPI_CS_HIGH )
@@ -462,8 +480,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
462480 {
463481 recv_buf = (rt_uint8_t * )message -> recv_buf + already_send_length ;
464482 }
465- const rt_bool_t scheduler_available = rt_scheduler_is_available ();
466- const rt_bool_t irq_disabled = rt_hw_interrupt_is_disabled ();
483+
467484#ifdef BSP_SPI_USING_DMA
468485 const rt_uint8_t * dma_send_buf = send_buf ;
469486 rt_uint8_t * dma_recv_buf = recv_buf ;
@@ -483,7 +500,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
483500 rt_bool_t use_rx_dma = RT_FALSE ;
484501#endif /* BSP_SPI_RX_USING_DMA */
485502
486- if (!scheduler_available || irq_disabled )
503+ if (!async_allowed )
487504 {
488505 use_rx_dma = use_tx_dma = dma_eligible = RT_FALSE ;
489506 }
@@ -541,7 +558,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
541558#else
542559 rt_bool_t use_rx_int = RT_FALSE ;
543560#endif /* BSP_SPI_RX_USING_INT */
544- if (!scheduler_available || irq_disabled )
561+ if (!async_allowed )
545562 {
546563 use_rx_int = use_tx_int = int_eligible = RT_FALSE ;
547564 }
0 commit comments