cancel
Showing results for 
Search instead for 
Did you mean: 

USART2_IRQHandler called continuously for DMA reception on STM32L031K6T6 with hardware flow control

noobmaster69
Associate III

Hi. I am using UART with DMA for TX and RX on STM32L031. It communicates with nRF52833 over UART with hwfc enabled. My problem is, when I receive data from nRF52, USART2_IRQHandler is called continuously. Below is the screenshot of all the flags that are set. Transmission from ST to Nordic works properly(tested 65535+ times). I receive around 3 data packets from nordic to ST and then the communication stops because USART2_IRQHandler is called contiuously. Why is this happening? Is there any workaroound for this? I am using STM32CubeIDE and HAL libraries on linux.

(NOTE: without HWFC it was working properly but for more reliabilty, I need HWFC. It so happend that Nrodic would drop data packets whenever it was busy transmitting bluetooth beacon)

Below is the debug log from Nordic. You can see that CTS pin is toggling continuously.

<info> app: NRF_UARTE_EVENT_CTS...
<info> app_timer: RTC: initialized.
<info> app: Debug logging for UART over RTT started.
<info> app: NRF_UARTE_EVENT_RXSTARTED...
<info> app: tx_data[0] = 01
<info> app: EVT:NRF_UARTE_EVENT_TXSTARTED
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: tx_data[0] = 02
<info> app: EVT:NRF_UARTE_EVENT_TXSTARTED
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: tx_data[0] = 03
<info> app: EVT:NRF_UARTE_EVENT_TXSTARTED
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...
<info> app: NRF_UARTE_EVENT_CTS...
<info> app: NRF_UARTE_EVENT_NCTS...

6 REPLIES 6

Suggests you're not servicing the source of the interrupt.

For example TXE, but not providing data​, or restarting DMA.

The UART typically has little internal buffering, so in flow control might help to monitor that before cramming more data across interface.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I tried clearing all the flags which were set using the following code. But no success.

	if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_REACK) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_REACK);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TEACK) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_TEACK);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_CTS) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_CTS);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_CTSIF) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_CTSIF);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_TXE);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_TC);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_RXNE);
	}
	else if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) == SET)
	{
		__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_IDLE);
	}

Dear @Community member​ 

In your attempt to clear all flags that could raise continuous USART2 IRQ, please note that some flags could not be cleared using __HAL_UART_GET_FLAG macro.

Examples :

RXNE flag is cleared by reading RDR register

TXE flag is cleared by writing some data in TDR register.

For getting a continuous interrupt, you must have a flag set in ICR, AND corresponding Interrupt Enable bit set in CRx registers.

What you could check is which flag is set in your ICR that corresponds to an enabled interrupt in CR1/CR2/CR3.

Example : having RXNE flag and RXNEIE both set.

Regards

Hi. I checked ICR but I couldnt see anything. Ive attached screenshot of the ICR. I had enabled RXNE interrupt because I wanted to know when data reception starts. I read that register in USART2_IRQHandler. But in an earlier project, I did same thing but I didnt get such problem. At that time I didnt use HWFC.

Now I am receiving all the packets but HAL_UART_RxCpltCallback function is called only once i.e. for the first data packet. After that I receive data but HAL_UART_RxCpltCallback is not called so I cant process the received data. Why is it not called?

Sorry, i made a mistake in my previous post. ICR is not of great help as would give no clue on the condition that triggers the interrupt. ISR would be better.

Please also consider that when you have a live watch on registers open in debug mode, this is actually performing read access to register. A side effect of this could be that a RXNE flag in ISR, trigerring the interrupt is automatically cleared, when USART2_IRQHandler breakpoint is reached, when debugger is reading RDR register ... So be cautious with interactions and impacts of debugger on realtime execution.

Regarding your last point, you mentioned that your callback HAL_UART_RxCpltCallback is called only once. How do you start your reception process (which HAL_UART API is called) ?

And after completion of first reception (HAL_UART_RxCpltCallback call), how do you restart it ?

I use HAL_UART_Receive_DMA to start the reception.

I have state machine for UART. Ideally, it is in WAIT_FOR_RX_START state. When reception starts (i.e. for first RXNE event), I change state to RX_START, on HAL_UART_RxCpltCallback, I change state to RX_END, and put received data in scheduler for processing and change state to WAIT_FOR_MSG_PROCESS. After received msg is processed, I change state to WAIT_FOR_RX_START and then restart reception.

So, as lomg as received msg is not processed, I dont restart next reception.