其他分享
首页 > 其他分享> > 基于STM32L4的NVIC中断系统

基于STM32L4的NVIC中断系统

作者:互联网

STM32L4中断系统

         STM32L4基于Cortex-M4架构,内部有一个嵌套中断向量控制器(NVIC)来管理异常,并将优先级最高的异常提交给CPU处理。异常的编号范围是1~255,其中编号1~15被归为系统异常(如NMI、SYSTICK等),编号16~255被归为外部异常(也称外部中断,如UART、EXTI等),各个异常源与NVIC和Core的关系如下图,

        对于STM32L4系列MCU,除了16个系统异常外,还支持82个中断源,这些中断源的优先级支持16级。

         NVIC对异常的管理通过一系列的寄存器进行,如外部中断控制的NVIC寄存器、系统异常控制的SCB寄存器、全局控制的特殊功能寄存器。

1.1、外部中断控制的NVIC寄存器

         NVIC寄存器用于控制外部中断IRQ的行为,如中断设置使能、中断清除使能、中断设置挂起、中断清除挂起、中断优先级设置、软件触发中断等。

  1. 中断使能配置寄存器的操作函数:

void __NVIC_EnableIRQ(IRQn_Type IRQn)  //使能中断,IRQn为中断编号,如USART3_IRQN;

void __NVIC_DisableIRQ(IRQn_Type IRQn) //禁止中断,IRQn为中断编号

uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)//获取中断使能状态,返回1:使能,0:禁止

  1. 中断挂起寄存器的操作函数:

void __NVIC_SetPendingIRQ(IRQn_Type IRQn) //设置挂起位,IRQn为中断编号

void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)//清除挂起位,IRQn为中断编号

uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) //获取挂起位状态,返回1:挂起,0:未挂起

  1. 活跃状态寄存器的操作函数:

uint32_t __NVIC_GetActive(IRQn_Type IRQn) //获取活跃位状态,返回1:活跃,0:未活跃

当某个活跃位置1时,表示MCU当前正在处理该中断的服务程序,执行完成后,该活跃位自动被清零;

当低优先级的中断服务程序正在执行时,高优先级中断挂起,则MCU打断低优先级中断,执行高优先级的中断服务程序,此时,低优先级与高优先级的活跃位均置1。

  1. 优先级配置寄存器

void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

//设置中断优先级,IRQn为中断编号,priority为优先级,STM32L4支持16级,即priority取值为0~15;

uint32_t __NVIC_GetPriority(IRQn_Type IRQn) //获取中断优先级,IRQn为中断编号

  1. 软件中断设置寄存器

NVIC->STIR = IRQn // IRQn为中断编号

软件中断设置与中断挂起设置寄存器使用的效果一致,都能触发一次软件中断。

1.2、系统异常控制的SCB寄存器

         SCB寄存器用于配置系统异常,包含系统异常使能、异常挂起设置与清除、优先级、活跃状态查询等;同时还有错误源状态与系统调试相关的寄存器。

         在SCB模块中,与系统异常设置有关的主要是SCB->ICSR、SCB->AIRCR、SCB->SHP[X]、SCB->SHCSR寄存器,相关的异常有NMI、FAULT、SVC、PendSV、SysTick等,对应的使能与挂起位配置如下表所示:

  1. NMI挂起位设置

SCB->ICSR |= (1 << 31); 或 (*((volatile uint32_t *)0xe000ed04)) |= (1 << 31);

  1. Memmanage错误

//使能Memmanage异常中断,默认关闭

SCB->SHCSR |= 1 << 16;或(*((volatile uint32_t *)0xe000ed24)) |= (1 << 16);

 //设置优先级,IRQn = -12;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed18)) = priority;

  1. 总线错误

//使能总线异常中断,默认关闭

SCB->SHCSR |= 1 << 17; 或(*((volatile uint32_t *)0xe000ed24)) |= (1 << 17);

//设置优先级,IRQn = -11;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed19)) = priority;

  1. 使用错误

//使能使用异常中断,默认关闭

SCB->SHCSR |= 1 << 18; 或(*((volatile uint32_t *)0xe000ed24)) |= (1 << 18);

//设置优先级,IRQn = -10;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed1A)) = priority;

  1. SVC系统调用

//系统调用指令,执行SVC_HANDLER()处理函数;

svc 0

//设置优先级,IRQn = -5;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed1F)) = priority;

  1. PendSV可挂起的系统调用

//设置pendsv挂起位

SCB->ICSR |= (1 << 28); 或 (*((volatile uint32_t *)0xe000ed04)) |= (1 << 28);

//清除pendsv挂起位

SCB->ICSR |= (1 << 27); 或 (*((volatile uint32_t *)0xe000ed04)) |= (1 << 27);

//设置优先级,IRQn = -2;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed22)) = priority;

  1. SysTick定时器

//异常使能

SysTick->CTRL |= (1 << 2); 或 (*((volatile uint32_t *)0xe000e010)) |= (1 << 2);

//设置SYSTICK挂起位

SCB->ICSR |= (1 << 26); 或 (*((volatile uint32_t *)0xe000ed04)) |= (1 << 26);

//清除SYSTICK挂起位

SCB->ICSR |= (1 << 25); 或 (*((volatile uint32_t *)0xe000ed04)) |= (1 << 25);

//设置优先级,IRQn = -1;

__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

或(*((volatile uint32_t *)0xe000ed23)) = priority;

1.3、全局控制的特殊寄存器

         全局中断使能与禁止主要是操作内核CPSR寄存器的I位与F位的置1与清0状态。

A、PRIMASK

         用于禁止除了NMI和HardFault外的所有异常和中断,内核提供的操作函数为:

         void __set_PRIMASK(uint32_t priMask);

         uint32_t __get_PRIMASK(void);

         举例:

         /* Disable interrupts*/

         uint32_t  primask_bit = __get_PRIMASK();

       __disable_irq();

         //…不可中断代码

         /* Re-enable the interrupts */

    __set_PRIMASK(primask_bit);

B、FAULTMASK

         用于禁止除了NUM外的所有异常和中断,包含HardFault也被屏蔽,内核提供的操作函数为:

         uint32_t __get_FAULTMASK(void);

         void __set_FAULTMASK(uint32_t faultMask);

         举例:

         /* Disable interrupts*/

         uint32_t  faultmask_bit = __get_ FAULTMASK ();

       __disable_fault_irq ();

         //…不可中断代码

         /* Re-enable the interrupts */

__set_ FAULTMASK (faultmask_bit);

C、BASEPRI

         该寄存器用于禁止优先级低于某特定等级的中断,在内核提供的操作函数如下:

         uint32_t  __get_BASEPRI(void);//获取当前被屏蔽等级阈值

         void __set_BASEPRI(uint32_t basePri);//设置当前被屏蔽的等级阈值

         举例:

         __set_BASEPRI(0x60); //禁止优先级在0x60~0xFF间的中断。

1.4、Core控制模块的地址空间

         ARM Cortex m4地址总线位宽32bit,支持4G的存储器容量,但实际在MCU中最多支持几个M的Flash容量,因此其它的地址位置用于各种外设的访问。

         4G的地址空间被分为8个块,每个块512M,代码区域为首块(0x00000000~0x1FFFFFFF),内部SRAM区域为第二块(0x20000000~0x3FFFFFFF),而内核控制模块则位于第8块,如下图所示:

标签:__,优先级,中断,STM32L4,NVIC,IRQn,uint32
来源: https://blog.csdn.net/goodshanzi/article/details/119683535