cancel
Showing results for 
Search instead for 
Did you mean: 

How to perform continuous sending and reading with DMA ?

DYann.1
Senior

Hello,

I looked at an example of DMA on CubeMX and I got this code :

 

 

 /* Infinite loop */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if (transferErrorDetected == 1)
    {
      /* Toggle LED4 with a period of 200 ms */
      BSP_LED_Toggle(LED4);
      HAL_Delay(200);
    }
    if (transferCompleteDetected == 1)
    {
      /* Turn LED4 on*/
      BSP_LED_On(LED4);
      transferCompleteDetected = 0;
    }
  }
  /* USER CODE END 3 */
}

 

 

It only works once, how to repeat this sending infinitely ?

 

 

  /* Configure the source, destination and buffer size DMA fields and Start DMA Channel/Stream transfer */
  /* Enable All the DMA interrupts */
  if (HAL_DMA_Start_IT(&hdma_memtomem_dma1_channel1, (uint32_t)&aSRC_Const_Buffer, (uint32_t)&aDST_Buffer, BUFFER_SIZE) != HAL_OK)
  {
    /* Transfer Error */
    Error_Handler();
  }

 

Do I have to stop the DMA, recover the data and restart the DMA each time ?

 Thank you for your answer

10 REPLIES 10
Tinnagit
Senior II

what type of DMA that you use?
Circular?

with address memory increasing?

and You had DMA Callback function too?

Hi,

This is an example that I took from my STM32L552E-EV evaluation board. It's called DMA. No It's not circular after CubeIDE

DYann1_0-1701781230975.png

After the readme file, it's only a transfer from Flash memory to RAM memory (after me).

DYann1_1-1701781374573.png

Here is the address of the source and destination memory

 

static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
{
  0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
  0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
  0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
  0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
  0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
  0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
  0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
  0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
};

static uint32_t aDST_Buffer[BUFFER_SIZE];

 

BUFFER_SIZE=32

Yes I the example has a DMA_callback function :

 

  /* Select Callbacks functions called after Transfer complete and Transfer error */
  HAL_DMA_RegisterCallback(&hdma_memtomem_dma1_channel1, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);
  HAL_DMA_RegisterCallback(&hdma_memtomem_dma1_channel1, HAL_DMA_XFER_ERROR_CB_ID, TransferError);

 

Tinnagit
Senior II

if it's no Circular so it's going to stop at the end of address and you have to restart it again as usual.
when you use ADC or SPI with DMA and you set memory with many byte, it's going to stop at the end of address.
you should try with circular mode.

But I'm really unsure what feature do you want. So it may useless for you.

TDK
Guru

You can either set it to circular mode so it transfers continuously, or you can restart the transfer after the transfer is complete within the TransferComplete callback.

 

If you feel a post has answered your question, please click "Accept as Solution".

Thank you for this information, to begin with, I would like to understand how DMA works using this example provided.
In fact when I say at the start of my topic, "how to repeat this sending infinitely ?" of course if I use with ADC, I'll have values ​​continually (this sounds a bit like what I'm saying sending the values ​​continuously also requires retrieving the values ​​continuously, right ?).
I know the circular mode, and I have already implemented it with an SAI (by looping the TX with the RX) and it works. But when I enter real values ​​I don't get anything back, that's why I use this DMA example.
With this example I am trying to understand the DMA mechanism. So my question is: How to send and retrieve continuously from this example which only works once ? With the code please no pharses, this will help me move forward.

 

 

 


@TDK wrote:

or you can restart the transfer after the transfer is complete within the TransferComplete callback.

 


In the Main I have this Function :

/* USER CODE BEGIN 4 */
/**
  * @brief  DMA conversion complete callback
  * @note   This function is executed when the transfer complete interrupt
  *         is generated
  * @retval None
  */
static void TransferComplete(DMA_HandleTypeDef *hdma_memtomem_dma1_channel1)
{
  transferCompleteDetected = 1;
}

 I think this function is call when the transfer is complete. How to restart the transfer since this function I only enter once. Or probably I'm wrong about the function "TransferComplete callback".

Is it possible that there is some error while DMA transferring so it go to Error_Handler and it won't do anything like as it stopped.

No, impossible because the LED4 is on

  /* Infinite loop */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if (transferErrorDetected == 1)
    {
      /* Toggle LED4 with a period of 200 ms */
      BSP_LED_Toggle(LED4);
      HAL_Delay(200);
    }
    if (transferCompleteDetected == 1)
    {
      /* Turn LED4 on*/
      BSP_LED_On(LED4);
      transferCompleteDetected = 0;
    }
  }
  /* USER CODE END 3 */
}

and I never get into this error loop

/**
  * @brief  DMA conversion error callback
  * @note   This function is executed when the transfer error interrupt
  *         is generated during DMA transfer
  * @retval None
  */
static void TransferError(DMA_HandleTypeDef *hdma_memtomem_dma1_channel1)
{
  transferErrorDetected = 1;
}

After the while loop previously, if there is an error then LED 4 flashes per period of 200 ms but it's not the case.

It can possible because the LED was turn ON at first transfer completely and if the error was occurred at second transfer at HAL_DMA_Start_IT so it go to Error Handler without turn OFF LED.

You can check it by debug and you should also add turn OFF LED before Error Handler.