Skip to content

Commit 67a90eb

Browse files
wdfk-progRbb666
authored andcommitted
fix[STM32][SPI]: keep async route decision stable per message
snapshot scheduler and interrupt state once per SPI message reuse the message-level async route decision for all split chunks disable DMA and interrupt paths consistently when async transfer is unavailable avoid mixed async and polling policies within one logical SPI transfer
1 parent faefdc7 commit 67a90eb

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

  • bsp/stm32/libraries/HAL_Drivers/drivers

bsp/stm32/libraries/HAL_Drivers/drivers/drv_spi.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)