Search code examples
stm32interruptuart

Modify the example named UART_HyperTerminal_IT to enable UART reception interrupts on STM32F4?


I'm developing a project with STM32F4 and I need to enable the UART6 receive interrupt. I have used STM32CubeMX to enable the UART6 and in the STM32CubeMX I have enabled the NVIC USART6 global interrupt.

The example UART_HyperTerminal_IT

I have followed the example UART_HyperTerminal_IT which is installed by the package STM32Cube_FW_F4_V1.27.0.
The code is more recent but not so different from this example code.

I would like to modify the example to send back every character received from UART6 on the same UART6 (echo). So I have removed all the code of the example that sends data by the UART and wait data from the UART.

I have initialized the UART6 by the following code:

UartHandle.Instance        = USART6;

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

if(HAL_UART_Init(&UartHandle) != HAL_OK) {
    /* Initialization Error */
    Error_Handler();
}

The previous code is very similar to the example code (I have changed only baud rate and the parity).

My interrupt routine

I have defined the function USART6_IRQHandler in the file stm32f4xx_it.c as in the code below:

void USART6_IRQHandler(void) {
    unsigned char ch;
    
    uint32_t isrflags   = READ_REG(huart6.Instance->SR);
    uint32_t cr1its     = READ_REG(huart6.Instance->CR1);   
    
    if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
        huart6.Instance->SR;
        ch = huart6.Instance->DR;
        HAL_UART_Transmit(&huart6, &ch, 1, 1000);
    }

    HAL_UART_IRQHandler(&huart6);
}

In the readme file of the example I have found this sentence:

This example shows how to ensure UART Data buffer transmission and reception with Interrupt.

The sentence says that in the example the Interrupt is enabled, but if I try to send data to the UART6 the interrupt routine USART6_IRQHandler() is not called.

I think that the UART6 Receive Interrupt is not enabled, but how can I enable it? Is there a specific bit in some register that must be set?

Thanks


This post on SO speak about this topic but I think is too old for my STM32F4.

This other post is old too.


Solution

  • Thanks to @pmacfarlane's comment I solved the problem of the lack of reception interrupts in the example UART_HyperTerminal_IT.

    So I confirm that the only modification needed to obtain the echo of the characters receives from UART6 is the addition of the instruction huart6.Instance->CR1 |= USART_CR1_RXNEIE;.

    Initialization of UART6 with reception interrupts enabled

    So the initialization code for the UART6 becomes:

    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.HwFlowCtl  = UART_HWCONTROL_NONE;
    huart6.Init.Mode       = UART_MODE_TX_RX;
    huart6.Init.OverSampling = UART_OVERSAMPLING_16;
    
    if(HAL_UART_Init(&huart6) != HAL_OK) {
        /* Initialization Error */
        Error_Handler();
    }
    
    // ---> enable reception interruptions
    huart6.Instance->CR1 |= USART_CR1_RXNEIE;
    

    Note. In the previous code I have substituted the variable UART_HandleTypeDef UartHandle used in the UART_HyperTerminal_IT example with the variable:

    UART_HandleTypeDef huart6;
    

    Interrupt routine implements echo

    The code of the interrupt routine presented in the question remains exactly the same:

    void USART6_IRQHandler(void) {
        unsigned char ch;
        
        uint32_t isrflags   = READ_REG(huart6.Instance->SR);
        uint32_t cr1its     = READ_REG(huart6.Instance->CR1);   
        
        if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
            huart6.Instance->SR;
            ch = huart6.Instance->DR;
            HAL_UART_Transmit(&huart6, &ch, 1, 1000);
        }
    
        HAL_UART_IRQHandler(&huart6);
    }
    

    The USART6_IRQHandler() function retrieves the received char and sends it immediately back implementing the echo of every char received.

    While loop empty

    That's all, the while(1) loop is completly empty:

    while(1) {
       // empty loop
    }