Skip to main content
Associate II
April 23, 2024
Question

problem of using USART6 on STM32F769I DISCOVERY kit board

  • April 23, 2024
  • 17 replies
  • 2996 views

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!

This topic has been closed for replies.

17 replies

ST Technical Moderator
April 24, 2024

 

Hello @phoenixjia,

 

You should check your UART configuration (the baud rate, data bits, parity, and stop bits) as this could cause issues with receiving data.

Maybe you are not calling HAL_UART_Receive_IT correctly and this could interfere with the reception function.

Please share your code to see how the functions are called and implemented.

If possible, share also a logic analyzer result.

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Tesla DeLorean
Guru
April 24, 2024

>>Any thoughts what could be the root cause? Thanks!

Timing and synchronization? Misplaced expectations? Race conditions?

With Async Serial you're likely to have to parse and synchronize data reception. Lead packets with preamble/sync bytes, or synchronize on terminating characters, ie <CR><LF>

Source and Destination devices might not be in sync, data might be lost or corrupt. Plan accordingly.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Principal
April 24, 2024

Attach your code so we can see what you're doing and if doing it correctly. 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate II
April 25, 2024

It is the uart set up issue. On the receiver side, once the uart init is completed and "HAL_UART_Receive_IT" is called, "USART6_IRQHandler" is triggered and the "errorflags" inside "HAL_UART_IRQHandler" is set to 2, which falls into "UART frame error". Then all the following transmit data have one byte shifted.

So what could be reason to trigger this "uart frame error" after uart is started?

Karl Yamashita
Principal
April 25, 2024

If you disconnect the other board, do you still get an error when the receiver board POR?

 

Is the transmitter sending while the receiver starts up? 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate II
April 25, 2024

Yes, it even occurs on the standalone board. It occurs right after the "HAL_UART_Receive_IT" is called during power up. Is the uart init wrong?

Associate II
April 25, 2024

Here is the code the we use to set up the uart6. Should "GPIO_PIN_7" and "GPIO_PIN_6" be set as "GPIO_PULLUP"?

 

 

#define ARD_D0_RX_Pin GPIO_PIN_7
#define ARDUINO_TX_D1_Pin GPIO_PIN_6

static constexpr uint32_t VCP_TX_Pin = GPIO_PIN_9;
#define VCP_TX_GPIO_Port GPIOA

static constexpr GPIO_InitTypeDef	m_UartInitializeTXPins =
{
	VCP_TX_Pin,
	GPIO_MODE_AF_PP,
	GPIO_NOPULL,
	GPIO_SPEED_FREQ_LOW,
	GPIO_AF7_USART1,
};


static constexpr uint32_t VCP_RX_Pin = GPIO_PIN_10;
#define VCP_RX_GPIO_Port GPIOA

static constexpr GPIO_InitTypeDef	m_UartInitializeRXPins =
{
	VCP_RX_Pin,
	GPIO_MODE_AF_PP,
	GPIO_NOPULL,
	GPIO_SPEED_FREQ_VERY_HIGH,
	GPIO_AF7_USART1,
};

static constexpr uint32_t CC_TX_Pin = GPIO_PIN_6;
#define CC_TX_GPIO_Port GPIOC

static constexpr GPIO_InitTypeDef	m_Uart6InitializeTXPins =
{
	CC_TX_Pin,
	GPIO_MODE_AF_PP,
	GPIO_NOPULL,
	GPIO_SPEED_FREQ_VERY_HIGH,
	GPIO_AF8_USART6,
};


static constexpr uint32_t CC_RX_Pin = GPIO_PIN_7;
#define CC_RX_GPIO_Port GPIOC

static constexpr GPIO_InitTypeDef	m_Uart6InitializeRXPins =
{
	CC_RX_Pin,
	GPIO_MODE_AF_PP,
	GPIO_NOPULL,
	GPIO_SPEED_FREQ_VERY_HIGH,
	GPIO_AF8_USART6,
};


// Forward Declarations -------------------------------------------------------
static void ConfigureClocksAndGPIO(UART_HandleTypeDef* huart);


// ============================================================================
// Implementation -------------------------------------------------------------
// ============================================================================
void USART1_UART_Init(void)
{
//	using namespace Global;
 memset(&huart1, 0x0, sizeof(huart1));
	huart1.Instance = USART1;

	huart1.Init.BaudRate = 115200;
	huart1.Init.WordLength = UART_WORDLENGTH_8B;
	huart1.Init.StopBits = UART_STOPBITS_1;
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

	huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 if(HAL_UART_DeInit(&huart1) != HAL_OK)
 {
 Error_Handler();
 }
	if (HAL_UART_Init(&huart1) != HAL_OK)
	{
		Error_Handler();
	}

	// Enable UART receive complete interrupt
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
	HAL_NVIC_EnableIRQ(USART1_IRQn);
}

void USART6_UART_Init(void)
{
 memset(&huart6, 0x0, sizeof(huart6));

 huart6.Instance = USART6;
 huart6.Init.BaudRate = 115200;
 huart6.Init.WordLength = UART_WORDLENGTH_8B;
 huart6.Init.StopBits = UART_STOPBITS_1;
 huart6.Init.Parity = UART_PARITY_NONE;
 huart6.Init.Mode = UART_MODE_TX_RX;
 huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart6.Init.OverSampling = UART_OVERSAMPLING_16;
 huart6.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
 huart6.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 if(HAL_UART_DeInit(&huart6) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_UART_Init(&huart6) != HAL_OK)
 {
 Error_Handler();
 }
 // Enable UART receive complete interrupt
// __HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE);
 HAL_NVIC_SetPriority(USART6_IRQn, 15, 0);
 HAL_NVIC_EnableIRQ(USART6_IRQn);
}


void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
 ConfigureClocksAndGPIO(huart);
}


static void ConfigureClocksAndGPIO(UART_HandleTypeDef* huart)
{
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(huart->Instance == USART1)
 {
 // Peripherals clock Initialization -----------------------------------

 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
 PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;

 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 __HAL_RCC_USART1_CLK_ENABLE();	// Peripheral clock enable

 // GPIO Configuration -------------------------------------------------
 // PA10 ---> USART1_RX
 // PA9 ---> USART1_TX

 GPIO_InitTypeDef* ptr = nullptr;

 __HAL_RCC_GPIOA_CLK_ENABLE();

 ptr = const_cast<GPIO_InitTypeDef*>(&m_UartInitializeRXPins);
 HAL_GPIO_Init(VCP_RX_GPIO_Port, ptr);

 ptr = const_cast<GPIO_InitTypeDef*>(&m_UartInitializeTXPins);
 HAL_GPIO_Init(VCP_TX_GPIO_Port, ptr);
 }
 else if(huart->Instance == USART6)
 {

 /** Initializes the peripherals clock
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART6;
 PeriphClkInitStruct.Usart6ClockSelection = RCC_USART6CLKSOURCE_PCLK2;

 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /* Peripheral clock enable */
 __HAL_RCC_USART6_CLK_ENABLE();

 /**USART6 GPIO Configuration
 PC7 ------> USART6_RX
 PC6 ------> USART6_TX
 */
 GPIO_InitTypeDef* ptr = nullptr;

 __HAL_RCC_GPIOC_CLK_ENABLE();

 ptr = const_cast<GPIO_InitTypeDef*>(&m_Uart6InitializeRXPins);
 HAL_GPIO_Init(CC_RX_GPIO_Port, ptr);

 ptr = const_cast<GPIO_InitTypeDef*>(&m_Uart6InitializeTXPins);
 HAL_GPIO_Init(CC_TX_GPIO_Port, ptr);
 }

}

 

Karl Yamashita
Principal
April 26, 2024

When posting code, use the code sample which formats it and makes it easier to read the code.

KarlYamashita_0-1714103078687.png

 

You need to post the rest of your code so we can see how you're enabling the UART interrupt and what you're doing  the callback

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate II
April 26, 2024

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
	}
}

 

Karl Yamashita
Principal
April 26, 2024

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.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate II
April 26, 2024

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.

Karl Yamashita
Principal
April 26, 2024

Nevermind, it's over your head.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Associate II
April 26, 2024

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.

Karl Yamashita
Principal
April 27, 2024

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. 

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source