中断优先级组
- STM32用4个比特位来指定中断源的优先级,并可分为5个优先级组(Cortex-M3中定义了8个比特位用于设置中断源的优先级,并且允许具有较少中断源时使用较少的寄存器位指定中断源的优先级)。
//stm32f10x.h
#define __NVIC_PRIO_BITS 4 /*!< STM32 uses 4 Bits for the Priority Levels */
//misc.h
/**
@code
The table below gives the allowed values of the pre-emption priority and subpriority according
to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function
============================================================================================================================
NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description
============================================================================================================================
NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority
| | | 4 bits for subpriority
----------------------------------------------------------------------------------------------------------------------------
NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority
| | | 3 bits for subpriority
----------------------------------------------------------------------------------------------------------------------------
NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority
| | | 2 bits for subpriority
----------------------------------------------------------------------------------------------------------------------------
NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority
| | | 1 bits for subpriority
----------------------------------------------------------------------------------------------------------------------------
NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority
| | | 0 bits for subpriority
============================================================================================================================
@endcode
*/
抢占优先级和响应优先级
执行顺序(同时到达)
- 抢占优先级不同时,抢占优先级高的先执行。
- 抢占优先级相同时,响应优先级高的先执行。
- 抢占优先级和响应优先级相同时,根据中断向量表的顺序执行。
打断规则(先后到达)
- 低抢占优先级在中断处理时,高抢占优先级可以被响应(中断的嵌套)。
- 相同抢占优先级在中断处理时,不管响应优先级是否高于前者,都不可打断前者的执行(需要等到前者处理完才可被处理)。
SysTick的中断优先级
- 当我们调用
SysTick_Config()
设置装载寄存器时,SysTick_Config()
已经为我们将SysTick
的中断优先级设置为最低。 - 以下是
SysTick_Config()
的实现。
//core_cm3.h
/**
* @brief Initialize and start the SysTick counter and its interrupt.
*
* @param ticks number of ticks between two interrupts
* @return 1 = failed, 0 = successful
*
* Initialise the system tick timer and its interrupt and start the
* system tick timer / counter in free running mode to generate
* periodical interrupts.
*/
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 */
}
- 主要是看
NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1)
这一句。这一句设置了SysTick_IRQn
的优先级。 - 以下是
NVIC_SetPriority()
的实现。
//core_cm3.h
/**
* @brief Set the priority for an interrupt
*
* @param IRQn The number of the interrupt for set priority
* @param priority The priority to set
*
* Set the priority for the specified interrupt. The interrupt
* number can be positive to specify an external (device specific)
* interrupt, or negative to specify an internal (core) interrupt.
*
* Note: The priority cannot be set for every core interrupt.
*/
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
else {
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */
}
(1<<__NVIC_PRIO_BITS) - 1)
即((1<<4) - 1)
,即1111(b)
。故SysTick
的中断优先级被设置为不管是哪个优先级分组始终是最低的。- 如下表所示。
优先级分组 | 抢占优先级 | 响应优先级 |
---|---|---|
NVIC_PriorityGroup_0 | - | 15 |
NVIC_PriorityGroup_1 | 1 | 7 |
NVIC_PriorityGroup_2 | 3 | 3 |
NVIC_PriorityGroup_3 | 7 | 1 |
NVIC_PriorityGroup_4 | 15 | - |
配置SysTick的中断优先级
- 只需要在使用
SysTick_Config()
后使用NVIC_SetPriority(SysTick_IRQn, xx)
配置SysTick
的中断优先级。 - 需要注意的是,
NVIC_SetPriority()
中的优先级是4比特位的数(0~15),需要根据优先级组选择合适的优先级。 - 如下代码将
SysTick
的中断优先级始终设置为最高优先级(设置任何优先级分组时都是最高优先级)。
NVIC_SetPriority(SysTick_IRQn, 0);