5. Interrupts

1. Vector Table

What are vectors?

Vectors are essentially pointers to the entry points of interrupt service routines (ISRs) or exception handlers. When an interrupt or exception occurs, the processor looks up the corresponding address in the vector table and jumps to that address to execute the relevant code.

Vector Table in Cortex-M

In Cortex-M processors, the vector table is a section in memory that holds these addresses. It usually starts at address 0x00000000 but can be relocated. The table includes various system handlers as well as interrupt handlers specific to the particular microcontroller.

startup_stm32f446retx.s

In STM32 microcontrollers, this is typically defined in assembly language, as shown below:

g_pfnVectors:
  .word _estack
  .word Reset_Handler
  .word NMI_Handler
  .word HardFault_Handler
  ...

This table starts with _estack, which is the initial stack pointer value. Following this are vectors for system exceptions like Reset_Handler, NMI_Handler, and so on. Custom interrupt handlers like WWDG_IRQHandler for the Window Watchdog interrupt are also listed.

STM32F446 Reference Manual

In the STM32F446 reference manual, the vector table is often shown as a well-organized list, sometimes in tabular form, defining each vector's purpose. Here's a representation:

vector_table

This example only shows the first 5 vectors. There are many more vectors specific to the microcontroller's peripherals and other features, and they are all documented in the reference manual. See my notes on Exception Model of ARM Cortex-M for more details.


2. External interrupt/event controller (EXTI)

The External Interrupt/Event Controller (EXTI) is a crucial hardware feature of the STM32F4xx series that enables the microcontroller to interact with external devices via interrupts. The EXTI serves as a bridge to connect the NVIC with various peripherals and sensors.

Features

Edge-Detector Lines

  • The EXTI features 23 edge-detecting lines that generate interrupt or event requests.
  • Each line is configurable, allowing you to specify the type of triggering event.

Trigger Types

  • Rising Edge: Trigger when the signal goes from low to high.
  • Falling Edge: Trigger when the signal goes from high to low.
  • Both Edges: Trigger on both rising and falling edges.

Masking

  • Each line can be masked independently, giving you the flexibility to enable or disable specific interrupts.

Pending Register

  • A pending register holds the status of the interrupt requests, allowing for efficient handling.

Pulse Width

  • The EXTI can detect external lines with a pulse width shorter than the Internal APB2 clock period. This enables high-speed signal recognition.

GPIO Connection

  • Up to 114 General-Purpose I/O (GPIO) pins can be connected to the 16 available external interrupt lines.

Use-Cases

  • Edge-detection in encoder reading
  • External buttons and switches
  • Wake-up from low-power modes
  • Real-time clock (RTC) alarms

Code Snippet Example

Here's a simple code snippet in C that shows how to configure an EXTI line for a rising-edge interrupt on a GPIO pin:

/* Enable clock for SYSCFG */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

/* Connect EXTI Line0 to PA0 pin */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

/* Configure EXTI Line0 */
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Configure NVIC (Nested Vector Interrupt Controller) */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

External interrupt/event line mapping

The STM32F4xx microcontrollers feature 16 external interrupt/event lines, ranging from EXTI0 to EXTI15. These lines can be mapped to different GPIO pins, allowing for flexible configurations.

  • Up to 8 GPIO pins can be mapped to a single EXTI line.
  • The mapping is often represented in a tabular or graphical format for easy reference.

EXTI_GPIO_mapping

  • Choosing the appropriate GPIO mapping can optimize both hardware layout and software logic.
  • Pay attention to conflicts if more than one GPIO pin is mapped to the same EXTI line.

EXTI registers

Registers are used to configure and control the behavior of the EXTI lines. Below is an outline of important EXTI registers.

EXTI

Interrupt mask register (EXTI_IMR)

  • Controls which lines are capable of generating interrupts.
  • A bit set to '1' will unmask the corresponding line, enabling its interrupt capability.

Event mask register (EXTI_EMR)

  • Similar to EXTI_IMR, but used for event configuration rather than interrupt.
  • A bit set to '1' will unmask the corresponding line for event generation.

Rising trigger selection register (EXTI_RTSR)

  • Determines which lines will generate an interrupt or event upon a rising edge.
  • Setting a bit to '1' activates the rising-edge trigger for the corresponding EXTI line.

Falling trigger selection register (EXTI_FTSR)

  • Determines which lines will generate an interrupt or event upon a falling edge.
  • Setting a bit to '1' activates the falling-edge trigger for the corresponding EXTI line.

Software interrupt event register (EXTI_SWIER)

  • Allows you to manually set an interrupt or event request.
  • Useful for debugging or simulating external triggers.

Pending register (EXTI_PR)

  • Stores the status of interrupt or event requests.
  • A bit set to '1' indicates that the corresponding EXTI line has a pending request.

Code Snippet for Register Configuration

Here's a simplified C code snippet that demonstrates the register configuration for an EXTI line:

// Enable interrupt for EXTI line 0
EXTI->IMR |= (1 << 0);

// Enable rising edge trigger for EXTI line 0
EXTI->RTSR |= (1 << 0);

// Clear pending bit for EXTI line 0, if set
EXTI->PR = (1 << 0);

Troubleshooting

  • Always check the status of the pending register (EXTI_PR) during debugging.
  • Verify that the appropriate bits in the mask registers (EXTI_IMR and EXTI_EMR) are set or cleared based on your needs.