NVIC (中断控制器)

简介

中断控制器 (NVIC) 是 ET6001 中心控制器的重要组成部分,负责管理和处理所有的外部和内部中断请求。它支持多达 146 个中断源,并提供优先级管理、屏蔽和触发方式配置等功能。

功能概述

  • 支持多达 146 个中断源

  • 支持中断优先级分组和动态调整

  • 支持外部中断和内部中断

  • 提供中断屏蔽和触发方式配置

  • 支持中断嵌套和优先级抢占

  • 支持中断向量表的动态配置

  • 支持中断处理函数的注册和注销

中断控制器 (NVIC) 结构图

中断优先级配置

中断优先级配置是 NVIC 的核心功能之一。ET6001 的优先级寄存器实现了 4 bit,最多支持 16 级中断优先级。默认配置为 16 级优先级 (4bit)。

优先级的实际可用位数由宏定义 __NVIC_PRIO_BITS 决定,该宏定义位于 et6002.h 文件中,本芯片实际实现 4 bit。

NVIC 优先级配置宏定义

Number of priority bits

Number of priority levels

3

8

4

16

NVIC的优先级组将中断优先级分为组优先级和子优先级, 组优先级决定了中断的抢占优先级,而子优先级则决定了在同一 组优先级下的中断处理顺序。

NVIC优先级分组配置可以通过调用 NVIC_SetPriorityGrouping(uint32_t PriorityGroup) 函数来实现。该函数允许用户设置优先级分组的数量,从而灵活地管理中断优先级。

上面提到优先级最大支持 4 bit, 当默认配置为16级优先级(4bit)时,其中 PriorityGroup 的取值如下:

  • 7:分为0位抢占优先级和 4位响应优先级

  • 6:分为1位抢占优先级和 3位响应优先级

  • 5:分为2位抢占优先级和 2位响应优先级

  • 4:分为3位抢占优先级和 1位响应优先级

  • 3,2,1,0:分为4位抢占优先级和 0位响应优先级 (默认配置)

备注

默认配置下,NVIC 的优先级分组值为 0,即没有响应优先级,共4位16个抢占优先级。

中断优先级的设置可以调用 NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 设置中断优先级。其中IRQn_Type 是中断号类型,priority 是优先级值。

  • IRQn_Type 是中断号参考 et6002.h 中的IRQn_Type定义

  • priority 是中断优先级值,范围从 0 到 15 (当配置为 16 级优先级时),0 为最高优先级,15 为最低优先级。(默认配置为 16 级优先级时)

备注

中断优先级越低,优先级越高。0 级为最高优先级,15 级为最低优先级。

另外还可以通过调用 NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) 函数来编码优先级。 该函数允许用户根据优先级分组、抢占优先级和响应优先级来生成一个编码的优先级值。该值可以直接用于设置中断优先级。

  • PriorityGroup 是优先级分组,取值范围为 0 到 7 (当配置为 16 级优先级时)

  • PreemptPriority 是抢占优先级,取值范围为 0 到 15 (当配置为 16 级优先级时)

  • SubPriority 是响应优先级,取值范围为 0 到 15 (当配置为 16 级优先级时)

注意

如果优先级分组与可用的优先级位(__NVIC_PRIO_BITS)之间存在冲突,则设置最小优先级组。

配置示例:

// 这将分配 0 位抢占优先级和 4 位响应优先级
NVIC_SetPriorityGrouping(7);
// 设置中断优先级
NVIC_SetPriority(TIMER0_IRQn, 8);
// 设置中断优先级为 3 级
NVIC_SetPriority(USART0_IRQn, 3);
// USART0的响应优先级高于 TIMER0

中断嵌套配置

中断嵌套是 NVIC 的一个重要特性,它允许高优先级的中断在低优先级中断处理过程中被响应。ET6001 支持中断嵌套和优先级抢占。

中断嵌套的配置可以通过设置中断优先级来实现。当一个高优先级的中断发生时,NVIC 会自动暂停当前低优先级中断的处理,并转而处理高优先级中断。

如果需要禁止中断嵌套,可以通过在中断处理函数中调用 __disable_irq() 来禁用全局中断。

软件配置流程

基础配置流程如下:

  1. 初始化中断向量表映射 调用 Interrupt_initVectorTable()

  2. 使能全局中断 调用 Interrupt_enableGlobal() 上电后默认为使能状态,所以可以省略此步骤。

  3. 配置中断优先级 调用 NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 传入中断号和优先级。

  4. 注册中断处理函数 调用 Interrupt_register() 传入中断号和处理函数指针。

  5. 使能外设中断 调用 Interrupt_enable() 传入中断号。

  6. 如果需要禁用中断 调用 Interrupt_disable() 传入中断号。

中断相关调试

Keil的调试界面提供了中断相关的调试功能,可以查看当前中断状态、优先级和嵌套情况。通过 NVIC 调试界面,用户可以方便地监控和管理中断。

NVIC 调试界面

API Reference

Header File

Functions

void Interrupt_defaultHandler(void)
bool Interrupt_enableGlobal(void)
bool Interrupt_disableGlobal(void)
void Interrupt_initVectorTable(void)
void Interrupt_register(IRQn_Type interruptNumber, void (*handler)(void))
void Interrupt_unregister(IRQn_Type interruptNumber)
void Interrupt_enable(IRQn_Type interruptNumber)
void Interrupt_disable(IRQn_Type interruptNumber)