完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
每一个外部中断都有一个对应的优先级寄存器,Cortex-M0中NVIC-IPR共有8个寄存器,而每个寄存器管理4个IRQ中断,所以M0的IRQ中断源最多只支持32个,再加上16个内核中断,也就是说M0最多48个中断源。 Cortex-M0采用ARMv6-M架构,优先级寄存器配置位有8位,但是有效位只有最高2位,这个地方很多人使用了Cortex-M3后一直也认为Cortex-M0也是最高3或4位有效位,在arm官方资料中有对比两个版本的差别。因此Cortex-M0可编程优先级有4个,加上3个固定的优先级(复位、NMI、HardFault),Cortex-M0总共有7个中断优先级。 Cortex-M0内核的中断优先级寄存器是以最高位(MSB)对齐的,并且只支持字传输,每次访问都会同时涉及4个中断优先级寄存器。见下图: 因为Bit0 - Bit5没有使用,所以如果没有进行写操作读出都为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已经在运行一个中断,而有了新的更高优先级的中断请求,正在运行的中断将会被暂停,转而执行更高优先级的中断,高优先级中断执行完成后又回到原来的低优先级中断。如果出现两个同一优先级的中断,则是判断谁开始发起中断请求,MCU会先执行同一优先级中首先发起请求的中断。 MM32F0130系列中断向量表: typedef enum IRQn { NonMaskableInt_IRQn = -14, ///< 2 Non Maskable Interrupt HardFault_IRQn = -13, ///< 3 Cortex-M0 Hard Fault Interrupt MemoryManagement_IRQn = -12, ///< 4 Cortex-M0 Memory Management Interrupt BusFault_IRQn = -11, ///< 5 Cortex-M0 Bus Fault Interrupt UsageFault_IRQn = -10, ///< 6 Cortex-M0 Usage Fault Interrupt SVC_IRQn = -5, ///< 11 Cortex-M0 SV Call Interrupt DebugMonitor_IRQn = -4, ///< 12 Cortex-M0 Debug Monitor Interrupt PendSV_IRQn = -2, ///< 14 Cortex-M0 Pend SV Interrupt Systick_IRQn = -1, ///< 15 Cortex-M0 System Tick Interrupt WWDG_IWDG_IRQn = 0, ///< WatchDog Interrupt WWDG_IRQn = 0, ///< Window WatchDog Interrupt PVD_IRQn = 1, ///< PVD through EXTI Line detect Interrupt BKP_IRQn = 2, ///< BKP through EXTI Line Interrupt RTC_IRQn = 2, ///< RTC through EXTI Line Interrupt FLASH_IRQn = 3, ///< FLASH Interrupt RCC_CRS_IRQn = 4, ///< RCC & CRS Interrupt RCC_IRQn = 4, ///< RCC Interrupt EXTI0_1_IRQn = 5, ///< EXTI Line 0 and 1 Interrupts EXTI2_3_IRQn = 6, ///< EXTI Line 2 and 3 Interrupts EXTI4_15_IRQn = 7, ///< EXTI Line 4 to 15 Interrupts HWDIV_IRQn = 8, ///< HWDIV Global Interrupt DMA1_Channel1_IRQn = 9, ///< DMA1 Channel 1 Interrupt DMA1_Channel2_3_IRQn = 10, ///< DMA1 Channel 2 and Channel 3 Interrupts DMA1_Channel4_5_IRQn = 11, ///< DMA1 Channel 4 and Channel 5 Interrupts ADC_COMP_IRQn = 12, ///< ADC & COMP Interrupts COMP_IRQn = 12, ///< COMP Interrupts ADC_IRQn = 12, ///< ADC Interrupts ADC1_IRQn = 12, ///< ADC Interrupts TIM1_BRK_UP_TRG_COM_IRQn = 13, ///< TIM1 Break, Update, Trigger and Commutation Interrupts TIM1_CC_IRQn = 14, ///< TIM1 Capture Compare Interrupt TIM2_IRQn = 15, ///< TIM2 Interrupt TIM3_IRQn = 16, ///< TIM3 Interrupt TIM14_IRQn = 19, ///< TIM14 Interrupt TIM16_IRQn = 21, ///< TIM16 Interrupt TIM17_IRQn = 22, ///< TIM17 Interrupt I2C1_IRQn = 23, ///< I2C1 Interrupt SPI1_IRQn = 25, ///< SPI1 Interrupt SPI2_IRQn = 26, ///< SPI1 Interrupt UART1_IRQn = 27, ///< UART1 Interrupt UART2_IRQn = 28, ///< UART2 Interrupt CAN_IRQn = 30, ///< CAN Interrupt USB_IRQn = 31, ///< USB Interrupt } IRQn_Type; 设置中断优先级的流程:先读一个字,再修改对应字节,最后整个字写回。 1.1C代码 void__NVIC_SetPriority() { unsigned long temp; //定义一个临时变量 temp = *(volatile unsigned long)(0xE000E400); //读取IRP0值 temp &= (0xFF00FFFF |(0xC0 << 16)); //修改中断#2优先级为0xC0 *(volatile unsigned long)(0xE000E400) = temp; //设置IPR0 } 1.2汇编代码 在程序中可以一次设置多个中断优先级。void__NVIC_SetPriority() { LDR R0, =0xE000E100 ; //设置使能中断寄存器地址 MOVS R1, #0x4 ; //中断#2 STR R1, [R0] ; //使能#2中断 LDR R0, =0xE000E200 ; //设置挂起中断寄存器地址 MOVS R1, #0x4 ; //中断#2 STR R1, [R0] ; //挂起#2中断 LDR R0, =0xE000E280 ; //设置清除中断挂起寄存器地址 MOVS R1, #0x4 ; //中断#2 STR R1, [R0] ; //清除#2的挂起状态 } 1.3CMSIS标准设备驱动函数 //设置中断优先级 __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { 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位。 方法一: void NVIC_SetPriority(TIM1_CC_IRQn, 3) ; //设置#14中断的优先级为0xC0 方法二: void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 设置好中断优先级后,用户还可以读取当前已经设置的中断优先级。 //读取中断优先级 __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
2252个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11817 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5975 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
11115 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4594 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4326 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
1269浏览 1评论
846浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 03:48 , Processed in 0.605753 second(s), Total 37, Slave 30 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号