Level sensitive interrupts with EXTI
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-19 11:18 AM
I need to achieve level sensitive interrupt behavior with EXTI, similar to shared PCI interrupts on other architectures.
Have several OR'ed interrupt requests wired together to a EXTI input;
all requests are active low.
All requests can be masked or dismissed outside of STM32.
(Actually this is a device with several interrupt reason bits in a memory mapped register; the common request pin is active low; each interrupt reason bit can be masked via another memory mapped register. Like a "classic" PCI thing).
Several threads in this forum and SO (links below) suggested that this is not possible, at least not trivial.
The following trick nevertheless seems to work for me, and looks simple.
extern void exti0_handler();
void EXTI0_IRQHandler(void)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
do {
exti0_handler();
} while (HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_0) == GPIO_PIN_RESET); /* active LOW */
__DSB();
}
Explanation:
* The EXTI0 interrupt is triggered by falling edge. GPIOx is some GPIO port (A,B...)
* exti0_handler() will check each of interrupts source on the shared EXTI pin and either masks it or dismisses
* If the pin still is low (request active) after exti0_handler(), repeat.
- If the interrupt pin goes down between check of the pin and return, then the falling edge detector will activate EXTI again and it won't be lost.
Can anyone spot a bug?
Of course if the EXTI pin remains low for too long time the interrupt latency would be indefinite. If this is important, number of loops can be limited (and some action taken, like masking the whole EXTI input).
Regards,
-- pa
References:
Level triggered interrupts on STM32L series
exception - Clarify interrupt mechanism on STM32H7 - Stack Overflow
- Labels:
-
GPIO-EXTI
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-19 12:17 PM
Looks good, IMO. Just minor things:
- What's the point of __DSB?
- One primary source gets active and ISR is entered, HAL incantation is invoked to clear the EXTI latch, then your handler is called which clears the primary source, thus pin goes low. While still in your handler, a new primary interrupt happens, setting the pin high, which sets also the EXTI latch, which never gets cleared. This new interrupt is resolved in the loop and ISR is exit, but the EXTI latch remains set thus this ISR gets reentered without reason. If your handler is written so that it qualifies every source and is not surprised by being called with no source, it's OK just a nuissance and probably not worth trying to solve, as placing the latch clear nearer the ISR exit (aftr call of exti0_handler() but before reading the pin) might result in "redundant ISR call" anyway.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-20 12:54 AM
I mean not next clear but break yu miss
void EXTI0_IRQHandler(void)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
do {
exti0_handler();
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET) break;
} while (HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_0) == GPIO_PIN_RESET); /* active LOW */
__DSB();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-20 7:41 AM
Thank you Jan. Yes, handler() is ok when no source bit is set. DSB is left there perhaps just for luck ;)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-20 8:36 AM
This your code is totaly miss , when no next interrupt edge you stay in while neverending.
My first code is ok, when new IRQ flag raised while is break, and NVIC controll start new EXTI0_IRQHandler ...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-20 10:35 AM
You're right. I'll remove my wrong 'guess'. -- pa
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-24 8:41 AM
Pavel's code is perfectly fine if the rest of the code and hardware functions as described. EXTI clear can even be put inside the while loop before exti0_handler(), potentially decreasing the chance of interrupt reentering.
@MM..1​, you should stop writing misinformation with such high confidence. Your code is exactly like ST's HAL - hacked something together without real understanding. And the language skill also should be at least at a level understandable by others.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-12-24 2:41 PM
@Piranha​ Pavel removes wrong code from message, and yes my eng isnt native
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-01-03 9:09 AM
OK, then it's clear about Pavel's code. But this particular line is still a nonsense:
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET) break;
Most of the users here aren't native English speakers. It's not so much about grammar, but more about expressing the ideas in a clear and structured way - so that others can understand and use that information.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-01-03 9:18 AM
Why nonsense explain...
