cancel
Showing results for 
Search instead for 
Did you mean: 

How do I process just UART RX interrupt events while using HAL_UART_Transmit_IT

magene
Senior II

I've run into another hurdle I don't seem to be able to solve myself while trying to learn embedded STM32 programming. I have a simple test program that transmits characters over a UART with the RX and TX pins looped together and receives them using interrupts. When I transmit the data using HAL_UART_Transmit, I can process the received characters in my IRQHandler fine. But when I use HAL_UART_Transmit_IT, my IRQHandler puts 2 characters in my receive buffer for every character I transmit. I'm pretty sure this is because my IRQHandler is getting called for every character transmitted and every character received. You can see how I tried to only process received characters in my IRQHandler below but it hangs up after a few characters. Any ideas on what I'm doing wrong or any ideas on a better way to do this will be greatly appreciated.

Thanks

PS In the long run, I'd like to make this work with DMA and end the transfer using the character match interrupt. I've got that working on a STM32H7A3 Nucleo board but not on the STM32H7B3Discovery board that I need to use. So I'm working on this IT method for now.

initUART4();
	
	uint8_t txBuffer[] = { "$PUBX,00*33\r\n" };
 
	memset(rxBuffer, 0, sizeof(rxBuffer));
	memset(gpsMessage, 0, sizeof(gpsMessage));
	msgReceivedUART4 = false;
	
	HAL_UART_Receive_IT(&uart4Handle, rxBuffer, 1);
	HAL_UART_Transmit(&uart4Handle, txBuffer, sizeof(txBuffer), 2000);	//This works
	//HAL_UART_Transmit_IT(&uart4Handle, txBuffer, sizeof(txBuffer));		//This doesn't work
 
	while (1)
	{
		//Do other stuff
		
		if(msgReceivedUART4)
		{
			//process UART4msg
			HAL_Delay(1);
		}
	}
}
 
void UART4_IRQHandler()
{
	HAL_UART_IRQHandler(&uart4Handle);
//	if (__HAL_UART_GET_FLAG(&uart4Handle, UART_FLAG_RXNE))
//	{
		if (rxBuffer[0] != 0)
		{
			gpsMessage[gpsMsgCount] = rxBuffer[0];
			gpsMsgCount++;
		}
		if (rxBuffer[0] == '\n')
		{
			fifoEnqueue(rxBuffer);	
			msgReceivedUART4 = true;
		}
		else
			HAL_UART_Receive_IT(&uart4Handle, rxBuffer, 1);
//	}
}

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Use the HAL callbacks, which only get called if the relevant flags are set. In this case, HAL_UART_RxCpltCallback.

The flags are checked and cleared within HAL_UART_IRQHandler, so checking for them after that will not be useful.

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

View solution in original post

3 REPLIES 3
TDK
Guru

Use the HAL callbacks, which only get called if the relevant flags are set. In this case, HAL_UART_RxCpltCallback.

The flags are checked and cleared within HAL_UART_IRQHandler, so checking for them after that will not be useful.

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

> HAL_UART_Receive_IT(&uart4Handle, rxBuffer, 1)

Using HAL_UART_Receive_IT to receive one byte is a terrible idea because it disables RX interrupt immediately after receive, so there's a window when incoming bytes can be lost . @Piranha​ and other prominent anti-HALers pointed this out many times.

If you cannot get DMA workng, write your own interrupt handler without calling any HAL stuff, and try to enable FIFO

(this works well for me on H743/753).

--pa

magene
Senior II

@TDK​ That worked like a charm. I can't express how much I appreciate your help. It's still amazes me that a novice like me can get near real time help from an expert like you and on a Saturday no less.

@Pavel A.​ This is an interim step so I can make progress elsewhere. The problem is the devices I need to talk to over UARTs do not send messages with a known, repeatable packet length. They do all terminate their messages with a CRLF so that's why I'm doing it this way. I am trying to keep my IRQ handlers as short as possible so I don't drop bytes. All I can say is it seems to be working for now at the low baud rates my devices work at. It will be interesting to see how many devices and how high a baud rate this approach will work at.  As you noted, I'm working on the DMA approach with character match (hence the STM32H7 family) and idle detection but haven't gotten it working yet on the H7B3 Discovery board yet. I'm well aware of how nearly unworkable and painful the STM HAL is and I'd love to dump it but I just don't know enough to take that step yet. At this point, I think it's still more time effective for me to bumble through the learning curve using HAL than stop progress entirely trying to figure out how to do this stuff without HAL.

@TDK​ , @Pavel A.​ , @Piranha​  I do have a full time job designing and building Oceanographic research equipment and this is just a background task for now. I hope porting my existing hardware and software to STM32 and C/C++ will fit into my foreground schedule for next year and I am absolutely in the market for a competent STM32 consultant. If you're interested or know someone, please let me know.