2026-04-15 1:35 AM - edited 2026-04-15 1:46 AM
Hello,
I am facing an issue with the STM32C5 HAL SPI driver related to CRC error detection.
In my setup, CRC is enabled for SPI. When a CRC error occurs, I can observe that the CRCERR flag is set before the transfer is closed. However, the CRC error is never reported via the HAL error callback.
Looking into the HAL implementation, I noticed the following behavior:
Additionally, in my case SPI_CloseTransfer() is called from HAL_SPI_IRQHandler(), but:
From my understanding:
Could you please clarify:
I would appreciate guidance or confirmation whether this is a HAL bug.
Best regards
Christian
Solved! Go to Solution.
2026-04-17 7:35 AM - edited 2026-04-17 7:35 AM
Hello @ChristianZ,
The developer had the same doubts about the other error flags and created the following fix, which will also be included in the release:
diff --git a/Code/c5/hal_spi.c b/Code/c5/hal_spi.c
index 7ad8f4f..1779cc7 100644
--- a/Code/c5/hal_spi.c
+++ b/Code/c5/hal_spi.c
@@ -5276,18 +5276,6 @@
}
#endif /* USE_HAL_SPI_CRC */
- LL_SPI_Disable((SPI_TypeDef *)((uint32_t)hspi->instance));
-
- /* Disable ITs */
- LL_SPI_DisableIT((SPI_TypeDef *)((uint32_t)hspi->instance),
- LL_SPI_IT_EOT | LL_SPI_IT_TXP | LL_SPI_IT_RXP | LL_SPI_IT_DXP |
- LL_SPI_IT_UDR | LL_SPI_IT_OVR | LL_SPI_IT_TIFRE | LL_SPI_IT_MODF);
-
-#if defined(USE_HAL_SPI_DMA) && (USE_HAL_SPI_DMA == 1)
- LL_SPI_DisableDMAReq_TX((SPI_TypeDef *)((uint32_t)hspi->instance));
- LL_SPI_DisableDMAReq_RX((SPI_TypeDef *)((uint32_t)hspi->instance));
-#endif /* USE_HAL_SPI_DMA */
-
/* Report Underrun error for non RX Only communication */
if (hspi->global_state != HAL_SPI_STATE_RX_ACTIVE)
{
@@ -5340,6 +5328,19 @@
status = HAL_ERROR;
}
+
+ LL_SPI_Disable((SPI_TypeDef *)((uint32_t)hspi->instance));
+
+ /* Disable ITs */
+ LL_SPI_DisableIT((SPI_TypeDef *)((uint32_t)hspi->instance),
+ LL_SPI_IT_EOT | LL_SPI_IT_TXP | LL_SPI_IT_RXP | LL_SPI_IT_DXP |
+ LL_SPI_IT_UDR | LL_SPI_IT_OVR | LL_SPI_IT_TIFRE | LL_SPI_IT_MODF);
+
+#if defined(USE_HAL_SPI_DMA) && (USE_HAL_SPI_DMA == 1)
+ LL_SPI_DisableDMAReq_TX((SPI_TypeDef *)((uint32_t)hspi->instance));
+ LL_SPI_DisableDMAReq_RX((SPI_TypeDef *)((uint32_t)hspi->instance));
+#endif /* USE_HAL_SPI_DMA */
+
hspi->tx_xfer_count = (uint16_t)0UL;
hspi->rx_xfer_count = (uint16_t)0UL;
Regarding CRC no longer being inside the if (hspi->global_state != HAL_SPI_STATE_TX_ACTIVE) statement, this is expected, since this case should be handled in all cases, not only in HAL_SPI_STATE_TX_ACTIVE.
For example, it may be necessary when the state is HAL_SPI_STATE_TX_RX_ACTIVE.
As for the release date of the next HAL2 update, there is still no fixed date I can share.
Best regards,
2026-04-15 2:02 AM
Hello @ChristianZ, and Welcome to ST Community!
I have escalated the issue to the relevant team for resolution. It is being tracked internally under ticket number CDM0061755.
Best regards,
2026-04-15 8:39 AM
Hello,
this thread has been moved to the STM32 MCUs Embedded software forum because it relates only to HAL2, not STM32CubeMX2. This will help improve visibility and ensure the right experts are involved.
Regards,
Sara.
2026-04-16 8:10 AM
Hello @ChristianZ,
I have just received the following fix for the issue you are encountering:
- (void)SPI_CloseTransfer(hspi);
+ if (SPI_CloseTransfer(hspi) != HAL_OK)
+ {
+#if defined(USE_HAL_SPI_REGISTER_CALLBACKS) && (USE_HAL_SPI_REGISTER_CALLBACKS == 1)
+ hspi->p_error_cb(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
This patch will be available in the next releases of HAL2 for all products, including C5.
Best regards,
2026-04-17 12:49 AM
Hello @STackPointer64,
thank you for your response.
Is this behavior only relevant in HAL_SPI_IRQHandler()? What about the other transfer methods (e.g. polling or DMA)?
From my analysis, this fix does not work in my case. SPI_CloseTransfer() never returns HAL_ERROR when a CRC error occurs, because the CRC error flag seems to be cleared by LL_SPI_Disable() (line 5256).
When I move the USE_HAL_SPI_CRC section (lines 5295–5309) before the call to LL_SPI_Disable(), the CRC error is detected correctly and status is set to HAL_ERROR. With the additional fix you mentioned regarding the SPI_CloseTransfer() return value, the error callback is then triggered as expected.
Did this really work for you without modifying SPI_CloseTransfer()? If so, could you please clarify how this was tested, or what I might be missing?
Thank you very much for your help.
Best regards,
Christian
2026-04-17 2:04 AM
Hello @ChristianZ,
This is the rest of the fix regarding CRC:
diff --git a/Code/c5/hal_spi.c b/Code/c5/hal_spi.c
index 35affef..7ad8f4f 100644
--- a/Code/c5/hal_spi.c
+++ b/Code/c5/hal_spi.c
@@ -5260,6 +5260,22 @@
/* Clear the Status flags in the SR register */
LL_SPI_ClearFlag((SPI_TypeDef *)((uint32_t)hspi->instance), LL_SPI_FLAG_EOT | LL_SPI_FLAG_TXTF);
+#if (USE_HAL_SPI_CRC != 0UL)
+ /* Check if CRC error occurred */
+ if (LL_SPI_IsEnabledCRC((SPI_TypeDef *)((uint32_t)hspi->instance)) != 0UL)
+ {
+ if (LL_SPI_IsActiveFlag_CRCERR((SPI_TypeDef *)((uint32_t)hspi->instance)) != 0UL)
+ {
+#if defined(USE_HAL_SPI_GET_LAST_ERRORS) && (USE_HAL_SPI_GET_LAST_ERRORS == 1)
+ STM32_SET_BIT(hspi->last_error_codes, HAL_SPI_ERROR_CRC);
+#endif /* USE_HAL_SPI_GET_LAST_ERRORS */
+ LL_SPI_ClearFlag_CRCERR((SPI_TypeDef *)((uint32_t)hspi->instance));
+
+ status = HAL_ERROR;
+ }
+ }
+#endif /* USE_HAL_SPI_CRC */
+
LL_SPI_Disable((SPI_TypeDef *)((uint32_t)hspi->instance));
/* Disable ITs */
@@ -5298,22 +5314,6 @@
status = HAL_ERROR;
}
-
-#if (USE_HAL_SPI_CRC != 0UL)
- /* Check if CRC error occurred */
- if (LL_SPI_IsEnabledCRC((SPI_TypeDef *)((uint32_t)hspi->instance)) != 0UL)
- {
- if (LL_SPI_IsActiveFlag_CRCERR((SPI_TypeDef *)((uint32_t)hspi->instance)) != 0UL)
- {
-#if defined(USE_HAL_SPI_GET_LAST_ERRORS) && (USE_HAL_SPI_GET_LAST_ERRORS == 1)
- STM32_SET_BIT(hspi->last_error_codes, HAL_SPI_ERROR_CRC);
-#endif /* USE_HAL_SPI_GET_LAST_ERRORS */
- LL_SPI_ClearFlag_CRCERR((SPI_TypeDef *)((uint32_t)hspi->instance));
-
- status = HAL_ERROR;
- }
- }
-#endif /* USE_HAL_SPI_CRC */
}
/* SPI Mode Fault error interrupt occurred -------------------------------*/
Best regards,
2026-04-17 2:55 AM
Hello @STackPointer64,
thank you for the clarification.
What about the other error flags – are they affected in a similar way and would they also need to be evaluated before calling LL_SPI_Disable()?
Additionally, if only the CRC handling is moved, it would no longer be inside if (hspi->global_state != HAL_SPI_STATE_TX_ACTIVE) { ... } together with the LL_SPI_IsActiveFlag_OVR() check.
In this case, is moving only the CRC part considered the correct and complete fix, or is it intended as an intermediate workaround?
Finally, is there already any information available regarding the schedule for the next HAL2 driver release?
Best regards,
2026-04-17 7:35 AM - edited 2026-04-17 7:35 AM
Hello @ChristianZ,
The developer had the same doubts about the other error flags and created the following fix, which will also be included in the release:
diff --git a/Code/c5/hal_spi.c b/Code/c5/hal_spi.c
index 7ad8f4f..1779cc7 100644
--- a/Code/c5/hal_spi.c
+++ b/Code/c5/hal_spi.c
@@ -5276,18 +5276,6 @@
}
#endif /* USE_HAL_SPI_CRC */
- LL_SPI_Disable((SPI_TypeDef *)((uint32_t)hspi->instance));
-
- /* Disable ITs */
- LL_SPI_DisableIT((SPI_TypeDef *)((uint32_t)hspi->instance),
- LL_SPI_IT_EOT | LL_SPI_IT_TXP | LL_SPI_IT_RXP | LL_SPI_IT_DXP |
- LL_SPI_IT_UDR | LL_SPI_IT_OVR | LL_SPI_IT_TIFRE | LL_SPI_IT_MODF);
-
-#if defined(USE_HAL_SPI_DMA) && (USE_HAL_SPI_DMA == 1)
- LL_SPI_DisableDMAReq_TX((SPI_TypeDef *)((uint32_t)hspi->instance));
- LL_SPI_DisableDMAReq_RX((SPI_TypeDef *)((uint32_t)hspi->instance));
-#endif /* USE_HAL_SPI_DMA */
-
/* Report Underrun error for non RX Only communication */
if (hspi->global_state != HAL_SPI_STATE_RX_ACTIVE)
{
@@ -5340,6 +5328,19 @@
status = HAL_ERROR;
}
+
+ LL_SPI_Disable((SPI_TypeDef *)((uint32_t)hspi->instance));
+
+ /* Disable ITs */
+ LL_SPI_DisableIT((SPI_TypeDef *)((uint32_t)hspi->instance),
+ LL_SPI_IT_EOT | LL_SPI_IT_TXP | LL_SPI_IT_RXP | LL_SPI_IT_DXP |
+ LL_SPI_IT_UDR | LL_SPI_IT_OVR | LL_SPI_IT_TIFRE | LL_SPI_IT_MODF);
+
+#if defined(USE_HAL_SPI_DMA) && (USE_HAL_SPI_DMA == 1)
+ LL_SPI_DisableDMAReq_TX((SPI_TypeDef *)((uint32_t)hspi->instance));
+ LL_SPI_DisableDMAReq_RX((SPI_TypeDef *)((uint32_t)hspi->instance));
+#endif /* USE_HAL_SPI_DMA */
+
hspi->tx_xfer_count = (uint16_t)0UL;
hspi->rx_xfer_count = (uint16_t)0UL;
Regarding CRC no longer being inside the if (hspi->global_state != HAL_SPI_STATE_TX_ACTIVE) statement, this is expected, since this case should be handled in all cases, not only in HAL_SPI_STATE_TX_ACTIVE.
For example, it may be necessary when the state is HAL_SPI_STATE_TX_RX_ACTIVE.
As for the release date of the next HAL2 update, there is still no fixed date I can share.
Best regards,
2026-04-21 4:08 AM
Hello @ChristianZ,
Did the fix solve your issue? If so, please click “Accept as Solution” on the reply that resolved your issue or answered your question.
Best regards,