I'm using STM32F4 and I want to generate a software interrupt. the question is how do I know in the interrupt handler if the interrupt was generated by software or by the pin connected to the EXTI line?
-
It is unclear what you are asking. Are you triggering the EXTI interrupt as described here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Cihhbccd.html? – Clifford Jun 11 '17 at 14:32
-
There is a good question here, but to anyone unfamiliar perhaps with STM32, a little research is necessary to understand what you are asking. You should not expect anyone to go to that effort and should perhaps include code to illustrate what you are doing. As it stands the question is attracting down and close votes, but could be a useful and interesting question with some clarification. – Clifford Jun 11 '17 at 15:08
-
Seems pretty obvious what is being asked here. I vote to keep it open. – Owl Jun 25 '19 at 15:03
1 Answers
There are two ways of generating a software interrupt on STM32F4.
the generic Cortex-M4 method or writing to the Software Trigger Interrupt Register (STIR), or
the STM32 EXTI specific method of writing to the EXTI Software interrupt event register (EXTI_SWIER).
I don't think in the first method the interrupts are distinguishable because STIR is a write-only register. However EXTI_SWIER is r/w and the bit written to trigger the interrupt is not cleared until the corresponding bit in EXTI_PR is explicitly written. It is therefore possible to determine whether the interrupt is software triggered simply by reading EXTI_SWIER.
void EXTI0_IRQHandler(void)
{
// Detect SWI
bool is_swi = (EXTI->SWIER & 0x00000001u) != 0 ;
// Clear interrupt flag
EXTI_ClearITPendingBit(EXTI_Line0);
if ( is_swi )
{
...
}
else
{
...
}
}
For EXTI lines that share a single interrupt, you would first have to determine the active line by checking the PR register:
void EXTI15_10_IRQn( void )
{
for( uint32_t exti = 10; exti < 15; exti++ )
{
bool is_swi = false ;
if( EXTI_GetFlagStatus( exti ) == SET )
{
is_swi = (EXTI->SWIER & (0x1u << exti)) != 0 ;
// Clear interrupt flag
EXTI_ClearITPendingBit( exti ) ;
if ( is_swi )
{
...
}
else
{
...
}
}
}
}

- 88,407
- 13
- 85
- 165
-
thanks a lot for the detailed answer.. sorry that the question was not very clear. – Samer.M Jun 12 '17 at 08:35
-
@Samer.M : you are welcome; you should still edit the question to address the issues. – Clifford Jun 13 '17 at 08:00
-
Sadly, your statement “EXTI_SWIER is r/w and the bit written to trigger the interrupt is not cleared until the corresponding bit in EXTI_PR is explicitly written“ is incorrect. Any write to the EXTI_SWIER will set or clear every bit as written: the `1` bits are NOT kept as `1` until zeroed by writing to EXTI_PR – John Burger Sep 29 '19 at 14:50
-
@JohnBurger : It is as documented _"If interrupt are enabled on line x in the EXTI_IMR register, writing '1' to SWIERx bit when it is set at '0' sets the corresponding pending bit in the EXTI_PR register, thus resulting in an interrupt request generation. This bit is cleared by clearing the corresponding bit in EXTI_PR (by writing a 1 to the bit)."_ I would advise against trusting any "undocumented" behaviour or use it in any way other than as documented. I am not sure your point has any relevance in practice. The int'rupt occurs when SWIER is set to 1 - it does not matter how it is reset. – Clifford Sep 29 '19 at 16:03
-
I said “sadly” above because I was bitten by that undocumented behaviour. If you have /two/ SWIs, and you set one, then (just) setting the other cancels the first! Of course, setting the first would normally immediately interrupt - but if the setting code was during disabled interrupts, or inside a higher priority interrupt, then it /does/ matter – John Burger Sep 29 '19 at 22:26
-
@JohnBurger The solution to that problem is to use read/modify/write, or better use atomic bit-banded writes. – Clifford Sep 29 '19 at 22:40
-