cancel
Showing results for 
Search instead for 
Did you mean: 

DMA Uart Rx occur only once

MGuil.1
Associate II

I have followed an example found on the web to get DMA RX usart2 running.

I had activate RX DMA, global interrupt in cubmx project.

In the main I have :

HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuf, RxBuf_SIZE);
  __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

and I added the callback function:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART2) {
		memcpy(MainBuf, RxBuf, Size);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuf, RxBuf_SIZE);
		__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
	}
}

Then when I launch the debbug, the callback function is well called, but only one time, and never called back again.

Did I miss something to re-activate the callback ?

I'm using a nucleo H743 board.

Thnaks for your help.

10 REPLIES 10
Muhammed Güler
Senior III

In the interrupt function, try to stop the DMA before starting it.

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART2) {
 
                HAL_UART_DMAStop(&huart2);
 
		memcpy(MainBuf, RxBuf, Size);
 
		HAL_UART_Receive_DMA(&huart2, RxBuf, RxBuf_SIZE);
		__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
	}
}

MGuil.1
Associate II

Thanks Muhammed, but that change anythings.

It seems that usart & dma interrupts are stops.

I check Timer interrupts, they are still occurs

MGuil.1
Associate II

If I add the enable IT_TC function in the callback, then it works:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART2) {
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
		memcpy(MainBuf, RxBuf, Size);
		HAL_UARTEx_ReceiveToIdle_DMA(huart, RxBuf, RxBuf_SIZE);
		__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
		__HAL_DMA_ENABLE_IT(&hdma_usart2_rx, DMA_IT_TC);
	}
}

I also add the toggle of a Led to help me and I can see it blinking each time the nucleo receive data on the usart.

But in debug mode if I add a breakpoint in the callback, application stop at the breakpoint line of code. then I resume the application and the application will never stop again. Also the led light stop blinking. If I push the reset button the led light start blinking.

What's going wrong with the debug mode ?

MGuil.1
Associate II

I'm still stuck with this debugger!

My app works without debugger, but with it, it hit the breakpoint once , it will never hit again !

I can't use it.

Any help ?

> What's going wrong with the debug mode ?

Debugging is intrusive, and reading USART registers may read data out of FIFO and clear status bits.

Also, if data source keeps transmitting, USART Rx is going to run over, and if the overrun is not handled (overrun flag cleared, typically in UART error interrupt), it stops receiving.

JW

MGuil.1
Associate II

Thanks waclawek jan,

but I manage data sent to the USART Rx. The processis:

Set breakpoint in the callback

Launch the debugger then the app is running

send 5 bits from my computer to the USART Rx of the nucleo.

The breakpoint hit in the callback, caracters are received, I read it in the buffer

Resume the debugger

send a second time caracters to the USART Rx.

never hit !

So it can't be an overrun problem! because the USART Rx only reveived 10 bits! (buffer is around 100 bits)

Read out USART and DMA/DMAMUX registers content and compare/post, after first and after second call to HAL_UARTEx_ReceiveToIdle_DMA(), before transmitting data from PC.

JW

MGuil.1
Associate II

I tried with a very simple example on my nucleo H743 with uart4. no DMA, only IT. I haven't change the code from the cubemx output, it is the same: interrupt works only once!!

uint8_t pData[20] = {0};
uint8_t Size = 1;
 
/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ETH_Init();
  MX_USART3_UART_Init();
  MX_UART4_Init();
  MX_USB_OTG_FS_PCD_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart4, pData, Size);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }

void UART4_IRQHandler(void)
{
  /* USER CODE BEGIN UART4_IRQn 0 */
 
  /* USER CODE END UART4_IRQn 0 */
  HAL_UART_IRQHandler(&huart4);
  /* USER CODE BEGIN UART4_IRQn 1 */
 
  /* USER CODE END UART4_IRQn 1 */
}

My computer send one character every second to the nucleo

The IT hit once and that's it, no more interrupt!!!! . Do I need to re-enable IT in the interrupt function (void UART4_IRQHandler(void)) ?

But SysTick_Handler interrupt are still working!

Please any idea ?I'm stuck with this issue

> The IT hit once and that's it, no more interrupt!!!! . 

How do you know? How are you observing it?

> MX_ETH_Init();

> MX_USART3_UART_Init();

> MX_UART4_Init();

> MX_USB_OTG_FS_PCD_Init();

Remove everything except UART4 and retry.

JW