2024-07-20 08:13 PM - edited 2024-07-20 08:14 PM
Hi.
I use a trigger source to trigger SPI tx/rx linked-list DMA (not circular). But have no clues how to jude if the tx/rx DMA is done. I traced the IRQ handler, it calls, the code below:
/**
* @brief DMA SPI transmit receive process complete callback.
* hdma: pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
{
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if (hspi->State != HAL_SPI_STATE_ABORT)
{
if ((hspi->hdmarx->Mode == DMA_LINKEDLIST_CIRCULAR) &&
(hspi->hdmatx->Mode == DMA_LINKEDLIST_CIRCULAR))
{
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
hspi->TxRxCpltCallback(hspi);
#else
HAL_SPI_TxRxCpltCallback(hspi);
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
}
else
{
/* Enable EOT interrupt */
__HAL_SPI_ENABLE_IT(hspi, SPI_IT_EOT);
}
}
}
It seems only when the DMA is configured as 'DMA_LINKEDLIST_CIRCULAR', the 'HAL_SPI_TxRxCpltCallback()' get called.
But in other situation, it only enable the EOT interrupt and simply return.
2024-07-20 09:37 PM - edited 2024-07-20 11:55 PM
Yeah, this looks strange to me as well. Especially since
#define DMA_LINKEDLIST_NORMAL DMA_LINKEDLIST /*!< Linear linked-list DMA channel transfer */
#define DMA_LINKEDLIST_CIRCULAR (DMA_LINKEDLIST | (0x01U)) /*!< Circular linked-list DMA channel transfer */
HAL_SPI_TransmitReceive_DMA() {
if ((hspi->hdmarx->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST) {
HAL_DMAEx_List_Start_IT() -> {
/* Enable common interrupts: Transfer Complete and Transfer Errors ITs */
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_DTE | DMA_IT_ULE | DMA_IT_USE | DMA_IT_TO));
}
}
}
So, the TC event is enabled whether mode is Circular or Linear.
For now, you can use CubeMX/ProjectManager/Advanced Settings to enable "Register Callback" For SPI,
[My mistake]
@STTwo-32 , can you please take a look? this looks like a possible bug.
2024-07-20 11:43 PM - edited 2024-07-21 04:45 AM
Hi,
Though I can register my own callback, the callback will be called only in linked-circular mode. 🙂
It seems the code intends to pass the event handling to the EOT handler, then which handler callback should I use?
2024-07-20 11:54 PM - edited 2024-07-20 11:54 PM
You're right of course. Too much coffee. Or maybe not enough.
2024-07-21 09:58 PM - edited 2024-07-21 10:10 PM
Hi,
I think my guess is right. After the EOT interrupt enabled, it will fire the SPI EOT IRQ, and the SPI IRQ handler will be called, then the same TxRx complete interrupt callback will be called. So, the strategy is mask the SPI's EOT interrupt, and let DMA engine to handle burst events, and finally enable the EOT of the last burst which hands the flow back to SPI,
Thanks.