STM32中断和异常

异常主要分为中断(如IO口,UART,等)和系统异常(如NMI,SYCTICK,等),注意区分中断和系统异常,下文异常为统称,

在CMSIS中,IRQn_Type为异常类型的枚举,系统异常一般为负数,中断则从0开始


常用的操作异常的CMSIS函数,为了可移植性,建议使用这些函数操作异常。中断相关寄存器主要在NVIC,系统异常相关寄存器主要在SCB中。

STM32中断和异常_第1张图片

这些函数在core_cm4.h中定义


系统复位时,所有中断都是禁止的,并且优先级为0(最高优先级),所有系统初始化时要调用一次NVIC_PriorityGroupConfig来设置优先级分组情况。


异常优先级分为抢占优先级子优先级,高抢占优先级的异常(优先级数字较小)可以抢占低抢占优先级(优先级数字较大)的异常。子优先级决定抢占优先级相同的异常谁先执行。如果抢占优先级和子优先级都相同,则异常号小的异常先执行。

hard fault,NMI,reset,优先级为-1,-2,-3,不可设置,其他异常的优先级只能设置0和以上的数字,所以他们在任何时候都可以抢占其他异常。


中断的状态:

    中断可以是Enable或Disable或,由软件设置和清除

    中断可以是Pending或Not Pending,当中断产生时Pending位会被硬件置位,中断消失后不会清除,进入中断处理函数时会被硬件清除,也可以软件设置和清除

    中断可以是Active或Inactive,由硬件设置和清除,正在执行的异常为Active,其他为Inactive,当高优先级中断抢占时,被抢占的中断仍是Active


当中断产生时Pending位会硬件被置位,处理器会马上处理Pending的中断,但有些时候,当中断产生时,处理器正在处理其他高优先级的异常,则处理完后,会根据Penging位再处理该中断。如果在处理高优先级异常过程中,Pending位被清除,则高优先级异常处理完成后不会再处理该中断。

如果中断产生时,该中断被屏蔽了,Pending位也会被置位。例如在执行中断时(此时为Active),将该中断Disable,此时又有该中断产生,则该中断Pending位会被置位。


除了NVIC的Pending位以外,EXTI有相应的Pending位在EXTI寄存器中,TIMER等也是,所以在中断处理函数中要调用相应的清除函数EXTI_ClearITPendingBit,TIM_ClearITPendingBit等,而NVIC的Pending位在进入中断处理函数时会被硬件清除


PRIMASK寄存器(只有最低位有用,其他为保留位)用于禁止所有异常,除了NMI和Hard Fault,只能在特权模式下访问

CMSIS操作的函数:

void __enable_irq();

void __disable_irq();

汇编操作:

CPSIE I           ;Clear PRIMASK (Enable interrupts)
CPSID I           ;Set PRIMASK (Disable interrupts)


需要软件触发中断可以使用:NVIC_SetPendingIRQ(Timer0_IRQn);

如果需要中断处理函数在下条指令前执行则需要加Barrier

NVIC_SetPendingIRQ(Timer0_IRQn);
__DSB();               //Data Synchronization Barrier
__ISB();                //Instruction Synchronization Barrier


ARM体系结构的C编译器遵循AAPCS原则,对函数调用由如下规定:

R0-R3, R12, LR, and PSR为调用者保存寄存器,就是当调用一个函数前需要保存这些寄存器,调用完后恢复,如果调用完后不关心这些寄存器则调用前可以不保存。

R4-R11为被调用者保存寄存器,就是任何函数如果要操作这些寄存器则要先保存,函数返回前要恢复。

浮点数单元的寄存器也一样

S0-S15 为调用者保存寄存器

S16-S31 为被调用者保存寄存器

R0-R3也被用作函数输入参数(R0为第一个参数...),R0也用作函数返回值(如果返回值为64bit,则也会用R1)


在进入异常处理函数前,硬件会将如下寄存器入栈(使用PSP或MSP),如果没有浮点数单元,则只有8个(xPSR,返回地址,LR,R12,R3-R0),这些寄存器组称为Stack Frame

根据AAPCS,在函数进入和退出时,SP的值必须double-word对齐,否则会插入padding以保证对齐。该对齐也可以关闭(xPSR的bit9为0时则不对齐)对齐都由硬件根据xPSR的bit9自动完成

操作CCR寄存器对是否对齐进行设置:

SCB->CCR |= SCB_CCR_STKALIGN_Msk;           // Set STKALIGN bit (bit 9) of CCR

STM32中断和异常_第2张图片

进入异常处理函数后,LR寄存器的值被设置为EXC_RETURN,该值根据此时处理器的状态设置为相应的值,如下图。

由于高四位永远是0xF,所以异常处理函数返回地址不能在0xF0000000 到 0xFFFFFFFF之间,但这部分区间是不能执行区,所以对程序并不造成什么问题。

STM32中断和异常_第3张图片

在Thread Mode下可以使用PSP或MSP,在Handler Mode下只能使用MSP。由于EXC_RETURN的bit2决定了入栈时用的SP,所以在出栈时也会用该SP,这样在线程模式进入异常处理模式,以及异常嵌套时都不会造成栈的混乱。也一样模式。


参考文献:

STM32F3 and STM32F4 Series Cortex®-M4 programming manual(PM0214)

The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors

你可能感兴趣的:(STM32)