cancel
Showing results for 
Search instead for 
Did you mean: 

How to disable/MASK an exti line ON THE FLY

Craig1
Associate

I'm currently trying to implement a button interrupt and need to disable the button interrupt after the initial call to the isr to avoid excessive interrupt triggering due to debounce. I'm using STM32CUBEIDE/MX currently. The button works as desired if I use

HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); (in interrupt)

//do some stuff

HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); (in main)

but this is non-ideal as it disables exti lines 5 through 9.

I've been trying to mask the EXTI line using EXTI_IMR. This seems to work for the first button press, but I'm never able to re-trigger the ISR

EXTI->IMR &= ~(EXTI_LINE_5);//in ISR

EXTI->IMR &= (EXTI_LINE_5);//in main

Thoughts?

19 REPLIES 19

They do support enable/disable interrupt, but not masking.

Piranha
Chief II

As Jan noted, there are gotchas related to interrupt disabling at peripheral level. This is explained in ARM Application Note 321, section 4.9 "Disabling interrupts at peripherals".

@deckhard​ 

MStra.3
Associate III

That solution doesn't work for me. In my case the line that signals an IRQ comes from an ADC and it uses the same line for SPI data output, so after I get the IRQ and then read the result from the ADC I get multiple IRQs unless I disable EXTI 9-5. It solves this problem but I have another peripheral using pin 7 for an IRQ so I don't really want 5-9 disabled together. Here is my code:

Mike.

  //EXTI->IMR &= -(EXTI_LINE_5); // Disable interrupts on line 5 while we read ADC. THIS DOESN'T WORK - NEED TO FIND A FIX... TODO

  HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); //Disable interrupt pins as pin5 will toggle when we read from ADC. Would rather fix the line above.

  spi3TxRxResult = HAL_SPI_TransmitReceive(&hspi3, spi3TxBuffer, ADC_Reading, 4, 2); // 2ms timeout.

  if (spi3TxRxResult != HAL_OK) Error_Handler();

  ADC_Ch = ADC_Reading[3] & 0x03;

  Chan_Status[ADC_Ch] = ADC_Reading[3] >> 4;

  Chan_Reading[ADC_Ch] = ((ADC_Reading[0] & 0x7F) << 16) + (ADC_Reading[1] << 😎 + ADC_Reading[2];

  EXTI->PR = 1 << 5; // Clear pending register for this EXTI Pin.

  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); // Re-enable interrupts. Would rather fix and use the line below.

  //EXTI->IMR |= (EXTI_LINE_5); // Re-enable interrupts on line 5. THIS DOESN'T WORK - NEED TO FIND A FIX... TODO

Which STM32?

//EXTI->IMR &= -(EXTI_LINE_5)

Not *minus*, but *tilde* (for bitwise inversion).

JW

MStra.3
Associate III

I am using the STM32F407VETx - I assume any in the STM32F4 family would work the same.

I thought the *minus* was weird but clearly that is what is in this post. I had tried with *tilde* and had the same results.

Mike.

> I assume any in the STM32F4 family would work the same.

Maybe yes, maybe not. Probably yes, but "probably" means little when facing a problem.

> I thought the *minus* was weird but clearly that is what is in this post.

No, it's not. A bad font is used in this mockup of a forum. Zoom up that post if your browser allows it, or, better, copy/paste that text into your programmer's editor.

Read out the EXTI register content before and after the operation and check/post.

How and where is EXTI_LINE_5 defined?

JW

MStra.3
Associate III

Well, bad font for sure!

OK so I changed to the tilde and looked at EXTI->IMR before (0x48B5) and after (0x48B0).

EXTI_LINE_5 is defined in stm32f4xx_hal_exti.h as:

#define EXTI_LINE_5            (EXTI_GPIO    | 0x05u)  /*!< External interrupt line 5 */

Seems weird to me that it isn't a single bit...

Mike.

MStra.3
Associate III

OK, I found the solution. EXTI_LINE_5 is defined as some large number like: 0x600005. It appears that line 5 corresponds to bit 5 so the following works for me:

EXTI->IMR &= 0xFFFFFFDF; To disable IRQ on line 5

EXTI->IMR |= 0x00000020; To enable IRQ on line 5

Mike.

This is a well deserved punishment for using Cube/HAL and its haphazardly defined symbols, instead of direct register access and symbols from CMSIS-mandated device headers.

Cube is good only as long as you stay within clicking distance of CubeMX. Anything other than the "usual usage" as envisaged by Cube's authors leave you vulnerable to Cube's innards. Here, definition of given symbol changed with changing Cube version, who could tell that when this thread started. I tried to find that symbol in some older CubeF4 I happen to have on my disk, but it was not there are all.

JW

Piranha
Chief II

It should be noted that operations on EXTI_IMR bits are not atomic. Therefore to use them from interrupts or multiple threads, they must be enclosed in critical sections. One can use OS/platform provided functions or a code like this:

https://community.st.com/s/question/0D50X0000BVmd12SQB/stm32l4-critical-section