This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USART fails in EXTI Interrupt

I have faced another strange thing today:
inside ISR of EXTI I wanted to send some character to USART, but I found that program halts there, after eliminating the commands regarding USART I found that program waits to reset USART_FLAG_TXE, but the flag remains in set mode. when I eliminated below command, program runs forward how ever just the last character transferred.

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)


Why TXE flag could not become reset after transfer of the character?!

  • Why have ISR where you busy-loop waiting for flags? That's time when your processor is locked up. A normal design uses a send queue for outgoing data.

    Next thing - you make a post but does not mention your processor. And only show a single code line in your ISR.

  • I am using STM32L1 Discovery board with a STM32L152RC.
    I want to send a string out from USART1 when a button is pushed so I write my sending function inside EXTI ISR. This is the part of code in below. by the way I didnt understand what should I do in a better way mentioned in the last reply.
    code below is my EXTI file for pushed button

     EXTI_InitTypeDef   EXTI_InitStructure;
    
            void EXTILine0_Config(void);
    
            void ExtInt_configuration(void)
            {
    
              /* Configure EXTI Line0 (connected to PA0 pin) in interrupt mode */
              EXTILine0_Config();
    
              /* Generate software interrupt: simulate a rising edge applied on EXTI0 line */
              EXTI_GenerateSWInterrupt(EXTI_Line0);
            }
    
    
            void EXTILine0_Config(void)
            {
    
              GPIO_InitTypeDef   GPIO_InitStructure;
              NVIC_InitTypeDef   NVIC_InitStructure;
    
              /* Enable GPIOA clock */
              RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
              /* Enable SYSCFG clock */
              RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    
              /* Configure PA0 pin as input floating */
              GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
              GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
              GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
              GPIO_Init(GPIOA, &GPIO_InitStructure);
    
              /* Connect EXTI Line0 to PA0 pin */
              SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
    
              /* Configure EXTI Line0 */
              EXTI_InitStructure.EXTI_Line = EXTI_Line0;
              EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
              EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
              EXTI_InitStructure.EXTI_LineCmd = ENABLE;
              EXTI_Init(&EXTI_InitStructure);
    
              /* Enable and set EXTI Line0 Interrupt to the lowest priority */
              NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
              NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
              NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
              NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
              NVIC_Init(&NVIC_InitStructure);
            }
    
            /**
              * @brief  This function handles External line 0 interrupt request.
              * @param  None
              * @retval None
              */
            void EXTI0_IRQHandler(void)
            {int i;
              if(EXTI_GetITStatus(EXTI_Line0) != RESET)
             {
               GPIO_ToggleBits(GPIOB, LED_Blue);
                                             uart_out_str("flag_1");
    //                                       USART_SendData(USART1,'A');
    //                                       while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}
    //            /* Clear the EXTI line 0 pending bit */
              EXTI_ClearITPendingBit(EXTI_Line0);
             }
            }
    
    


    and my USART1 code is:

    
    
    void uart1_RCC_configuration(void) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); }
    void uart1_configuration(void) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    /* Configure USART2 pins: Rx and Tx ----------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1,ENABLE); /* Enable RXNE interrupt */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* Enable USART1 global interrupt */ NVIC_EnableIRQ(USART1_IRQn);
    }
    void uart_out_str(char str[]) { int count=0; int bufsize=strlen(str); for(count=0;count<bufsize;count++) { USART_SendData(USART1, str[count]); /* Wait until Tx data register is empty, not really */ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} } }
    
    
    
    

  • TXE will go High if the buffer is empty, it may go low briefly (1-2 baud clocks) after you send a character if the shift register is empty too, if it's busy then it might remain low for 8-10 baud clocks. If the USART is giving a problem make sure it's clocked properly. Don't look at in the debugger, as there are interactions between SR and DR registers.

    You should check TXE *before* sending characters, not after. Ideally you don't want to be spinning for microseconds or milliseconds within an interrupt handler. Perhaps you could buffer the output data, and manage it's output in the USART TXE interrupt?

  • Yes you are right, checking TXE before sending is true. I handled the problem in another way, I set a flag in the EXTI ISR and checked it inside while loop in main.c and executed the sending chars there, so now I have no problems anymore.