Search code examples
stm32uarthalusart

STM32 Uart HalfDuplex keeps looping on USART2_IRQHandler never breaks


I cant seem to figure out why but when the Interrupt is enabled it just keeps calling USART2_IRQHandler I've checked the ISR register and nothing is changing it all stays the same.

I've tried reconfiguring it to be Full duplex and i encounter the same problem. The uart is supposed to be SingleWire/Half Duplex

void USART2_IRQHandler()
{
    //never stops getting called loops
}
static void MX_USART2_UART_Init(void)
{
    /* USER CODE BEGIN USART2_Init 0 */
    // HAL_UART_Receive_IT(&huart1, &Uart1_Rx, 1);
    /* USER CODE END USART2_Init 0 */

    /* USER CODE BEGIN USART2_Init 1 */

    /* USER CODE END USART2_Init 1 */
    huart2.Instance = DELTA_USART;
    huart2.Init.BaudRate = 57600; // 57.6
    huart2.Init.WordLength = UART_WORDLENGTH_9B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_ODD;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_8;
    huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    if (HAL_HalfDuplex_Init(&huart2) != HAL_OK) {
         Error_Handler();
    }
    /* USER CODE BEGIN USART2_Init 2 */

    /* USER CODE END USART2_Init 2 */
}


inline void EnableInterupt()
{
    NVIC_EnableIRQ(irq);
}
inline void DisableInterupt()
{
    NVIC_DisableIRQ(irq);
}

void setupUartInterupt()
{
    huart2.Instance->CR1 |= USART_CR1_RXNEIE //| USART_CR1_TXEIE
                    | USART_CR1_IDLEIE;
    huart2.Instance->CR1 |= USART_CR1_TE | USART_CR1_RE;
        //_huart->CR3 |= USART_CR3_OVRDIS;

    NVIC_SetPriority(USART2_IRQn, 2);
}

Solution

  • I figured it out it was something really stupid because i should have clarified earlier it only really happened when i set break points and so all i can figure it would sometime set the Overrun error flag witch is enabled by default and so it was never getting cleared causing it to keep calling repetitively so i just tweaked the setup code and disabled over run.

    Just clarity the code sample before was a simplification to the project that its apart of it was just a lot of different pieces to try and include so i simplified it as best as i could. (Thanks again for the help it did point me in the right direction because i started monitoring the ISR register real time by making a crude struct to decode the ISR and i noticed the ORE was getting called when it would start looping.

    DeltaUARTHL::ISRBitField isrTest = DeltaUARTHL::ISRBitField();
    void USART2_IRQHandler(void) //<<In main CPP
    {
        isrTest = DeltaUARTHL::ISRBitField(&huart2.Instance->ISR);
        delta.DeltaUartEventCallBack();
    }
    
    
    inline void DeltaInitialize(uint16_t _bufferSize, volatile uint32_t *microTickCounter, USART_TypeDef *_huart, IRQn_Type _irq)//<<In Library H
    {
        huartHandle = _huart;            //Set internal refrence to Uart Handle
        deltaTickPtr = microTickCounter; //Sets internal counter to refrence some external counter
        ClearReceiverStats();            //Clears receiver stats to default
        if (_bufferSize > 0)             //Checks if wanting to creat buffer
            CreateBuffer(_bufferSize);   //Creates a buffer space
    
        localDeviceAddress = 0; //Sets localDevice address to 0 (To Be Determained)
        irq = _irq;             //Sets the internal Interrupt number.
    
        _huart->CR1 &= ~USART_CR1_UE;                       //have to disable uart inorder to set control bits
        _huart->CR1 |= USART_CR1_RXNEIE | USART_CR1_IDLEIE; //Enables  idle interupt and receive interupt
        _huart->CR1 |= USART_CR1_TE | USART_CR1_RE;         //Enables Transmitter and Receiver
        _huart->CR3 |= USART_CR3_OVRDIS;                    //Disable over run
        _huart->CR1 |= USART_CR1_UE;                        //Then re-enable uart
        NVIC_SetPriority(_irq, 2);                          //Setup interupt priority
        NVIC_EnableIRQ(irq);                                //Enable interupt
    }
    
    
    
    void DeltaUARTHL::DeltaUartEventCallBack(void)
    {
    
        if (huartHandle->ISR & USART_ISR_IDLE) // handle idle line event<<<<<<<<<<<<<<<<<<<<<
        {
            huartHandle->ICR |= USART_ICR_IDLECF;
            DeltaHandleIDLE_CallBack();
        }
    
        if (huartHandle->ISR & USART_ISR_RXNE) // handle received data event<<<<<<<<<<<<<<<<<
        {
            // deltaHuart->RQR |= USART_RQR_RXFRQ;
            DeltaHandleRX_CallBack();
        }
    }
    
    
    struct ISRBitField//<<Also in Library H
    {
        ISRBitField() {}
        ISRBitField(volatile uint32_t *isrReg)
        {
            uint32_t isr = *isrReg;//Dereference
            REACK = isr & USART_ISR_REACK;
            TEACK = isr & USART_ISR_TEACK;
            WUF = isr & USART_ISR_WUF;
            RWU = isr & USART_ISR_RWU;
            SBKF = isr & USART_ISR_SBKF;
            CMF = isr & USART_ISR_CMF;
            BUSY = isr & USART_ISR_BUSY;
            ABRF = isr & USART_ISR_ABRF;
            ABRE = isr & USART_ISR_ABRE;
            EOBF = isr & USART_ISR_EOBF;
            RTOF = isr & USART_ISR_RTOF;
            CTS = isr & USART_ISR_CTS;
            CTSIF = isr & USART_ISR_CTSIF;
            LBDF = isr & USART_ISR_LBDF;
            TXE = isr & USART_ISR_TXE;
            TC = isr & USART_ISR_TC;
            RXNE = isr & USART_ISR_RXNE;
            IDLE = isr & USART_ISR_IDLE;
            ORE = isr & USART_ISR_ORE;
            NF = isr & USART_ISR_NE;
            FE = isr & USART_ISR_FE;
            PE = isr & USART_ISR_PE;
        }
        bool REACK = false;
        bool TEACK = false;
        bool WUF = false;
        bool RWU = false;
        bool SBKF = false;
        bool CMF = false;
        bool BUSY = false;
        bool ABRF = false;
        bool ABRE = false;
    
        bool EOBF = false;
        bool RTOF = false;
        bool CTS = false;
        bool CTSIF = false;
        bool LBDF = false;
        bool TXE = false;
        bool TC = false;
        bool RXNE = false;
        bool IDLE = false;
        bool ORE = false;
        bool NF = false;
        bool FE = false;
        bool PE = false;
    };