For the cases when multiple pins share an interrupt, when the interrupt fires, you need to check what pin specifically caused an interrupt. Unlike pin 1 interrupt, where the interrupt itself means it was pin 1 and you can process it right away, in this case an interrupt means "it's either pin 5, or 6, or 7, or 8, or 9", so in the ISR you need to check "was it pin 5? or 6?..."
I think it's a good opportunity to look directly into the registers of EXTI peripheral.
If you open the reference manual of your MCU on page 299, section 14.3.6, you can see this EXTI_PR1 register holds pending bits for lines 0..31. Those bits are marked as rc_w1, which from the start of the document means (reference manual, page 46):
read/clear (rc_w1)
Software can read as well as clear this bit by writing 1. Writing ‘0’
has no effect on the bit value.
So the logic is the following: if an interrupt of lines 5..9 occurred, you need to check what bit specifically in that register is set to 1, and then you write 1 there to reset it. This will clear the flag.
void EXTI9_5_IRQHandler(void)
{
if(EXTI_PR1 & (1U<<5U)) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
{
EXTI_PR1 |= (1U<<5U); //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
do_stuff_if_it's_pin5();
}
}
Alternatively, instead of 1U<<5U you should be able to use EXTI_PR1_PR5, so the code would look a little easier to read, like this:
void EXTI9_5_IRQHandler(void)
{
if(EXTI_PR1 & EXTI_PR1_PR5) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
{
EXTI_PR1 |= EXTI_PR1_PR5; //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
do_stuff_if_it's_pin5();
}
}
This is what the functions provided by @Lime7 do behind the scenes, I suspect (can't check, but it makes logical sense).
I don't have that microcontroller to test it, but it should work.