Skip to content

Commit 58dbf25

Browse files
committed
fix(spi): bound HAL v2 polling transfers
1 parent f326cf1 commit 58dbf25

1 file changed

Lines changed: 43 additions & 1 deletion

File tree

‎libraries/SPI/src/utility/spi_com.c‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@
2020
extern "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

Comments
 (0)