2024-04-22 09:17 PM
I am using the usart6 port (PC6 and PC7) on a STM32F769I DISCOVERY board to communicate with another STM32F769I DISCOVERY board. I use cubemx generated code "MX_USART6_UART_Init" to initiate the usart6 and use "HAL_UART_Transmit" on sender and "HAL_UART_Receive_IT" on receiver. The problem I have now is the received data shifts one byte to right compared to the send data. Both "HAL_UART_Transmit" and "HAL_UART_Receive_IT" returns with "HAL_OK".
Any thoughts what could be the root cause? Thanks!
2024-04-26 09:05 AM - edited 2024-04-26 09:09 AM
Set "GPIO_PIN_7" and "GPIO_PIN_6" as "GPIO_PULLUP" solved the problem. No more error interrupts from USART6.
Here is the code on the receiver side,
void HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart)
{
if (huart->Instance == USART1)
{
UART1_RxComplete();
}
else if(huart->Instance==USART6)
{
UART6_RxComplete();
}
return;
}
extern void UART6_RxComplete(void)
{
// Put it into the RingBuffer
TransferFrame* pFrame = CC_RB.Put();
uint8_t* ptr = reinterpret_cast<uint8_t*>(pFrame);
if (ptr)
{
hal_status = HAL_UART_Receive_IT(huart6, static_cast<uint8_t*>(ptr), sizeof(TransferFrame));
if( hal_status != HAL_OK)
{
ret = UARTStatus::ERROR;
Error_Handler();
}
}
else
{
assert (false && "Buffer is full"); // Buffer is full
}
}
2024-04-26 09:50 AM
Sounds like a race condition. The Tx output is a pull-push type so you wouldn't need a pull-up on the Rx line.
So i'm guessing that your Transmitting board must be powering up at the same time as the receiving board but hasn't set up the Tx pin before the receiving board has the uart ready and set the output high. So the receiver board must be seeing a low on the Rx line and sees it as a start condition.
You should see if HAL_UART_ErrorCallback is called? If so, you can call HAL_UART_GetError which will probably return a frame error.
2024-04-26 10:10 AM
It has nothing to do with the Transmitter and Receiver. As I mentioned before, the error interrupt occurs even on the standalone board, without two boards being connected. After updating "GPIO_PIN_7" and "GPIO_PIN_6" from "GPIO_NOPULL" to "GPIO_PULLUP", no more error interrupts.
2024-04-26 10:28 AM
Nevermind, it's over your head.
2024-04-26 11:31 AM
Please use your words politely.
Could you please explain why I got error interrupts on the standalone board, and it is gone after I set up "GPIO_PULLUP"? It is in my head, not over yet.
2024-04-26 05:28 PM
Adding the the pull-up on the Rx line is no different from the Tx on the other board being set to high, once the UART is initialized. So it's a race condition as I mentioned before.
When you disconnected the other board, the Rx isn't being set to high from the other board anymore. So you've made the Rx input float which would cause an unknown input state. Yes the pull-up fixed your issue because you've replaced what the other board would have essentially done by setting the Rx input high.
2024-04-29 09:41 AM
It is not the race condition. Both boards are set up as the combination of transmitter and receiver so it does not matter which one starts first. It occurs randomly (not always) in both the standalone board and two boards connected, and it is usually fixed by just reset the program (by software reset in IAR).
I think the problem is that Rx input is float when it is set up as "GPIO_NOPULL", which causes an unknown input state during start up. It triggers error interrupts right after the start up.
2024-04-29 10:47 AM
You need to Google about push-pull and open collector outputs. Once your learn about push-pull which UART uses, you'll soon understand that the Rx line would be pulled to high once the transmitting board is initialized.
If you look at any of ST's Nucleo boards which uses UART for the VCP between the debugger
MCU and the actual STM32, you'll see they don't use internal/external pull-ups.
I2C uses open collector output so that is why you must have pull-ups for that type of peripherals but not for UART.