STM32 Interrupt priority knowledge

The Cortex-M3 kernel supports 256 interrupts, which includes 16 kernel interrupts (exceptions) and 240 external interrupts, and has 256 levels of programmable interrupt Settings. However, STM32 does not use all of the CM3 kernel, but only part of it. The STM32 has 84 interrupts, including 16 kernel interrupts (exceptions) and 68 maskable interrupts, with 16 levels of programmable interrupt priority. In the STM32F103 series, 16 kernel interrupts (exceptions) remain the same, and only 60 are maskable interrupts (68 in the 107 series).

Note that CM3’s external interrupt is not the same as STM32’s external interrupt. CM3: External interrupts except kernel exceptions; STM32: External interrupt EXTI only has 6 (?)

Kernel interrupts are also called kernel exceptions. (?)

  • Interrupt refers to the system to stop the current running program to other services, may be the program received a higher priority than its own request, or is artificially set interrupt, interrupt is a normal phenomenon.
  • An exception is an error caused by a CPU fault, a program fault, or a service request fault.

An exception or interrupt is triggered, the program counter pointer (PC) will jump to the address of the exception or interrupt execution, the address is stored in this jump instruction, jump to the exception or interrupt service function to perform the corresponding function. Therefore, exception and interrupt tables can only be written in assembly language.

In MDK, there are standard exception and interrupt chart files available (startup_STM32F10X_hd.s), in which the name of the interrupt handler is specified and cannot be arbitrarily defined. The interrupt channel NVIC_IRQChannel (that is, type IRQn_Type) is macroscopically defined in the STM32F10X.h file.

What is an NVIC, or a Nested Vectored Interrupt Controller? CM3 has a powerful and convenient NVIC, which is part of the Cortex core and handles all 60 interrupts in the interrupt table.

The core functions of the NVIC are interrupt priority grouping, interrupt priority configuration, read interrupt request flag, clear interrupt request flag, enable interrupt, clear interrupt, etc. It controls 60 interrupts with interrupt numbers 0-59 in the STM32 interrupt list!! The external interrupt signal is emitted from outside the core, and the signal is eventually transmitted to the NVIC(nested vector interrupt Controller). The NVIC is tightly coupled to the core and controls the interrupt-related functions of the entire chip.

NVIC interrupt priority packet

STM32 divides interrupts into five groups, groups 0-4; Also, set one for each interruptPreemption priorityandResponse priority. The grouping configuration is defined by bit10-8 of the SCB->AIRCR register.From this table, you can clearly see the configuration relationship corresponding to groups 0-4. For example, if the group is set to 3, then for all 60 interrupts at this time, the highest 3 of the top 4 bits of the interrupt priority register of each interrupt is the preemption priority, and the lowest 1 bit is the response priority. For each interrupt, you can set the preemption priority to 07 07, the response priority is 1 or 0, a total of 16 levels.

The preemption priority is higher than the response priority, and a smaller value indicates a higher priority.

Preemption priority and response priority difference

  • A high priority preemption priority can interrupt an ongoing low priority preemption interrupt;
  • Interrupts with the same priority are preempted. Interrupts with lower response priority cannot be interrupted by higher response priority.
  • Preempt interrupts with the same priority. When two interrupts occur at the same time, whichever response has the highest priority is executed first.
  • If both interrupt preemption and response priorities are the same, whichever interrupt occurs first will be executed first.

Interruptions are only related to preemption priority, not response priority! In general, the interrupt priority group, such as group 2, is set only once during the system code execution. After the group is set, the group is generally not changed again. Changing the group arbitrarily can lead to disorganized interrupt management and unexpected execution results.

NVIC interrupt priority setting

Use the NVIC_Init() function to set the priority of each interrupt (in the misc.c file)

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
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); }}Copy the code

The NVIC_InitTypeDef structure is defined as follows:

typedef struct
{
  uint8_t NVIC_IRQChannel;
  uint8_t NVIC_IRQChannelPreemptionPriority;
  uint8_t NVIC_IRQChannelSubPriority;       
  FunctionalState NVIC_IRQChannelCmd;        
} NVIC_InitTypeDef;
Copy the code

The NVIC_InitTypeDef structure has four member variables:

  • NVIC_IRQChannel: defines which interrupt is initialized. This can be found in the stM32F10x.h file by the name of each interrupt, such as USART1_IRQn;
  • NVIC_IRQChannelPreemptionPriority: define the interruption of preemption priority;
  • NVIC_IRQChannelSubPriority: Defines the response priority for this interrupt;
  • NVIC_IRQChannelCmd: indicates whether the interrupt is enabled.

For example, if serial port 1 is interrupted, the preemption priority is 1, and the response priority is 2, the initialization method is as follows:

NVIC_InitTypeDef   NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;// Serial port 1 is interrupted
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// The preemption priority is 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// Subpriority bit 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;// Enable the IRQ channel
NVIC_Init(&NVIC_InitStructure);	// Initialize the NVIC register according to the parameters specified above
Copy the code

The problem

  1. Kernel interrupts and kernel exceptions are the same concept?
  2. What is an STM32 external interrupt and what is a CM3 external interrupt?
  3. Where is the interrupt response function set?
  4. Interrupt specific implementation?

The resources

  1. [STM32] NVIC Interrupt Priority Management (Interrupt direction Scale)
  2. Teach you to learn STM32 microcontroller teaching video