历史上的今天
返回首页

历史上的今天

今天是:2024年12月03日(星期二)

正在发生

2018年12月03日 | STM32 中断优先级以及全局允许和禁止

2018-12-03 来源:eefocus

请问例程上为什么要把串口中断优先级设置在NVIC中断分组2


NVIC: M3内核允许8bit做优先级分组设置,而STM32只有4bit可以设置。 

AIRCR寄存器的4个位的分组方式如下: 

第0组:所有4位用于指定响应优先级 

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级 

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级 

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级 

第4组:所有4位用于指定抢占式优先级 

例:定义为第二组,抢占式优先级2bit,响应式优先级2bit,2bit共可有4种状态,也就是总共能设置4*4=16个中断优先级。 

定义为第三组,抢占式优先级3bit,响应式优先级1bit,也就是总共能设置8*2=16个中断优先级。


我觉得可能是易于程序员查看代码吧,比如把串口1、2、3分在同一组,把SPI1、2、3分在同一组,看起来比较直观。 

实际上分不分组都能实现同一种结果。


====================================


优先级可以被分为高低两个位段,分别是抢占优先级和亚优先级


Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位 AIRC 中 PRIGROUP 的值规定了设置和确定每个外部中断通道优先级的格式。例如,在上面将 0x05 写入了 AIRC 中 PRIGROUP,也就规定了当前系统中只能有 4 个抢先式优先级,相同的抢先式优先级下还可以有 4 个不同级别的子优先级,他们分别为: 

位[7:6]                   位[5:4]                  位[3:0] 
00         0 号抢先优先级   00        0 号子优先级    无效 
01         1 号抢先优先级   01        1 号子优先级    无效 
10         2 号抢先优先级   10        2 号子优先级    无效 
11         3 号抢先优先级   11        3 号子优先级    无效 


在Cortex—M3的优先级分配中,较低的优先级值具有较高的优先级。


数值小的优先级高, 数值大的优先级低


a 只能高抢先优先级的中断可以打断低抢先优先级的中断服务,构成中断嵌套。


b 当 2(n)个相同抢先优先级的中断出现,它们之间不能构成中断嵌套,但 STM32 首先响应子优先级高的中断。


c 当 2(n)个相同抢先优先级和相同子优先级的中断出现,STM32 首先响应中断通道所对应的中断向量地址低的那个中断。 


可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:

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


第0组:所有4位用于指定响应优先级   ( 从不嵌套 )

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级

第4组:所有4位用于指定抢占式优先级 ( 最大的嵌套可能性 ) ( 类似于 STR710 )



subpriority 开始的位号 :


如果从 7 号开始 那么没有 pre-emption priority, [ b7 b6 b5 b4 ] 全部为 subpriority 


如果从 6 号开始 那么 [ b7 ]为 pre-emption priority, [ b6 b5 b4 ] 为 subpriority 


如果从 3 号开始 那么 [ b7 b6 b5 b4 ]为 pre-emption priority, 没有 subpriority 


[pre-emption priority] :: [ subpriority ] ( STM32 共计 4 位 ) 所以无论如何配置做多只能有 16 级, 数值最小的具有最高的优先级


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


要注意的几点是:

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

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

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



#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
                                                            4 bits for subpriority */
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
                                                            3 bits for subpriority */
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
                                                            2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
                                                            1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
                                                            0 bits for subpriority */


/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
  *                                4 bits for subpriority
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
  *                                3 bits for subpriority
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
  *                                1 bits for subpriority
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
  *                                0 bits for subpriority
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;



/**
  * @brief  Initializes the NVIC peripheral according to the specified
  *   parameters in the NVIC_InitStruct.
  * @param  NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
  *   the configuration information for the specified NVIC peripheral.
  * @retval None
  */
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
  
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
    
  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/    
    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
    tmppre = (0x4 - tmppriority);
    tmpsub = tmpsub >> tmppriority;


    tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    tmppriority = tmppriority << 0x04;
        
    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
    
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else // if (NVIC_InitStruct->NVIC_IRQChannelCmd == DISABLE)
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}


stm32如何开关中断


在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



推荐阅读

史海拾趣

BEI Sensors公司的发展小趣事

自上世纪80年代起,Beckhoff便将基于PC的自动化新技术作为公司的发展理念。通过不断研发和创新,公司成功地将工业PC、现场总线模块、驱动产品和控制软件等整合为一套完整的、相互兼容的控制系统。这一创新为工控领域带来了革命性的变革,使得工业自动化系统更加开放、灵活和高效。

Datapro International Inc公司的发展小趣事

面对不断变化的市场环境和客户需求,Datapro International Inc公司始终保持着对创新的追求。他们不断投入研发资源,推动新技术和新产品的不断涌现。同时,他们还积极关注行业趋势和客户需求的变化,以便及时调整自己的发展战略和业务模式。

在未来的发展中,Datapro International Inc公司将继续秉承“创新、质量、服务”的理念,致力于为客户提供更加卓越的产品和服务。同时,他们也将积极探索新的市场机会和商业模式,以实现更加持续、稳健的发展。

请注意,以上故事均为虚构内容,旨在展示一个电子行业公司可能的发展历程和故事。如需了解Datapro International Inc公司的真实历史和发展故事,请查阅相关官方资料或行业报告。

General Electronic Devices公司的发展小趣事
负责产生控制信号,驱动开关元件按一定频率和占空比工作。
Advanced Linear Devices公司的发展小趣事

AnalogicTech深知品质是企业生存和发展的关键。因此,公司建立了严格的质量管理体系,从原材料采购到产品出厂的每一个环节都进行严格把控。同时,公司还注重客户反馈和需求,不断优化产品和服务,以满足客户的期望和需求。这种对品质的执着追求和对客户的深度关注,使得AnalogicTech赢得了众多客户的信任和忠诚。

Davies Molding公司的发展小趣事

随着电子行业的快速发展,Davies Molding公司意识到,只有不断创新,才能在市场上保持领先地位。因此,公司积极引进先进的生产技术和设备,不断提升自身的研发能力。通过不断的技术创新,Davies Molding公司成功推出了一系列具有竞争力的新产品,满足了市场对高品质塑料注塑成型产品的需求。

City_Technology公司的发展小趣事

随着市场的不断变化和需求的日益增长,City Technology并未满足于已有的成就。在1980年代末至1990年代初,公司积极扩展产品线,相继开发了电化学有毒气体传感器和可燃气体传感器。这些新产品的推出,不仅丰富了公司的产品线,也进一步巩固了其在气体传感领域的领先地位。同时,公司还不断对已有产品进行优化升级,以满足客户日益多样化的需求。

问答坊 | AI 解惑

大容量闪存芯片-K9K2GXXU0M

K9K2GXXU0M是三星公司生产的大容量闪存芯片,它的单片容量可高达256M。文中主要介绍了... …

查看全部问答>

arm_design(基于ARM的嵌入式系统(软件设计))

arm_design(基于ARM的嵌入式系统(软件设计))…

查看全部问答>

avrmega16在7.3728Mhz的晶振下 不能用定时器产生1ms的精确时间吗?

为了实现9600的标准波特率 我试用了7.3728Mhz的晶振频率,可好像怎么这个晶振频率下产生1秒的时间呢??…

查看全部问答>

关于驱动的一点问题

写驱动是C合适?还是C++更好些? 性能上有什么差别吗?…

查看全部问答>

wince windows ce 能过 USB 接口 与 PC 电脑 通信的问题(不想用actviesync RAPI)

在PC端通过USB(2.0)线与wince 设备 连接,PC端实时向Wince device发送数据(或者双方传输数据),请问大牛们有没有什么好解决方案呀? 我有试过通过activesync RAPI通信,但是速度太慢了,达不到mass storage模式下的速度, 主要是不想用activesy ...…

查看全部问答>

zet6内部的flash怎么能做成优盘

                                 做成优盘 然后pc端 放很多文件进去 每个文件是一个程序 mcu能够随时调用…

查看全部问答>

Enet_tcp -客户端.

这是我根据网友academic以太网学习的例子改的,作为客户端链接主机的时候一直没有反应。请教大家问题出在哪里? #include #include \"inc/hw_ints.h\" #include \"inc/hw_memmap.h\" #include \"inc/hw_nvic.h\" #include \"inc/hw_types.h\" ...…

查看全部问答>

写windows驱动,需要懂得 windows操作系统原理吗

写windows驱动,需要懂得 windows操作系统原理吗…

查看全部问答>

领导给任务了啊

用单片机控制步进电机还有气缸的工作,是如何实现的! 1.做一个治具,连续测试六个产品,治具上要有能显示正在测试产品的LED指示灯, 2.面板上要有急停、测试、三档选择开关 3.每支产品测试时间为10S(时间可调范围为10~30S),前个产品测试完后 ...…

查看全部问答>

对比方案赛+单片机多路供电比较

本帖最后由 ddllxxrr 于 2014-6-8 11:23 编辑 本人从事单片机好多年了。第一步自然是电源电路。我司的单片机是220降到12V。然后再分出几路来。一般有12V,供外接模块或传感器用。5V供5V单片机或5V传感器用。3.3V供3.3V单片机用。 我司的方案是。2 ...…

查看全部问答>