Skip to main content
Louie88
Senior
January 27, 2025
Solved

STM32H747I-DISCO Virtual Com USART Example

  • January 27, 2025
  • 9 replies
  • 3578 views

Hi,

If I understand right USART1 is used in STM32H747I-DISCO board for VCOM. I could not find any example for my board. I would like to want for an 8-byte host command using:

HAL_UART_Receive_IT(&huart1, hostCommand.buffer, 8);

 Once a command is received then I process it, I create the answer and wait for the next command. So simple. 

Noe: on CN13 pin 13 I see the command from my PC on scope, but the HAL_UART_RECEIVE_IT() never receives anything. 

Can sombody send me a short example?

Thanks,

Louie

Best answer by Tesla DeLorean

 

void USART1_IRQHandler(void) // gets called per byte/interrupt
{
 HAL_UART_IRQHandler(&huart1); // calls into HAL, it works the buffering and calls your call-back when complete
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) // call from HAL_UART_IRQHandler
{
 // Do something with the filled buffer
 ..

 HAL_UART_Receive_IT(&huart1, hostCommand.buffer, 8); // initate again (returns immediately)
}


void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
 Error_Handler(); // or manage failure
}

main()
{
 ..

 HAL_UART_Receive_IT(&huart1, hostCommand.buffer, 8); // start (returns immediately)

 while(1);
}

9 replies

Karl Yamashita
Principal
January 27, 2025

You need to be sure the NVIC is enabled for the UART which most people miss.

 

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
Louie88
Louie88Author
Senior
January 27, 2025

Hi Karl,

Thanks for the reply. Of course, it is enabled.

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 if(huart->Instance==USART1)
 {
 /** Initializes the peripherals clock
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
 PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /* Peripheral clock enable */
 __HAL_RCC_USART1_CLK_ENABLE();

 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 /**USART1 GPIO Configuration
 PB7 ------> USART1_RX
 PA9 ------> USART1_TX
 */
 GPIO_InitStruct.Pin = GPIO_PIN_7;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = GPIO_PIN_9;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 /* USART1 interrupt Init */
 HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(USART1_IRQn);
 }
}

 

Thanks,

Louis

Tesla DeLorean
Guru
January 28, 2025

HAL_UART_Receive_IT() returns immediately, you have to catch the content in the callback.

Make sure the UART is not flagging some kind of status or error, ie noise, framing, etc

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Louie88
Louie88Author
Senior
January 28, 2025

Hi Tesla DeLoran,

Thanks for the generic answer, but you know the question: How I can do that?

In stm32h7xx_it.c:

 

void USART1_IRQHandler(void)
{
	// RXNE flag will be cleared by reading of RDR register (done in call)
	// Call function in charge of handling Character reception
	USART1_CharReception_Callback();
	// Generated code
	// HAL_UART_IRQHandler(&huart1);
}

 

in main.c:

 

void USART1_CharReception_Callback(void)
{
	// Get ISR register of USART3
	uint32_t isr = huart1.Instance->ISR;

	// USART_ISR_RXNE_RXFNE	= Read Data Register or RX FIFO Not Empty
	if (isr & USART_ISR_RXNE_RXFNE)
	{
		// Read Received character. RXNE flag is cleared by reading of RDR register
		hostCommand.buffer[hostCommand.dataIndex++] = (uint8_t)huart1.Instance->RDR;
		if (hostCommand.dataIndex >= HOST_CMD_BUF_LENGTH)
			hostCommand.dataIndex = 0;
	}
}

 

The interrupt is raised once during startup one and never again.

What is wrong?

Louis

 

Andrew Neil
Super User
January 28, 2025

@Tesla DeLorean wrote:

Make sure the UART is not flagging some kind of status or error, ie noise, framing, etc



@Louie88 wrote:

Thanks for the generic answer, but you know the question: How I can do that?


Doesn't the HAL do that - via HAL_UART_IRQHandler() ?

Isn't there a HAL_UART_ErrorCallback() ?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Guenael Cadier
ST Employee
January 28, 2025

Hi @Louie88 
Are you using the Virtual COM port on ST-Link connection ?
In this case, I'm not sure you are using the right PIN for RX (PB7).
Could you try PA10 instead ?

In DK manuals and schematics, I think PA9/PA10 are mentioned for VCP connection on this board.

GuenaelCadier_1-1738051711107.png

GuenaelCadier_0-1738051495166.png

GuenaelCadier_2-1738051794603.png

Regards
Guenael

Louie88
Louie88Author
Senior
January 28, 2025

Hi Guenael,

You are absolutely right. Thanks for the note. I never checked the pinouts because those were assigned by STM32CubeMX, when I enabled the USART1 for H7 CPU.

 

Bit I double checked it. I disable USART1 first then, the PB7 was released (form USART1). But when I enable USART1 again the STM32CubeMX always assigns PB7 instead of PA10 as RX pin. You found a bug in STM32CubeMX, I think.

Currently I am not in the office, but I will check it during this afternoon and report back what I found to you.. 

Thanks again! It seems to be very valuable notice.

Louis

 

Karl Yamashita
Principal
January 28, 2025

That's not a bug. USART1 has 3 user selectable Rx pins, and 3 user selectable Tx pins. You just have to override what CubeMX selects when you enable USART1. So in CubeMX, left click PA9 and PA10 pins and choose USART1 Tx and Rx configuration. 

Or search for it. For Rx example, you can see the 3 black pins that are available

KarlYamashita_0-1738059677540.png

 

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
Louie88
Louie88Author
Senior
January 28, 2025

Okay, thanks for this note.

Louis

Louie88
Louie88Author
Senior
January 28, 2025

Yes Andrew, I did it. The board "knows" itself.

Louis

Louie88
Louie88Author
Senior
January 28, 2025

Hi Andrew,

It is not so simple.

CobeMX automatically generates PB7 = Rx, but the discovery card uses PA10 = Rx. This is Guenael's fix.

But, this is only one half of the fix.

The other half is from TeslaDeLorean:

HAL_UART_Receive_IT() returns immediately, you have to catch the content in the callback. 

Which means I have read and store each received bytes int the UART1 ISR because HAL_UART_Receive_IT() does not do it for me.

With these two fixes the communication works nice.

Thanks for the help from all of you!

Best regards,

Louis

 

 

Andrew Neil
Super User
January 28, 2025

@Louie88 wrote:

CubeMX automatically generates PB7 = Rx, but the discovery card uses PA10 = Rx.


Again, did you tell CubeMX that it's an STM32H747I-DISCO board?

When you tell CubeMX that it's an STM32H747I-DISCO board, it should know what pins to use for the VCP.

If it's using the wrong ones, that's a bug in CubeMX.

@Guenael Cadier 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Guenael Cadier
ST Employee
January 28, 2025

@Andrew Neil, @Louie88 
I checked with latest CUBEMX 6.13.0, starting a brand new project from "Acces to BAORD Selector", then picked up the

GuenaelCadier_0-1738073115912.png

Then, i choose to initialize all peripherals to their default configs.
And I could check that PA9/PA10, are properly assigned to USART1 TX/RX.

GuenaelCadier_1-1738073450949.png

So no issue in CubeMX from my point of view.

Best regards

Andrew Neil
Super User
January 28, 2025

Indeed.

I just tried creating a project for the STM32H747I-DISCO board, and CubeMX clearly identifies the pins connected to the ST-Link VCP:

AndrewNeil_0-1738075015440.png

@Louie88 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Louie88
Louie88Author
Senior
January 29, 2025

Thanks for the demo.

Louis