STM32-NVIC Interrupt Priority Grouping-Interrupt Priority Settings

Posted by drfate on Tue, 11 Jan 2022 18:34:50 +0100

STM32 - Interrupt Priority Management NVIC

1.NVIC interrupt priority grouping

The full name of NVIC is Nested vectoredinterrupt controller, which is a nested vector interrupt controller. Searching the vector table in the STM32F Chinese Reference Manual will find the corresponding break instructions.
The CM4/CM7 kernel supports 256 interrupts, including 16 kernel interrupts and 240 external interrupts, with 256-level programmable interrupt settings.
STM32F4/F7 doesn't use everything about the CM4 kernel, it just uses part of it.
STM32F40xx/STM32F41xx has a total of 92 interrupts. Ten kernel interrupts and 82 shieldable interrupts.
STM32F42xx/STM32F43xx has a total of 97 interrupts. Ten kernel interrupts and 87 shieldable interrupts.
STM32F76x has a total of 118 interrupts, 10 kernel interrupts, and 108 shieldable interrupts.

STM32 has 16 levels of programmable interrupt priority, which is what we commonly use to shield interrupts.

How to manage dozens of interruptions?

First, STM32 interrupts are grouped into groups 0-4. At the same time, a preemption priority and a response priority value are set for each interrupt.

Grouping configuration is configured in registers SCB->AIRCR: IP bit[7:4] has 4 bits and 2^4=16, so their priority can have 16 values. At this time, if it is a 2-bit preemption priority, its value may be 0, 1, 2, 3. That is, the preemption priority can be 0 to 3. Grouping is used to determine the preemption priority and response priority. The smaller the number, the higher its priority.

groupAIRCR[10: 8]IP bit[7:4] allocationDistribution results
0 111 0: 4 0-bit preemption priority, 4-bit response priority
1 110 1: 3 1-bit preemption priority, 3-bit response priority
2 101 2: 2 2-bit preemption priority, 2-bit response priority
3 100 3: 1 3-bit preemption priority, 1-bit response priority
4 011 4: 0 4-bit preemption priority, 0-bit response priority

Preemption Priority-Response Priority Difference:

A high priority preemption priority can interrupt an ongoing low preemption priority interrupt. Preemption determines whether to interrupt someone else.
Interrupts with the same preemption priority should not be interrupted by high response priority.
Interrupts with the same preemption priority, which one has the highest response priority and which executes first when both interrupts occur simultaneously.
If both interrupts have the same preemption priority and response priority, the interrupt will be executed before it occurs.

Give an example:

Assume that the interrupt priority group is set to 2, then set

Interrupt 3(RTC interrupt) has a preemption priority of 2 and a response priority of 1.

Interrupt 6 (external interrupt 0) has a preemption priority of 3 and a response priority of 0

Interrupt 7 (external interrupt 1) has a preemption priority of 2 and a response priority of 0.

Then the priority order of the three interrupts is: interrupt 7 > interrupt 3 > interrupt 6.

In general, during the execution of system code, only one interrupt priority grouping is set, such as Group 2. When grouping is set, the grouping is generally not changed. Changing groupings arbitrarily can lead to interrupt management confusion and unexpected execution results.

Interrupt priority grouping function stm32f7xx_in HALLIB Hal_ Cortex. C:void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
  NVIC_SetPriorityGrouping(PriorityGroup);
}

IS_can be found NVIC_ PRIORITY_ The definition of GROUP, which in turn determines how the PriorityGroup parameter is written.

#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PRIORITYGROUP_0) || \
                                       ((GROUP) == NVIC_PRIORITYGROUP_1) || \
                                       ((GROUP) == NVIC_PRIORITYGROUP_2) || \
                                       ((GROUP) == NVIC_PRIORITYGROUP_3) || \
                                       ((GROUP) == NVIC_PRIORITYGROUP_4))

At stm32f7xx_ Hal. HAL_can be found in C Init function: where HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); You can see that interrupt grouping is 2.

HAL_StatusTypeDef HAL_Init(void)
{
  /* Configure Flash prefetch and Instruction cache through ART accelerator */ 
#if (ART_ACCLERATOR_ENABLE != 0)
   __HAL_FLASH_ART_ENABLE();
#endif /* ART_ACCLERATOR_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);
  
  /* Init the low level hardware */
  HAL_MspInit();
  
  /* Return function status */
  return HAL_OK;
}

2.NVIC Interrupt Priority Settings

After grouping is set, how do I set the preemption and response priority for a single interrupt?

Interrupt Settings Related Registers:

_ IO uint8_t IP[240]; // Interrupt Priority Control Register Group

_ IO uint32_t ISER[8]; // Interrupt enable register group
_ IO uint32_t ICER[8]; // Interrupt Failure Register Group
_ IO uint32_t ISPR[8]; // Interrupt pending register group
_ IO uint32_t ICPR[8]; // Interrupt Unhang Register Group
_ IO uint32_t IABR[8]; // Interrupt Activation Flag Bit Register Group

At core_cm7.h: NVIC_ The member variables in the Type structure are those registers.

/**
  \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).
 */
typedef struct
{
  __IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */
        uint32_t RESERVED0[24U];
  __IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */
        uint32_t RSERVED1[24U];
  __IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */
        uint32_t RESERVED2[24U];
  __IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */
        uint32_t RESERVED3[24U];
  __IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */
        uint32_t RESERVED4[56U];
  __IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
        uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
}  NVIC_Type;

How do I set the priority for each interrupt?

Interrupt priority control register group: IP[240], full name: Interrupt Priority Registers

240 8-bit registers, one for each interrupt to determine priority. The STM32F40x series has 82 shieldable interrupts, using IP[81]~IP[0].

The top four bits per IP register are used to set preemption and response priorities (according to grouping), while the lower four bits are not used.

At stm32f7xx_hal_cortex.c can be found:

/**
  * @brief  Sets the priority of an interrupt.
  * @param  IRQn: External interrupt number.
  *         This parameter can be an enumerator of IRQn_Type enumeration
  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
  * @param  PreemptPriority: The preemption priority for the IRQn channel.
  *         This parameter can be a value between 0 and 15
  *         A lower priority value indicates a higher priority 
  * @param  SubPriority: the subpriority level for the IRQ channel.
  *         This parameter can be a value between 0 and 15
  *         A lower priority value indicates a higher priority.          
  * @retval None
  */
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{ 
  uint32_t prioritygroup = 0x00;
  
  /* Check the parameters */
  assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
  
  prioritygroup = NVIC_GetPriorityGrouping();
  
  NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
}

Interrupt priority setting steps:

  • HAL_after the system runs Interrupt priority grouping is set in the Init function. Call function:
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
    //Interrupt Priority Grouping 2 Interrupt grouping is set only once during system execution.
  • For each interrupt, set the corresponding preemption and response priorities:
    void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t
    PreemptPriority, uint32_t SubPriority);
  • Enables channel interruption:
    void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
{
  /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Enable interrupt */
  NVIC_EnableIRQ(IRQn);
}

 

Topics: stm32