Interrupts

Interrupts : Interrupt vs. Polling

int main()
{
    while(1){
        . . .
    }
}

OnSwitch_ISR{
    getData()
}

Interrupt

int main()
{
    while(1){
        if(switch = on ){
            getData();
        }
        . . .
    }
}

Polling


Interrupts NVIC

image.png

Interrupts: The Vector Table

The vector table contains the addresses of the Interrupt Handlers and Exception Handlers.

image.png

Interrupts: External Interrupt (EXTI) Lines

image.png

...

This means we cannot have PB0 and PA0 as input interrupt pins at the same time since they are connected to the same multiplexer i.e. EXTI0

Same for PC4 and PB4 at the same time, etc.

image.png

Interrupts : States

example:

image.png

ADC Interrupt fires at time t = 0.

This is indicated by F

Since there is no other interrupt, the pending state is cleared and the interrupt becomes active.

This is indicated by P

At time t=1 TIMER interrupt fires

This is indicated by F

Since it has a lower priority than the ADC interrupt it remains in the pending state

At time t=3 ADC interrupt completes its execution

Since there is no other interrupt with a higher priority, the pending state of the TIMER interrupt is cleared and the interrupt becomes active.

This is indicated by P

Interrupts : Priorities

Some interrupt priorities are defined by ARM, these cannot be changed. E.g.:

Lower number = Higher priority

image.png

Interrupts : Priorities in M3/M4/M7

💡 - 8-bits to configure the priority of an IRQ implies there are 2⁸ = 255 priority levels
- STM32 microcontrollers use only the 4 upper bits to configure the priority of each IRQ. This implies that in STM32 MCUs there are 2⁴ = 16 priority levels

image.png

image.png

Interrupts : Sub-priorities

GPIO Interrupt example

#include "stm32f4xx.h"

#define GPIOCEN    (1U<<2)
#define SYSCFGEN   (1U<<14)
#define LINE13     (1U<<13)

void pc13_exti_init(void)
{
    /*Disable global interrupts (recommended)*/
    __disable_irq();

    /*Enable clock access for GPIOC*/
    RCC->AHB1ENR |= GPIOCEN;

    /*Set PC13 as input*/
    GPIOC->MODER &= ~(1U<<26);
    GPIOC->MODER &= ~(1U<<27);

    /*Enable clock access to SYSCFG*/
    RCC->APB2ENR |= SYSCFGEN;

    /*Select PORTC for EXTI13*/
    SYSCFG->EXTICR[3] |= (1U<<5); //  PC[x] pin

    /*Unmask EXTI13*/
    EXTI->IMR |= (1U<<13);

    /*Select falling edge trigger*/
    EXTI->FTSR |= (1U<<13);

    /*Enable EXTI13 line in NVIC*/
    NVIC_EnableIRQ(EXTI15_10_IRQn);  // EXTI15_10_IRQn=40

    /*Enable global interrupts*/
    __enable_irq();
}

static void doStuff()
{
...
}

/* Intr routine */
void EXTI15_10_IRQHandler(void)
{
	// check which pin trigred the intr
	if ((EXTI->PR & LINE13) != 0)
	{
		//Cleat PR flag
		EXTI->PR != LINE13;
		
		doStuff();
	}
}

💡 SYSCFG stands for System Configuration Controller. It is a peripheral in STM32 microcontrollers that manages system-level features, including external interrupt line mapping.

Why enable SYSCFG?
You need to enable the SYSCFG clock because the EXTI (external interrupt) configuration registers are part of the SYSCFG peripheral. Without enabling its clock, you cannot configure which GPIO port is connected to an EXTI line (like mapping PC13 to EXTI13). This is done by setting the appropriate bit in RCC->APB2ENR.

💡 image.png