硬汉嵌入式论坛

 找回密码
 立即注册
查看: 9335|回复: 7
收起左侧

STM32中断优先级和开关总中断

[复制链接]

759

主题

1050

回帖

3332

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3332
发表于 2013-3-6 09:09:18 | 显示全部楼层 |阅读模式
STM32中断优先级和开关总中断

一,中断优先级:
STM32(Cortex-M3)中的优先级概念
STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:

[blockquote]所有8位用于指定响应优先级
最高1位用于指定抢占式优先级,最低7位用于指定响应优先级
最高2位用于指定抢占式优先级,最低6位用于指定响应优先级
最高3位用于指定抢占式优先级,最低5位用于指定响应优先级
最高4位用于指定抢占式优先级,最低4位用于指定响应优先级
最高5位用于指定抢占式优先级,最低3位用于指定响应优先级
最高6位用于指定抢占式优先级,最低2位用于指定响应优先级
最高7位用于指定抢占式优先级,最低1位用于指定响应优先级
[/blockquote]
这就是优先级分组的概念,在CM3中一共分8个组,GROUP0优先级最高,GROUP7最低,但是在后面讲到的STM32这块具体的芯片只实现了5个优先级分组,即简化了设计,读者可以自行参考。

--------------------------------------------------------------------------------
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
[blockquote]第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级
[/blockquote]
可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:

NVIC_PriorityGroup_0 => 选择第0组
NVIC_PriorityGroup_1 => 选择第1组
NVIC_PriorityGroup_2 => 选择第2组
NVIC_PriorityGroup_3 => 选择第3组
NVIC_PriorityGroup_4 => 选择第4组

接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:

// 选择使用优先级分组第1组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
// 使能EXTI0中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
  
// 使能EXTI9_5中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

要注意的几点是:

1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;

2)抢占式优先级别相同的中断源之间没有嵌套关系;

3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。

三、Systick中断优先级

打开Systick中断,我们一般调用函数 SysTick_Config(SystemCoreClock / 1000);
SysTick_Config 函数是一个内联函数 (用__INLINE修饰),在编译时会自动展开在代码行中,类似于宏展开。
[blockquote]static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

[/blockquote][blockquote]#ifndef __NVIC_PRIO_BITS
  #define __NVIC_PRIO_BITS    4               /*!< standard definition for NVIC Priority Bits */
#endif
[/blockquote]函数中的宏 __NVIC_PRIO_BITS = 4, 也就是SysTick_IRQn的中断优先级被设置为 (1 << 4)  - 1 = 15, 也就是最低优先级。




三、开关总中断:
在STM32/Cortex-M3中是通过改变CPU的当前优先级来允许或禁止中断。
PRIMASK位:只允许NMI和hard fault异常,其他中断/异常都被屏蔽(当前CPU优先级=0)。
FAULTMASK位:只允许NMI,其他所有中断/异常都被屏蔽(当前CPU优先级=-1)。

在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h) 定义了四个函数操作PRIMASK位和FAULTMASK位,改变CPU的当前优先级,从而达到控制所有中断的目的。

下面两个函数等效于关闭总中断:
void NVIC_SETPRIMASK(void);
void NVIC_SETFAULTMASK(void);

下面两个函数等效于开放总中断:
void NVIC_RESETPRIMASK(void);
void NVIC_RESETFAULTMASK(void);

上面两组函数要成对使用,不能交叉使用。

例如:

第一种方法:
NVIC_SETPRIMASK();   //关闭总中断
NVIC_RESETPRIMASK();//开放总中断

第二种方法:
NVIC_SETFAULTMASK();   //关闭总中断
NVIC_RESETFAULTMASK();//开放总中断
常常使用
NVIC_SETPRIMASK();                    // Disable Interrupts
NVIC_RESETPRIMASK();                  // Enable Interrupts
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116761
QQ
发表于 2013-3-6 09:55:18 | 显示全部楼层
函数中的宏 __NVIC_PRIO_BITS = 4, 也就是SysTick_IRQn的中断优先级被设置为 (1 << 4)  - 1 = 7, 也就是最低优先级
(1 << 4)  - 1 = 7 算错了  应该是15.
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116761
QQ
发表于 2013-3-6 09:58:01 | 显示全部楼层
NVIC.png


NVIC2.jpg


nvic3.jpg
回复

使用道具 举报

759

主题

1050

回帖

3332

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3332
 楼主| 发表于 2013-3-6 11:10:14 | 显示全部楼层
确实算错了,已更正。

我现在目的是希望一个TIMx定时器中断能打断Systick中断,获得抢占执行权。实际测试结果不对,因此查了下相关资料。
如果只调用 SysTick_Config() 函数,确实设置了最低优先级。但是缺省优先级分组为0,因此TIM定时中断不能抢占Systick中断。
需要 再调用 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 函数,形参只要不选 NVIC_PriorityGroup_0即可。

NVIC_SetPriority() 函数是直接修改中断优先级
4个bit (包含了抢占优先级和响应优先级)
NVIC_Init(&NVIC_InitStructure); 函数可以分别指定抢占优先级和响应优先级。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116761
QQ
发表于 2013-3-6 11:46:39 | 显示全部楼层
按照版主的测试结果,是不是说NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);函数,
形参只要不选 NVIC_PriorityGroup_0
外部中断(比如SPI TIM 等)可以抢占系统级中断(比如SysTick ,PendSV等)
这个问了已经纠结了1年了,以前打算做一个测试程序,但是也不知道怎么做比较好。
回复

使用道具 举报

759

主题

1050

回帖

3332

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3332
 楼主| 发表于 2013-3-6 12:11:55 | 显示全部楼层
是的。

我的应用需要在50us定时器中断服务程序中翻转IO.  如果不启用抢占式中断,偶尔出现波形脉宽不准,原因就是 systick中断执行完毕后才能响应定时中断。  
必须用 NVIC_PriorityGroupConfig() 函数设置 非0组优先级。来保证定时中断能够抢占systick中断。
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2013-3-9 22:15:34 | 显示全部楼层

回 armfly 的帖子

armfly:确实算错了,已更正。

我现在目的是希望一个TIMx定时器中断能打断Systick中断,获得抢占执行权。实际测试结果不对,因此查了下相关资料。
如果只调用 SysTick_Config() 函数,确实设置了最低优先级。但是缺省优先级分组为0,因此TIM定时中断不能抢占Systick中断。
需要 再调用 N .. (2013-03-06 11:10) 
systick缺省优先级分组为0,在哪里,能告诉我下吗,我没找到
回复

使用道具 举报

759

主题

1050

回帖

3332

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3332
 楼主| 发表于 2013-3-11 20:53:48 | 显示全部楼层
中断优先级分组是全局设置,不是针对某1个中断。CPU复位后,默认就是0组。如果需要改变优先级分组设置,需调用 NVIC_PriorityGroupConfig。
如果你没找到,那就是缺省0组。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-7-5 13:56 , Processed in 0.310160 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表