Cortex-M0中断控制和系统控制(二)
转载:https://aijishu.com/a/1060000000237975
每个外部中断都有相应的优先级寄存器。NVIC有8个寄存器-Cortex-M0的IPR,每个寄存器管理4个IRQ中断,所以M0最多只支持32个IRQ中断源,加上16个核心中断,也就是说M0最多有48个中断源。
Cortex-M0采用Armv6-M架构,优先级寄存器的配置位为8位,但最高有效位仅为2位。这个地方很多人一直认为Cortex-M0也是使用Cortex-M3后的3、4位最高有效位,arm官方信息中两个版本是有区别的。因此,Cortex-M0有四个可编程优先级,而Cortex-M0有三个固定优先级(复位、NMI和HardFault),总共有七个中断优先级。
Cortex-M0内核的中断优先级寄存器与最高有效位(MSB)对齐,仅支持字传输。每次访问同时涉及四个中断优先级寄存器。见下图:
因为不使用位0-位5,所以如果没有写操作,读出全部为0。
因为不同的Cortex-M系列有不同的中断优先级,所以可以在CMSIS库的头文件中检查优先级\_\_NVIC\_PRIO\_BITS的个数。
中断优先级寄存器的编程应在中断使能之前完成,通常在程序开始时完成。根据arm的官方信息,应该避免在中断使能后改变中断优先级,因为这种情况的结果在ARMv6-M系统结构中是不可预测的,Cortex-M0处理器不支持。Cortex-M3/M4处理器的情况有所不同。它们都支持中断优先级的动态切换。Cortex-M3处理器和Cortex-M0处理器的另一个区别是,当访问中断优先级寄存器时,Cortex-M3支持字节或半字传输,因此一次只能设置一个寄存器。如果需要改变优先级,需要在程序中重置中断优先级寄存器之前关闭中断。
在Cortex-M内核中,中断的优先级值越低,逻辑优先级越高。例如,中断优先级为2的中断可以抢占中断优先级为3的中断,但不能反过来。换句话说,中断优先级2的优先级高于中断优先级3。
Cortex-M0处理器支持中断嵌套,无需任何软件干预。如果单片机已经在运行一个中断,并且有一个新的优先级更高的中断请求,运行中的中断将被挂起,而执行优先级更高的中断。高优先级中断执行后,将回到原来的低优先级中断。如果有两个优先级相同的中断,则确定是谁开始发起中断请求,MCU将首先执行与发起请求优先级相同的中断。
MM32F0130系列中断向量表:
typedefensumirqn {
NonMaskableInt_IRQn=-14,///2NonMaskableInterrupt
HardFault_IRQn=-13,///3 cortex-m0 hard fault interrupt
MemoryManagement_IRQn=-12,///4 cortex-m0 memorymanagementinterrupt
BusFault_IRQn=-11,///5Cortex-M0BusFaultInterrupt
UsageFault_IRQn=-10,///6 cortex-m0usagefaulttinterrupt
SVC_IRQn=-5,///11Cortex-M0SVCallInterrupt
DebugMonitor_IRQn=-4,///12 cortex-m0 debugmonitorinterrupt
PendSV_IRQn=-2,///14 ortex-m0 PendSV interrupt
SysTick_IRQn=-1,///15 cortex-m0systemtick interrupt
WWDG_IWDG_IRQn=0,///watchdointerrupt
WWDG_IRQn=0,///窗口监视中断
PVD_IRQn=1,///pvdthroothxtilinedprotectinterrupt
BKP_IRQn=2,///bkpthroughextiliineinterrupt
RTC_IRQn=2,///rtcthrughextilineinterrupt
FLASH_IRQn=3,///FLASHInterrupt
RCC_CRS_IRQn=4,///RCCCRSInterrupt
RCC_IRQn=4,///RCCInterrupt
EXTI0_1_IRQn=5,EXTI0和1Interrupts
EXTI2_3_IRQn=6,EXTI2和3中断
EXTI4_15_IRQn=7,///exti line4 to 15中断
HWDIV_IRQn=8,///HWDIVGlobalInterrupt
DMA1_Channel1_IRQn=9,///DMA1Channel1Interrupt
DMA1_Channel2_3_IRQn=10,///DMA1 channel 2和channel 3中断
DMA1_C
hannel4_5_IRQn=11,///DMA1Channel4andChannel5Interrupts
ADC_COMP_IRQn=12,///ADCCOMPInterrupts
COMP_IRQn=12,///COMPInterrupts
ADC_IRQn=12,///ADCInterrupts
ADC1_IRQn=12,///ADCInterrupts
TIM1_BRK_UP_TRG_COM_IRQn=13,///TIM1Break,Update,TriggerandCommutationInterrupts
TIM1_CC_IRQn=14,///TIM1CaptureCompareInterrupt
TIM2_IRQn=15,///TIM2Interrupt
TIM3_IRQn=16,///TIM3Interrupt
TIM14_IRQn=19,///TIM14Interrupt
TIM16_IRQn=21,///TIM16Interrupt
TIM17_IRQn=22,///TIM17Interrupt
I2C1_IRQn=23,///I2C1Interrupt
SPI1_IRQn=25,///SPI1Interrupt
SPI2_IRQn=26,///SPI1Interrupt
UART1_IRQn=27,///UART1Interrupt
UART2_IRQn=28,///UART2Interrupt
CAN_IRQn=30,///CANInterrupt
USB_IRQn=31,///USBInterrupt
}IRQn_Type;
设置中断优先级的流程:先读一个字,再修改对应字节,最后整个字写回。
1.1 C代码
void__NVIC_SetPriority()
{
unsignedlongtemp;//定义一个临时变量
temp=*(volatileunsignedlong)(0xE000E400);//读取IRP0值
temp=(0xFF00FFFF|(0xC016));//修改中断#2优先级为0xC0
*(volatileunsignedlong)(0xE000E400)=temp;//设置IPR0
}
1.2 汇编代码
在程序中可以一次设置多个中断优先级。
void__NVIC_SetPriority()
{
LDRR0,=0xE000E100;//设置使能中断寄存器地址
MOVSR1,#0x4;//中断#2
STRR1,[R0];//使能#2中断
LDRR0,=0xE000E200;//设置挂起中断寄存器地址
MOVSR1,#0x4;//中断#2
STRR1,[R0];//挂起#2中断
LDRR0,=0xE000E280;//设置清除中断挂起寄存器地址
MOVSR1,#0x4;//中断#2
STRR1,[R0];//清除#2的挂起状态
}
1.3 CMSIS标准设备驱动函数
//设置中断优先级
__STATIC_INLINEvoid__NVIC_SetPriority(IRQn_TypeIRQn,uint32_tpriority)
{
if((int32_t)(IRQn)=0){
NVIC-IP[_IP_IDX(IRQn)]=((uint32_t)(NVIC-IP[_IP_IDX(IRQn)]~(0xFFUL_BIT_SHIFT(IRQn)))|
(((priority(8U-__NVIC_PRIO_BITS))(uint32_t)0xFFUL)_BIT_SHIFT(IRQn)));
}
else{
SCB-SHP[_SHP_IDX(IRQn)]=((uint32_t)(SCB-SHP[_SHP_IDX(IRQn)]~(0xFFUL_BIT_SHIFT(IRQn)))|
(((priority(8U-__NVIC_PRIO_BITS))(uint32_t)0xFFUL)_BIT_SHIFT(IRQn)));
}
}
这里的参数IRQn为中断ID号,可以为负,也可以为正。当IRQn为负时,设置系统异常的优先级,当IRQn大于等于0时,设置外设中断优先级,芯片厂商会提供中断向量表IRQn\_Type,应用层只需要调用即可;priority是0、1、2、3,函数内部会自动移位到对应的优先级最高2位。
方法一:
voidNVIC_SetPriority(TIM1_CC_IRQn,3);//设置#14中断的优先级为0xC0
方法二:
voidNVIC_Config(void)
{NVIC_InitTypeDefNVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(NVIC_InitStructure);
}
设置好中断优先级后,用户还可以读取当前已经设置的中断优先级。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/126073.html