2020extern "C" {
2121#endif
2222
23+ #if defined(USE_HALV2_DRIVER )
24+ /* HAL v2 polling APIs use HAL_GetTick() for their timeout. On the current
25+ * Arduino C5 clock path that tick is not guaranteed to advance while polling,
26+ * so use the Arduino microsecond clock to bound LL polling instead. */
27+ static bool spi_transfer_timed_out (uint32_t start_us )
28+ {
29+ return (SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY )
30+ && ((uint32_t )(micros () - start_us ) >= (SPI_TRANSFER_TIMEOUT * 1000UL ));
31+ }
32+ #endif
33+
2334/* Private Functions */
2435/**
2536 * @brief return clock freq of an SPI instance
@@ -564,13 +575,19 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff
564575{
565576 spi_status_e ret = SPI_OK ;
566577 uint32_t tickstart , size = len ;
578+ #if defined(USE_HALV2_DRIVER )
579+ uint32_t start_us ;
580+ #endif
567581 SPI_TypeDef * _SPI = obj -> spi ;
568582 uint8_t * tx_buf = (uint8_t * )tx_buffer ;
569583
570584 if (len == 0 ) {
571585 ret = SPI_ERROR ;
572586 } else {
573587 tickstart = HAL_GetTick ();
588+ #if defined(USE_HALV2_DRIVER )
589+ start_us = micros ();
590+ #endif
574591
575592#if defined(SPI_CR2_TSIZE )
576593 /* Start transfer */
@@ -581,14 +598,32 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff
581598
582599 while (size -- ) {
583600#if defined(SPI_SR_TXP )
601+ #if defined(USE_HALV2_DRIVER )
602+ while (!LL_SPI_IsActiveFlag_TXP (_SPI )) {
603+ if (spi_transfer_timed_out (start_us )) {
604+ ret = SPI_TIMEOUT ;
605+ goto spi_transfer_end ;
606+ }
607+ }
608+ #else
584609 while (!LL_SPI_IsActiveFlag_TXP (_SPI ));
610+ #endif
585611#else
586612 while (!LL_SPI_IsActiveFlag_TXE (_SPI ));
587613#endif
588614 LL_SPI_TransmitData8 (_SPI , tx_buf ? * tx_buf ++ : 0XFF );
589615
590616#if defined(SPI_SR_RXP )
617+ #if defined(USE_HALV2_DRIVER )
618+ while (!LL_SPI_IsActiveFlag_RXP (_SPI )) {
619+ if (spi_transfer_timed_out (start_us )) {
620+ ret = SPI_TIMEOUT ;
621+ goto spi_transfer_end ;
622+ }
623+ }
624+ #else
591625 while (!LL_SPI_IsActiveFlag_RXP (_SPI ));
626+ #endif
592627#else
593628 while (!LL_SPI_IsActiveFlag_RXNE (_SPI ));
594629#endif
@@ -598,17 +633,24 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff
598633 LL_SPI_ReceiveData8 (_SPI );
599634 }
600635 if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY ) &&
636+ #if defined(USE_HALV2_DRIVER )
637+ (spi_transfer_timed_out (start_us ))) {
638+ #else
601639 (HAL_GetTick () - tickstart >= SPI_TRANSFER_TIMEOUT )) {
640+ #endif
602641 ret = SPI_TIMEOUT ;
603642 break ;
604643 }
605644 }
606645
607646#if defined(SPI_IFCR_EOTC )
647+ spi_transfer_end :
608648 // Add a delay before disabling SPI otherwise last-bit/last-clock may be truncated
609649 // See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294
610650 // Computed delay is half SPI clock
611- delayMicroseconds (obj -> disable_delay );
651+ if (ret == SPI_OK ) {
652+ delayMicroseconds (obj -> disable_delay );
653+ }
612654
613655 /* Close transfer */
614656 /* Clear flags */
0 commit comments