Skip to main content
stenasc
Associate III
August 26, 2017
Question

Disabling Uart4 interrupt causes lockup

  • August 26, 2017
  • 18 replies
  • 3802 views
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          

}
    This topic has been closed for replies.

    18 replies

    Tesla DeLorean
    Guru
    August 27, 2017
    Posted on August 27, 2017 at 05:21

    >>the system locks up

    The prescient question is where is it locked up, if you stop it in the debugger where is it stuck.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    stenasc
    stenascAuthor
    Associate III
    August 28, 2017
    Posted on August 28, 2017 at 10:38

    Hi Clive,

    Appreciate you getting back to me. It hasn't locked up. It just remains in the interrupt handler and seems to loop continuously which seems very surprising as I would have expected the

    NVIC_DisableIRQ(USART3_8_IRQn)  to allow it to exit cleanly 

    . I'll get a chance to look at the flags and registers later today.

    Bob 

    Tesla DeLorean
    Guru
    August 28, 2017
    Posted on August 28, 2017 at 15:57

    Wouldn't 

    USART_ITConfig(USART4, USART_IT_RXNE, DISABLE/ENABLE); be the more appropriate?

    This is a bit nonsensical

    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;                        

            }

    }

    The interrupt source is self clearing, and there is a single byte buffer on the USART, just check the RXNE bit in the status, not the interrupt, and scope the buffer depth so it doesn't overrun and corrupt things.

    void USART3_8_IRQHandler(void)

    {

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

    {

    uint8_t rx_byteby = USART_ReceiveData(USART4);

    if (U4_rx_count < sizeof(rx_str))

    rx_str[U4_rx_count++] = rx_byteby;

    }

    }
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    August 30, 2017
    Posted on August 30, 2017 at 04:07

    Stops in the sense of you stepping it, or is there when you hit the stop button in the debugger?

    This is with what part? If a Cortex-M0, is the vector table copied into RAM?

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    stenasc
    stenascAuthor
    Associate III
    August 30, 2017
    Posted on August 30, 2017 at 09:15

    Hi Clive,

    It's there when I hit stop in the debugger. The part is an

    stm32f091 (Cortex M0). Don't quite understand regarding the vector table copying. Would you not expect all other interrupts to cause problems if there was a vector table issue?

    Regards

    Bob 

    Tesla DeLorean
    Guru
    August 30, 2017
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    S.Ma
    Principal
    August 30, 2017
    Posted on August 30, 2017 at 09:54

    Could you explain the application and the reason to stop the USART interrupt?

    Usually interrupt priority will be used to make sure other peripherals will be processed first.

    Is disabling the interrupt purpose to make sure the buffer is 'stopped'? Because in this case, it would be better to implement a SW FIFO between the USART that push bytes in, and the other task that reads bytes in.

    For fun, implemented something like a ring buffer which could be used as FIFO or STACK (see attached).

    The notification of the buffer empty/non-empty can be used to enable/disable peripherals.

    ________________

    Attachments :

    SebByteVein.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hxpe&d=%2Fa%2F0X0000000b8F%2F49K0EbWwog.r1HF__blvwRAXQc.nnNm14MWWNjN8qVo&asPdf=false

    sebByteVein.h.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyPH&d=%2Fa%2F0X0000000b8A%2FI2GssU3VPPQVRNh_.gE9Z1AjhxI_rC4mx1k2qdfrjrE&asPdf=false
    stenasc
    stenascAuthor
    Associate III
    August 30, 2017
    Posted on August 30, 2017 at 10:41

    At regular intervals, data is written to memory and it was noticed that erroneous writes were occurring. After the interrupt was disabled, writes were fine. However, I don't think it is an issue with disabling the interrupt. The problem occurs after I re-enable it when it remains in the handler and doesn't return to the main loop.

    Bob

    Tesla DeLorean
    Guru
    August 30, 2017
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Vangelis Fortounas
    Associate II
    September 2, 2017
    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

    stenasc
    stenascAuthor
    Associate III
    September 6, 2017
    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

    Tesla DeLorean
    Guru
    September 6, 2017
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..