Skip to main content
Visitor II
April 23, 2024
Question

problem of using USART6 on STM32F769I DISCOVERY kit board

  • April 23, 2024
  • 11 replies
  • 2946 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.

    11 replies

    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.

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

    Graduate II
    April 24, 2024

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

    Visitor 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?

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

    Visitor 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?

    Visitor 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);
     }
    
    }

     

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

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

     

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

    Visitor 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.

    Graduate II
    April 26, 2024

    Nevermind, it's over your head.

    Visitor 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.

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