2、中断使能
在中断初始化中仅仅是对事件n的使能,在此要对相应的中断进行使能。
类比于Cortex-M3架构,在MDK内与NVIC相关的寄存器,MDK为其定义了如下的结构体
NVIC(NestedVectoredInterruptController)嵌套中断向量控制器
[objc] viewplain copy
1.14px;">/** \ingroup CMSIS_core_register
2. \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
3. \brief Type definitions for the NVIC Registers
4. @{
5. */
6.
7./** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
8. */
9.typedef struct
10.{
11. __IO uint32_t ISER[1]; /*!
< Offset:
0x000 (R/W) Interrupt Set Enable Register */
12. uint32_t RESERVED0[31];
13. __IO uint32_t ICER[1]; /*!
< Offset:
0x080 (R/W) Interrupt Clear Enable Register */
14. uint32_t RSERVED1[31];
15. __IO uint32_t ISPR[1]; /*!
< Offset:
0x100 (R/W) Interrupt Set Pending Register */
16. uint32_t RESERVED2[31];
17. __IO uint32_t ICPR[1]; /*!
< Offset:
0x180 (R/W) Interrupt Clear Pending Register */
18. uint32_t RESERVED3[31];
19. uint32_t RESERVED4[64];
20. __IO uint32_t IP[8]; /*!
< Offset:
0x300 (R/W) Interrupt Priority Register */
21.} NVIC_Type;
22.
23./*@} end of group CMSIS_NVIC */
ISER[1]:
中断使能寄存器。
由前边可以看到,nRF51的寄存器编号为0-25,在这里ISER[1]为32位寄存器,总共可以表示32个中断,bit0-bit25分别对应中断0-25(其实后来发现在NVIC_EnableIRQ()函数中是将1左移IRQn位之后又与0x1F,也就是空出了低五位,所以在这里应该是对应的高地址,而把低位给空出来的)。
要使能某个中断,必须设置相应的ISER位为1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、I/O口映射等设置才算是一个完整的中断设置)。
此处是按照STM32中断设置理解的。
ICER[1]:
中断除能寄存器,和ISER的作用恰好相反,用来清除某个中断的使能的。
专门设置一个ICER来清除中断位,而不是向ISER写0来清除,这是因为NVIC的这些寄存器都是写1有效的,写0无效的。
ISPR[1]:
中断挂起控制寄存器。
通过置1可以将正在进行的中断挂起,而执行同级或者更高级别的中断。
ICPR[1]:
中断解挂控制寄存器。
通过置1可以将挂起的中断解挂。
IP[8]:
中断优先级控制寄存器组。
这个寄存器组相当重要。
中断分组与这个寄存器密切相关。
在这里插入一下中断优先级的理解。
因为以前都是用的STM32,在这里就按照Cortex-M3架构来理解。
Cortex-M3中有两个优先级的概念——抢占优先级和响应优先级,有人把响应优先级称作“亚优先级”和“副优先级”,每个中断源都需要被指定这两种优先级。
具有高抢占优先级的中断可以在具有低抢占优先级的中断处理过程中被响应,即中断嵌套。
当两个中断源的抢占优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。
如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个(在《原子教你玩STM32》中说在抢占优先级相同的中断,高优先级的响应优先级不可打断低响应优先级的中断,有待考证);如果他们的抢占优先级和响应优先级相等,则根据他们在中断表中的排位顺序来决定先处理哪一个。
在STM32中需要用NVIC_PriorityGroupConfig(uint32_tNVIC_PriorityGroup)先对中断优先级进行分组,这个分组在一个程序中只能设定一次,是在中断与复位控制寄存器SCB->AIRCR中设置的,也就是分组之后所有的中断只能按照这个分组方式进行设定抢占优先级和响应优先级。
在对中断优先级进行分组设置之后,要对每个中断的中断源优先级进行设置,也就是设置中断优先级控制寄存器IP,中断源优先级具体设置了该中断源的优先级别。
在此先说一下STM32中断优先级设置的步骤:
系统运行开始的时候设置中断分组,确定组号,也就是确定抢占优先级和子优先级的分配位数,调用函数为NVIC_PriorityGroupConfig();
设置用到的中断的中断优先级别,对每个中断调用函数为NVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct);
而在nRF51822中,我现在还没有碰到中断优先级进行分组的情况,在此就先不写,如果将来用到,再进行相关补充
首先是中断使能,和STM32中在初始化NVIC_InitStruct结构体的同时完成中断使能不同,nRF51822通过专门的函数NVIC_EnableIRQ(IRQn_TypeIRQn)来实现响应中断使能,形参变量IRQn为要进行初始化的中断编号,在本博文的开头已经给出,在SDK的core-m0.h中定义,以下为中断使能函数。
[objc] viewplain copy
1./** \brief Enable External Interrupt
2.
3. The function enables a device-specific interrupt in the NVIC interrupt controller.
4.
5. \param [in] IRQn External interrupt number. Value cannot be negative.
6. */
7.__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
8.{
9. NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
10.}
11.
12.
13./** \brief Disable External Interrupt
14.
15. The function disables a device-specific interrupt in the NVIC interrupt controller.
16.
17. \param [in] IRQn External interrupt number. Value cannot be negative.
18. */
19.__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
20.{
21. NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
22.}
例如,要使能GPIOTE中断,则调用
[objc] viewplain copy
1.NVIC_EnableIRQ(GPIOTE_IRQn);
3、中断优先级设置
中断优先级设置源函数如下:
[objc] viewplain copy
1./** \brief Set Interrupt Priority
2.
3. The function sets the priority of an interrupt.
4.
5. \note The priority cannot be set for every core interrupt.
6.
7. \param [in] IRQn Interrupt number.
8. \param [in] priority Priority to set.
9. */
10.__STATIC_INLINE void NVIC_SetPrior