cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7B3I - Receiving an unknown interrupt on the EXT9_5 after clearing the interrupts on all lines 5 - 9.

Garnett.Robert
Senior III

Hi,

I have the following code: which clears the WXTI9_5 interrupts, enables the EXTI9_5 interrrupts and provides an interrupt handler for these.

void clearAll_EXTI9_5_IRQ(void)
{
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_5);
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6);
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_7);
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8);
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_9);
}
 ...
  clearAll_EXTI9_5_IRQ();
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
 
/**
  * @brief This function handles EXTI line[9:5] interrupts.
  * GPIO_PIN_5 is the WiFi Ready status
  */
uint16_t flagInt;
void EXTI9_5_IRQHandler(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	flagInt = 0;
 
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_5) != 0x00U)
  {
  	/* DataReady Pin Rising */
  	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_5);
  	wiFiRdyState = true;
  	xSemaphoreGiveFromISR(wiFiReadySemHandle, &xHigherPriorityTaskWoken);
  	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  	return;
  }
 
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_8) != 0x00U)
  {
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8); /* SD Card detect */
  	return;
  }
 
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_6) != 0x00U)
  {
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6); /* NIU */
  	return;
  }
 
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_7) != 0x00U)
  {
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_7); /* NIU */
  	return;
  }
 
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_9) != 0x00U)
  {
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_9); /* NIU */
  	return;
  }
 
  /* What interrupt is this? */
  flagInt = 1;
}

I am using the line 5 interrupt on a rising edge and that works fine.

However before I initiate a SPI transaction which results in Line 5 asserting on completion, I get an interrupt which does not match any of the lines and I end up at line 58 i.e. flagInt = 1;

This is in spite of the fact that I clear all of the interrupts for EXTI9_5 and I have checked that there are no other active pins floating that could cause this. I also checked that I only enabled the EXTI9_5 once.

I have seen another question similar to this and putting __DSB()'s before the returns was the fix, but I do not seem to be missing genuine interrupts in the 5 - 9 range I just get the extra one at the start.

I would like to nail it down because rogue interrupts can cause nastiness to occur in complex projects.

Any ideas?

Regards

Rob

13 REPLIES 13

> The multi-input interrupts on return however do NOT appear clear the interrupts in the NVIC reg's.

NVIC always clears the interrupt on exit from the handler, but immediately re-samples the input.

If the input has not been silenced (or the change has not arrived to the NVIC yet), NVIC will mark the vector pending again.

Garnett.Robert
Senior III

Hi PA,

Yes it's definitely a timing problem. If you single step through the IRQ Handler it does not produce a second interrupt.

To fix the problem you basically just need a few instructions immediately prior to the return in the IRQ Handler.

I tried a few different ones just too experiment, obviously only one at a time:

void EXTI9_5_IRQHandler(void)
{...
 
  k = 1;                                                            /* or */
  __DSB();                                                      /* or */
 
  register int k;        
  for (k = 0; k < 1; k++){}                                 /* or */
 
  NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
 
  asm("nop"); /* No amount of these in-lined fix the problem I tried 10 */
 
 
   return;
}

With the exception of the simple nop's all of these variation fixed the problem.

So I think that the __DSB(); is probably the best of these. I am not sure whether the function of this memory barrier instruction plays a part or whether it is simply timing. If you wanted to clear all of the line interrupts for some reason then clear pending would be OK, but I'm not sure, but it could cause a loss of interrupts that occur whilst the interrupt handler is executing.

The execution times for the various methods is very small, but the dsb is the fastest:

Anyhow I will use DSB as it works, is the fastest and shouldn't be optimised out by the compiler.

  • DSB 265ns
  • Loop 301 ns
  • Clear Pending 414 ns

Something weird happened with my last upload so I've posted it uncleaned below

Regards

Rob

I made a flow chart of the interrupts behaviour for various cases.

I forgot to attach it:

Piranha
Chief II

Read the ARM Application Note 321 section "4.9 Disabling interrupts at peripherals".