cancel
Showing results for 
Search instead for 
Did you mean: 

Disabling Uart4 interrupt causes lockup

stenasc
Senior
Posted on August 27, 2017 at 00:02

Hello Forum,

I have a function that I call to read data from Uart4. As there are a number of critical times that I need Uart4 interrupt disabled, I enable the interrupt on entry to the function and disable it after priocessing the uart data. However, I found that the

system locks up after executing the NVIC_DisableIRQ(USART3_8_IRQn) command. I've tried many things but I cannot seem to get it working. My code is as follows. Any help greatly appreciated.

 

 Kind Regards

 Bob

void Enable_Usart4_Interrupts(void)

{

  NVIC_EnableIRQ(USART3_8_IRQn);                

}

void Disable_Usart4_Interrupts(void)

{    

  NVIC_DisableIRQ(USART3_8_IRQn);    

}

void Usart4Init_RS485(void)

{      

  USART_InitTypeDef USART_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

    

  // Enable GPIOC and DMA clock

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

        

  // Enable USART4 APB clock

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4, ENABLE);

        

 

  // Connect pin to Periph

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_0);   //  USART4 TX

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_0);   //  USART4 RX

 

  // Configure pins as AF pushpull

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_Init(GPIOC, &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(USART4, &USART_InitStructure);

        

  USART_Cmd(USART4, ENABLE);

            

//  Enable the COM4 Receive interrupt: this interrupt is generated when the

//  COM4 receive data register is not empty

  USART_ITConfig(USART4, USART_IT_RXNE, ENABLE);

  // USART4 IRQ Channel configuration

  NVIC_InitStructure.NVIC_IRQChannel = USART3_8_IRQn;    

  // USART4 IRQ Channel priority     

  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;    

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);       

 }

 

 

 void USART3_8_IRQHandler(void)

{

uint8_t rx_byteby = 0;

        

USART_ClearITPendingBit(USART4, USART_IT_RXNE);      //Clear any pending uart interrupts bits        

                 

  while (USART_GetITStatus(USART4, USART_IT_RXNE) != RESET) // Received characters modify string

         {                

        rx_byteby = USART_ReceiveData(USART4);

       rx_str[U4_rx_count++] = rx_byteby;                        

        }

}

int Read_From_Uart4(void)

{       

Enable_Usart4_Interrupts();   // Enable Usart4 interrupts for Uart4 data

    

// Receive and process UART4 data

//    .....

// ...

Disable_Usart4_Interrupts();  // Disable Usart4 interrupts          

}
18 REPLIES 18
Posted on August 30, 2017 at 13:14

You are calling it from within the handler? I don't understand the assembler here compared to the C code shown.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 30, 2017 at 13:46

What !!  Couldn't be Clive but I have no reason to doubt you. I'll post up the exact handler C code later this evening, It was very similar to the handler code you posted. How on earth could I call it from within the handler except by calling the handler function name which I definitely don't do? 

Posted on August 30, 2017 at 14:20

Ok, sorry it's the clear pending call, but looks to be in your while() loop

Is there a constant stream of data? Could it be flagging an overrun, which you aren't checking/clearing

Look at the USART->SR in debugger

Keep stepping, see how it cycles

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 31, 2017 at 00:17

Hi Clive,

Here is the offending code....

void USART3_8_IRQHandler(void)

{

uint8_t rx_byteby = 0;

    

            

USART_ClearITPendingBit(USART4, USART_IT_RXNE);      //Clear any pending uart interrupts bits    

         

  if (USART_GetFlagStatus(USART4, USART_FLAG_RXNE) != RESET) // Received characters modify string

         {                

           rx_byteby = USART_ReceiveData(USART4);

       rx_str[U4_rx_count++] = rx_byteby;    

    

       if (rx_byteby == 'C')

               {                    

               rx_str[U4_rx_count+1] = '\0';  // Ensure string is null terminated                          

         }                 

       if (U4_rx_count >= (sizeof(rx_str) - 1))

           U4_rx_count = 0;           

       }

            

}
Posted on September 01, 2017 at 21:52

Hi Clive,

As you said, the interrupt is continually triggering after it is re-enabled. The interrupt is exited but then triggers again, resulting in it never returning to the main loop. I've tried reading all the flags on entry to the handler and clearing them but no use.

&sharpdefine USART_RX_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE | USART_FLAG_IDLE)

if (USART_GetFlagStatus(USART4, USART_RX_FLAG_ERRORS) != RESET)

   USART_ReceiveData(USART4);

I've also tried flushing the usart receive buffer before enable the interrupt but again no joy

void Flush_Usart4_Rx_Buffer(void)

{

//Flush any old data from the usart    

while (USART_GetFlagStatus(USART4, USART_FLAG_RXNE) == SET)

   USART_ReceiveData(USART4);    

}

I've also seen the following link so I tried clearing the interrupt on entry to the handler but no use..

http://false.ekta.is/2012/06/interrupt-service-routines-double-firing-on-stm32/comment-page-1/

 

   

would be appreciated .

Regards

Bob

Latest interrupt handler

&sharpdefine USART_RX_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE | USART_FLAG_IDLE)

&sharpdefine USART_TX_FLAG_ERRORS (USART_FLAG_TC | USART_FLAG_TXE)

void USART3_8_IRQHandler(void)

{

uint8_t rx_byteby = 0;

    

//if (USART_GetFlagStatus(USART4, USART_RX_FLAG_ERRORS) != RESET)

//   USART_ReceiveData(USART4);

//if (USART_GetFlagStatus(USART4, USART_TX_FLAG_ERRORS) != RESET)

//   USART_SendData(USART4, 255);

        

         

if (USART_GetITStatus(USART4, USART_IT_RXNE) != RESET) // Received characters modify string

         {

             USART_ClearITPendingBit(USART4, USART_IT_RXNE);

           rx_byteby = USART_ReceiveData(USART4);

       rx_str[U4_rx_count++] = rx_byteby;

   

       if (rx_byteby == 'C')

               {                    

               rx_str[U4_rx_count+1] = '\0';  // Ensure string is null terminated                          

         }                 

       if (U4_rx_count >= (sizeof(rx_str) - 1))

           U4_rx_count = 0;

        //     rx_str[sizeof(rx_str)-1] = '\0';  // Ensure string is null terminated

                

       }                

}
Posted on September 02, 2017 at 02:01

Hello Bob!

I observed in your last posted code that you comment out some functions containing macro definitions involving TXE flag , also you have the transmitter enabled in your initialization code. Do you use code that transmits something?  (like echo or similar?)

Check if somewhere in your program some code sets TXEIE flag in USARTx_CR1. (by enabling TXE interrupts)

In case you don't clear TXEIE after after finish transmission TXE causes execution flood in handler mode.

Most possible in this situation is to have incorrect results from debuger .

Best regards

VF

Posted on September 06, 2017 at 00:52

Hi Forum,

After some work, I was able to fix the issue but a question remains. I checked all the flags that would cause and interrupt and a number were being set. e.g. USART_FLAG_ORE, USART_FLAG_TC and USART_FLAG_IDLE. After clearing these flags, the interrupt handler returned to the main loop. However, the corresponding pending bits were not set and I would have expected this. I would like an explanation as I would have expected the pendng bits to be set to explain why the handler was being continually called.

Kind Regards

Bob

Posted on September 06, 2017 at 03:14

>>

I would like an explanation as I would have expected the pending bits to be set to explain why the handler was being continually called.

Make a bullet-proof demo and get it in front of someone at ST with a gate level understanding of the design.

Dump out the NVIC registers relating to it and determine if it is getting flagged by the peripheral.

The interrupt selection in the peripheral should be a combination of AND gates masking the sources and OR gates combining the sources.

Do the masking at the peripheral level.

If you must do it at an NVIC level, disable the interrupt, and clear any pending internal state.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 10, 2017 at 22:20

Hi Clive,

I appreciate the replies. I did dump out all the NVIC registers based on the interrupt hardware (the combination of OR and AND gates). That is how I determined which flags were being set. To solve, I disabled the interrupt and cleared the set flags. No corresponding pending bits were set. As it works now, I will try to get a small demo to ST as soon as possible. 

Best Regards

Bob