0
0
Cnc-programmingHow-ToBeginner · 4 min read

How to Configure NVIC in ARM Cortex-M: Step-by-Step Guide

To configure the NVIC in ARM Cortex-M, you enable interrupts by setting the appropriate bits in the NVIC_ISER registers and set interrupt priorities using NVIC_IPR registers. You also clear pending interrupts with NVIC_ICPR and can disable interrupts via NVIC_ICER. This setup allows precise control over interrupt handling and priority.
📐

Syntax

The main registers used to configure NVIC are:

  • NVIC_ISER: Interrupt Set-Enable Registers to enable interrupts.
  • NVIC_ICER: Interrupt Clear-Enable Registers to disable interrupts.
  • NVIC_ISPR: Interrupt Set-Pending Registers to set interrupts as pending.
  • NVIC_ICPR: Interrupt Clear-Pending Registers to clear pending interrupts.
  • NVIC_IPR: Interrupt Priority Registers to assign priority levels.

Each interrupt line corresponds to a bit in these registers. Priority values are usually 8-bit fields, where lower values mean higher priority.

c
/* Enable interrupt number 'IRQn' */
NVIC->ISER[IRQn / 32] = (1 << (IRQn % 32));

/* Disable interrupt number 'IRQn' */
NVIC->ICER[IRQn / 32] = (1 << (IRQn % 32));

/* Set priority for interrupt 'IRQn' */
NVIC->IP[IRQn] = priority_value;

/* Clear pending interrupt 'IRQn' */
NVIC->ICPR[IRQn / 32] = (1 << (IRQn % 32));
💻

Example

This example shows how to enable an interrupt, set its priority, and clear any pending flags for interrupt number 5.

c
#include "stm32f4xx.h"  // Example MCU header

void configure_NVIC_example(void) {
    uint32_t IRQn = 5; // Example interrupt number
    uint8_t priority = 2; // Priority level (0 = highest)

    /* Enable interrupt */
    NVIC->ISER[IRQn / 32] = (1 << (IRQn % 32));

    /* Set priority */
    NVIC->IP[IRQn] = (priority << 4); // Shift depends on implementation

    /* Clear pending interrupt */
    NVIC->ICPR[IRQn / 32] = (1 << (IRQn % 32));
}

int main(void) {
    configure_NVIC_example();
    while(1) {
        // Main loop
    }
}
Output
No visible output; NVIC interrupt 5 is enabled with priority 2 and pending flag cleared.
⚠️

Common Pitfalls

Common mistakes when configuring NVIC include:

  • Not enabling the interrupt in the peripheral and NVIC both.
  • Setting priority values incorrectly (priority bits may be shifted).
  • Forgetting to clear pending interrupts before enabling.
  • Using wrong interrupt numbers or bit positions.

Always consult your MCU's reference manual for exact register details.

c
/* Wrong: Setting priority without shifting bits */
NVIC->IP[IRQn] = priority; // May cause wrong priority

/* Correct: Shift priority to correct bits */
NVIC->IP[IRQn] = (priority << 4);
📊

Quick Reference

RegisterPurposeUsage
NVIC_ISEREnable interruptsSet bit corresponding to IRQ number
NVIC_ICERDisable interruptsSet bit corresponding to IRQ number
NVIC_ISPRSet pending interruptsSet bit to mark interrupt pending
NVIC_ICPRClear pending interruptsSet bit to remove pending status
NVIC_IPRSet interrupt priorityWrite priority value (shifted)

Key Takeaways

Enable interrupts by setting bits in NVIC_ISER registers.
Set interrupt priority carefully, considering bit shifts.
Clear pending interrupts before enabling to avoid unexpected triggers.
Always verify IRQ numbers and bit positions from your MCU manual.
NVIC configuration controls how and when interrupts are handled on Cortex-M.