cancel
Showing results for 
Search instead for 
Did you mean: 

How to know the when the DMA transfer done?

diverger
Senior

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.

 

4 REPLIES 4
BarryWhit
Senior III

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.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

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?

BarryWhit
Senior III

You're right of course. Too much coffee. Or maybe not enough.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

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.