Skip to main content
Visitor II
January 27, 2025
Solved

STM32H747I-DISCO Virtual Com USART Example

  • January 27, 2025
  • 9 replies
  • 3577 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

    This topic has been closed for replies.
    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

    Graduate II
    January 27, 2025

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

     

    Louie88Author
    Visitor II
    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

    Graduate II
    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

    Louie88Author
    Visitor II
    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

     

    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() ?

    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

    Louie88Author
    Visitor II
    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

     

    Graduate II
    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

     

    Louie88Author
    Visitor II
    January 28, 2025

    Okay, thanks for this note.

    Louis

    Louie88Author
    Visitor II
    January 28, 2025

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

    Louis

    Louie88Author
    Visitor II
    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

     

     

    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 

    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

    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 

    Louie88Author
    Visitor II
    January 29, 2025

    Thanks for the demo.

    Louis