2017-08-26 03:02 PM
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 Bobvoid 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 }2017-08-30 06:14 AM
You are calling it from within the handler? I don't understand the assembler here compared to the C code shown.
2017-08-30 06:46 AM
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?
2017-08-30 07:20 AM
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
2017-08-30 05:17 PM
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; } }2017-09-01 02:52 PM
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 } }2017-09-01 05:01 PM
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
2017-09-05 05:52 PM
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
2017-09-05 08:14 PM
>>
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.
2017-09-10 03:20 PM
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