2020-11-16 05:03 PM
My Board is the STM32-G431KB Nucleo-32. I have a Mavlink Serial Tx/Rx (From a PX4 Autopilot) connected to PA10/PA9.
I am attempting to receive serial data at 115200 8N1 on UART1 and then send it at the same rate on UART2. I am just doing a basic polling implementation of HAL_UART_Receive() grabbing a single byte at a time.
Unfortunately, HAL_UART_Receive only gets the first byte and transmits it. After the first loop, HAL_UART_Receive doesn't get any new data from the serial line. I can see there is good data coming in on UART1 with a logic analyzer. If I don't set to 0 in the while loop, it just transmits out the last byte received over and over.
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* Infinite loop */
while (1)
{
uint8_t c = 0;
HAL_UART_Receive(&huart1, &c, 1, 1);
HAL_UART_Transmit(&huart2, &c, sizeof(c), 0xFFFF);
}
}
Can anyone point out where I'm going wrong? I expected HAL_UART_Receive to work like Arduino's 'serial->read'. Is there another step to force HAL_UART to grab a new byte?
Edit:
Using @KnarfB 's example below and the "uart forwarding" works fine. Incoming bytes on UART1 are transmitted out UART2 - as I intended.
while (1)
{
if( USART1->ISR & USART_ISR_RXNE ) {
char c = USART1->RDR & 0xFF;
while( (USART2->ISR & USART_ISR_TXE) == 0 );
USART2->TDR = c;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//HAL_Delay(20);
}
Can anyone explain to me what I'm doing wrong with HAL_UART_Receive?
Edit: I believe I solved this by setting the parameter 'Fifo Mode' to 'Enable'
Solved! Go to Solution.
2020-11-17 08:58 AM
HAL_UART_Receive returns HAL_TIMEOUT whether I set the timeout to 1ms or 5000ms. Which is odd because I can see data on the line with a logic analyzer
2020-11-17 08:58 AM
It looks like HAL_UART_Receive is returning '3' (HAL_TIMEOUT) after the first byte.
2020-11-17 09:06 AM
Thanks, your above code works fantastic by changing the USART2 on lines 5 and 6 to USART1. STM32G431KB is streaming the mavlink from uart1 to uart2 and receiving fine on my desktop.
I can't figure out why this doesn't work with the HAL_UART_Receive.
2020-11-17 09:17 AM
Hi DWalt.1, good to hear that it works for you. Don't have a STM32G431KB but a STM32G431RB. If you send my the complete sources I will look at it.
KnarfB
2020-11-17 11:15 AM
I may have solved this by setting Fifo Mode to "Enable". By default, this Parameter is disabled.
@KnarfB does this sound right?
2020-11-17 11:18 AM
Luckily my final implementation is not serial forwarding, but this was an initial step to ensure I was getting the correct serial data.
I may have solved this by setting the 'Fifo Mode' to 'Enable' which was not the default value. Does this sound correct?
2020-11-17 02:54 PM
Well, I suggested to check if there was overflow in UART (UART_ISR.ORE), but if yes, FIFO might have solved it.
The fundamental difference between KnarfB's code and Cube/HAL is, that, as I've said above, Cube's Tx routine waits until TC after the last character.
JW
2020-11-18 12:17 AM
Glad you solved it. Two minor remarks.
The HAL loop worked for me on STM32-G431RB Nucleo-64 when not using timeouts, i.e.
while (1)
{
HAL_StatusTypeDef status = HAL_UART_Receive(&huart2, &c, 1, 0 );
if (status == HAL_OK) {
HAL_UART_Transmit(&huart2, &c, sizeof(c), 0 );
}
}
Basically, if you start using timeouts, HAL uses SysTick which is comparatively slow (1ms) and not well suited for single char timeouts. And yes, with timeouts I saw overflows as @Community member suspected. The bad thing is that the HAL API encourages using timeouts.
FIFO mode is only avail in some MCU series and I haven't used it here, but I know it from the famous 16550 UART and clones. Proper error handling and recovery can be a serious issue for serial comm. This might get worse when FIFOs are used.
PS: I was surprised to see that the G4 Nucleo-32 board has the SWO pin available. This is a nice debugging aid for debugging by tracing, previously available only on larger boards.
2020-11-18 10:23 AM
Fantastic answer, thanks for the information. This is my first time tipping my toes into "real" embedded development as most of my experience is working with arduino. I am just trying to achieve an initial start point with some working serial comms and can look at a more robust implementation down the road.