STM32 interrupt vector nesting NVIC understanding

Publisher:自由探索Latest update time:2015-10-21 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1. Interrupt priority:

The concept of priority in STM32 (Cortex-M3)
There are two concepts of priority in STM32 (Cortex-M3) - preemptive priority and response priority. Some people call response priority 'sub-priority' or 'sub-priority'. Each interrupt source needs to be assigned these two priorities.

An interrupt with a high preemptive priority can be responded to during the interrupt processing with a low preemptive priority, that is, interrupt nesting, or an interrupt with a high preemptive priority can nest an interrupt with a low preemptive priority.

When the preemptive priority of two interrupt sources is the same, there will be no nesting relationship between the two interrupts. When one interrupt arrives, if another interrupt is being processed, the later interrupt will have to wait until the previous interrupt is processed. If the two interrupts arrive at the same time, the interrupt controller decides which one to process first based on their response priority; if their preemptive priority and response priority are equal, the order of their ranking in the interrupt table determines which one to process first.

Since each interrupt source needs to be assigned these two priorities, there needs to be a corresponding register bit to record the priority of each interrupt; in Cortex-M3, 8 bits are defined to set the priority of the interrupt source. These 8 bits can be allocated in 8 ways, as follows:

All 8 bits are used to specify the response priority
The highest 1 bit is used to specify the preemptive priority, and the lowest 7 bits are used to specify the response priority
The highest 2 bits are used to specify the preemptive priority, and the lowest 6 bits are used to specify the response priority
The highest 3 bits are used to specify the preemptive priority, and the lowest 5 bits are used to specify the response priority
The highest 4 bits are used to specify the preemptive priority, and the lowest 4 bits are used to specify the response priority
The highest 5 bits are used to specify the preemptive priority, and the lowest 3 bits are used to specify the response priority
The highest 6 bits are used to specify the preemptive priority, and the lowest 2 bits are used to specify the response priority
The highest 7 bits are used to specify the preemptive priority, and the lowest 1 bit is used to specify the response priority

This is the concept of priority grouping.

--------------------------------------------------------------------------------
Cortex-M3 allows fewer interrupt sources to use fewer register bits to specify the priority of the interrupt source, so the STM32 reduces the register bits for specifying interrupt priority to 4 bits. These 4 register bits are grouped as follows:

Group 0: All 4 bits are used to specify the response priority
Group 1: The highest 1 bit is used to specify the preemptive priority, and the lowest 3 bits are used to specify the response priority
Group 2: The highest 2 bits are used to specify the preemptive priority, and the lowest 2 bits are used to specify the response priority
Group 3: The highest 3 bits are used to specify the preemptive priority, and the lowest 1 bit is used to specify the response priority
Group 4: All 4 bits are used to specify the preemptive priority

You can choose which priority grouping method to use by calling the function NVIC_PriorityGroupConfig() in the STM32 firmware library. This function has the following five parameters:

NVIC_PriorityGroup_0 => Select Group 0
NVIC_PriorityGroup_1 => Select Group 1
NVIC_PriorityGroup_2 => Select Group 2
NVIC_PriorityGroup_3 => Select Group 3
NVIC_PriorityGroup_4 => Select Group 4

The next step is to specify the priority of the interrupt source. The following is a simple example to illustrate how to specify the preemptive priority and response priority of the interrupt source:

// Select to use priority group 1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
 Interrupt settings: Enable interrupt->Priority grouping method (each corresponding interrupt has)->Set preemptive priority->Set response priority->Call NVIC_Init(&xx)
// Enable EXTI0 interrupt
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPrio rity = 1; // Specify preemptive priority 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // Specify response priority level 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
 
// Enable EXTI9_5 interrupt
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPrio rity = 0; // Specify preemptive priority level 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // Specify response priority level 1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

A few points to note are:

1) If the specified preemptive priority or response priority exceeds the range defined by the selected priority group, unexpected results may occur;

2) There is no nesting relationship between interrupt sources with the same preemptive priority level;

3) If an interrupt source is assigned a preemptive priority level and there is no other interrupt source at the same preemptive priority level, any valid response priority level can be assigned to this interrupt source.

Second, the switch is always interrupted:

In STM32/Cortex-M3, interrupts are enabled or disabled by changing the current CPU priority.
PRIMASK bit: Only NMI and hard fault exceptions are allowed, and all other interrupts/exceptions are masked (current CPU priority = 0).
FAULTMASK bit: Only NMI is allowed, and all other interrupts/exceptions are masked (current CPU priority = -1).

In the STM32 firmware library (stm32f10x_nvic.c and stm32f10x_nvic.h), four functions are defined to operate the PRIMASK bit and the FAULTMASK bit to change the current priority level of the CPU, thereby achieving the purpose of controlling all interrupts.

The following two functions are equivalent to turning off the general interrupt:
void NVIC_SETPRIMASK(void);
void NVIC_SETFAULTMASK(void);

The following two functions are equivalent to opening the global interrupt:
void NVIC_RESETPRIMASK(void);
void NVIC_RESETFAULTMASK(void);

The above two groups of functions should be used in pairs and cannot be used interchangeably.

For example:

The first method:
NVIC_SETPRIMASK();   //Disable the general interrupt
NVIC_RESETPRIMASK(); //Enable the general interrupt

The second method:
NVIC_SETFAULTMASK();   //Disable the general interrupt
NVIC_RESETFAULTMASK(); //Enable the general interrupt

Frequently used

NVIC_SETPRIMASK();                    // Disable Interrupts
NVIC_RESETPRIMASK();                  // Enable Interrupts

 STM32 interrupt process processing

As a habit of mine, when learning something about a certain platform, I always have to understand the interrupt processing flow first, of course, from the file code level process analysis.
 
Let's talk about the interrupt process of stm32. We know that there are many drivers written in the stm32 library, which can be said to include all. At the same time, many data processing methods are also provided, such as serial port reading and writing, and users can choose polling, interruption, DMA and other 3 methods to process.
 
Regarding interrupts, the stm32 library has a good framework, and users only need to fill in the implementation of several functions. As the Internet says, this is fool-proof development.
 
To understand interrupts, you must first know the file stm32f10x_it.c, which is generally in the same directory as the main file. Open this file, we can see the implementation of the xyz_IRQHandler function. Although it is an implementation, it is almost empty. By the way, these functions are interrupt processing functions that users need to fill in. If you use which interrupt to do the corresponding processing, you have to fill in the corresponding interrupt processing function. You need to fill it out according to the actual situation of each peripheral, but generally there will be interrupts turned off and on. There are many system-related interrupt handling functions in this file, such as the system clock SysTickHandler. For specific implementations, please refer to the examples under stm32fwlibFWLibexamples.
 
So far, we have only seen the interrupt handling functions, but how are these handling functions called by hardware interrupts? Well, here we have to mention the file stm32f10x_vector.c. The content is as follows:
typedef void( *intfunc )( void );
typedef union { intfunc __fun; void * __ptr; } intvec_elem;
 

 
// Some extensions made by IAR to the used language (here is C), that is, the extended functions can be used here
#pragma language=extended #pragma segment="CSTACK"
 
void __iar_program_start( void );
 

#pragma location = ".intvec"
 

const intvec_elem __vector_table[] =
{
 { .__ptr = __sfe( "CSTACK" ) },
 &__iar_program_start,
 NMIException,
 HardFaultException,
 MemManageException,
 BusFaultException,
 UsageFaultException,
 0, 0, 0, 0,            
 vPortSVCHandler,
 DebugMonitor,
 0,                      
 xPortPendSVHandler,
 xPortSysTickHandler,
 WWDG_IRQHandler,
 PVD_IRQHandler,
 TAMPER_IRQHandler,
 RTC_IRQHandler,
 FLASH_IRQHandler,
 RCC_IRQHandler,
 EXTI0_IRQHandler,
 EXTI1_IRQHandler,
 EXTI2_IRQHandler ,
 EXTI3_IRQHandler,
 EXTI4_IRQHandler,
 DMAChannel1_IRQHandler, DMAChannel2_IRQHandler, DMAChannel3_IRQHandler, DMAChannel3_IRQHandler nel4_IRQHandler, DMAChannel5_IRQHandler, DMAChannel6_IRQHandler ,
 DMAChannel7_IRQHandler , ADC_IRQHandler , USB_HP_CAN_TX_IRQHandler , USB_LP_CAN_RX0_IRQHandler, CAN_RX1_IRQHandler, CAN_SCE_IRQHandler, EXTI9_5_IRQHandler, TIM1_BRK_IRQHandler, TIM1_UP_IRQHandler, TIM1_TRG_COM_IRQHandler, TIM1_CC_IRQHandler, vTimer2IntHandler, TIM3_IRQHandler, TIM4_IRQHandler, I2C1_EV_IRQHandler, I2C1_ER_IRQHandler, I2C2_EV_IRQHandler , I 2C2_ER_IRQHandler, SPI1_IRQHandler, SPI2_IRQHandler, vUARTInterruptHandler, USART2_IRQHandler, USART3_IRQHandler, EXTI15_10_IRQHandler, RTCAlarm_IRQHandler, USBWakeUp_IRQHandler, }; Now we know that this is the interrupt vector table. Each item corresponds to an interrupt or exception handler. The items here should be filled in the same order as in the list in the Interrupt and exception vectors section of stm32spec.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
At this point, there is another question, where is this vector table placed? From the above explanation of .intvec, we can see that it is placed at an address by the linker (here is 0x08000000, NVIC_VectTab_FLASH). But how does stm32 know this address? Maybe there is a default value, or is it just a fixed value? ). We found the following function in the stm32f10x_nvic.c file:
void NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
{
 
 assert(IS_NVIC_VECTTAB(NVIC_VectTab));
 assert(IS_NVIC_OFFSET(Offset)); 
  
 SCB->ExceptionTableOffset = (((u32)Offset << 0x07) & (u32)0x1FFFFFF80);
 SCB->ExceptionTableOffset |= NVIC_VectTab;
}
At the same time, there is an example of vectortable_relocation in the example directory: This example describes how to use the NVIC firmware library to set the CortexM3 vector table in a specific address other than default.
In this example, the above function is called directly, and it seems that the meaning is obvious. But how does SCB->ExceptionTableOffset work?
 
To explain this problem in detail, let's first look at a set of definitions: [stm32f10x_map.b]

#define SCS_BASE              ((u32)0xE000E000)
#define SysTick_BASE  (         SCS_BASE + 0x0010)
#define NVIC_BASE  (SCS_BASE + 0x0100) #define SCB_BASE  (SCS_BASE + 0x0D00) #ifdef _SCB #define SCB  ((SCB_TypeDef *) SCB_BASE) #endif typedef struct { vu32 CPUID; vu32 IRQControlState; vu32 ExceptionTableOffset; vu32 AIRC; vu32 SysCtrl; vu32 ConfigCtrl; vu32 SystemPriority[3]; vu32 SysHandlerCtrl; vu32 ConfigFaultStatus; vu32 HardFaultStatus; vu32 DebugFaultStatus; vu32 MemoryManageFaultAddr; vu32 BusFaultAddr; } SCB_TypeDef; Actually, the main thing here is to figure out what this SCB means, because this structure is mapped to a physical address. Like other control registers, this is the same way. Could it be that this is also some kind of controller? After a google search, I found that the system control register group [mentioned in the previous article] is defined in the STM32 firmware library as follows: typedef struct { vuc32 CPUID; vu32 ICSR; vu32 VTOR; vu32 AIRCR; vu32 SCR ; vu32 CCR; vu32 SHPR[3]; vu32 SHCSR; vu32 CFSR; vu32 HFSR; vu32 DFSR; vu32 MMFAR; vu32 BFAR ; vu32 AFSR; } SCB_TypeDef; Their corresponding names in the ARM manual are CPUID = CPUID Base Register ICSR = Interrupt Control State Register VTOR = Vector Table Offset Register AIRCR = Application Interrupt/Reset Control Register SCR = System Control Register CCR = Configuration Control Register SHPR = System Handlers Priority Register SHCSR = System Handler Control and State Register CFSR = Configurable Fault Status Registers HFSR = Hard Fault Status Register DFSR = Debug Fault Status Register MMFAR = Mem Manage Address Register BFAR = Bus Fault Address Register AFSR = Auxiliary Fault Status Register           
            

                 



 
 
 
 
 
 
 
 
 
 
 
 
 

 



 
 
 
 
 
 
 
 
 
 
 
 
 
 
















 
At this point, we finally know that the address of this interrupt vector table will eventually be written to a controller. So, the above 0x08000000 can be a different value, as long as it is ensured that this address cannot be accessed by other programs.


Keywords:STM32 Reference address:STM32 interrupt vector nesting NVIC understanding

Previous article:About stm32 microcontroller, using id encryption, plain code security analysis
Next article:Create an STM32 project based on the V3.4.0 firmware library in Keil4

Recommended ReadingLatest update time:2024-11-16 17:44

STM32 --UART serial communication
UART serial port timing For UART serial port protocol, please refer to the following article:  http://blog.csdn.net/gogomusic/article/details/54767502 UART serial port configuration 1) Serial port clock enable. As a peripheral of STM32, the serial port clock is controlled by the peripheral clock enable regist
[Microcontroller]
STM32 --UART serial communication
STM32 output PWM status summary
Output polarity: Based on positive logic, that is, high level is 1 and low level is 0 1. Output polarity high (Polarity_High): High level 1 is valid (active), low level 0 is invalid (inactive) 2. Output polarity low (Polarity_Low): Low level 0 is valid (active), high level 1 is invalid (inactive) PWM Mode: Divi
[Microcontroller]
The most convenient timer Systick on stm32 [operation register + library function]
Systick is a very useful internal device on stm32. All arm-cortex m3 based chips have this timer, so when considering the portability of the platform, you can use Systick more.   Systick is a 24-bit data width countdown timer, whose counting range can only reach 1677215 (2^24). When the count reaches 0, it will automa
[Microcontroller]
stm32 interrupt function name table
The names of stm32 interrupt service functions are a bit special. Their names are fixed. But on the surface, there seems to be no pattern. Still use the old method, write it down and memorize it.   WWDG_IRQHandler   PVD_IRQHandler   TAMPER_IRQHandler   RTC_IRQHandler   FLASH_IRQHandler   R
[Microcontroller]
The role of stm32f10x.h in stm32
1. Define the order of various interrupt vector tables according to the type of stm32 (mainly the size of the flash); 2. Define data types 3. Define the structure related to MCU peripherals: 4. Define the address of the peripheral in FLASH: 5. Define the bits of peripheral registers
[Microcontroller]
The role of stm32f10x.h in stm32
STM32 boot pin setting
Boot mode selection           Bootmode   pins                                 Aliasing BOOT1 BOOT0    x               0                    Main Flash memory               Main Flash memory is selected as boot space    0               1                    System memory                      System memory is selected as
[Microcontroller]
STM32 clock configuration, the program required to configure different crystal oscillators
In the header file "stm32f10x.h":  #define HSE_Value ((uint32_t)8000000) /! Value of the External oscillator in Hz/  The italic content defaults to 8000000. When you modify the external crystal oscillator, it must be the same as your external crystal oscillator value. For example, my external crystal oscillator is 24M
[Microcontroller]
STM32 USB Design-MCU Program
First, let's take a look at the working process of USB. When a USB device is connected to the host, the host begins to enumerate the USB device and sends a command to the USB device to obtain the relevant description information of the USB device, including device description (device descriptor), configuration
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号