[STM32] Interrupt and NVIC take external interrupt as an example

Preface

In stm32, it can be considered that exceptions are interrupts.

After the microcontroller is powered on, it first executes the startup file, opens the stack, and then begins to initialize the interrupt vector table.

NVIC

NVIC

NVIC is a nested vector interrupt controller, which controls the interrupt-related functions of the entire chip. It is tightly coupled with the core and is 内核a peripheral inside.

####Three registers ISER, ICERand NVIC structure definitions IP
come from the firmware library header file: core_cm3.h.
When configuring interrupts, we generally only use ISERthese three registers, ISER and ICER to enable interrupts. Can interrupt, IP is used to set interrupt priority. : Interrupt Set Enable Registers, this is an interrupt enable register set. It is an array of u32 type with 8 members. The CM3 and 4 cores support 256 interrupts, which are controlled by eight 32-bit registers, with each bit controlling an interrupt. Depending on the design of the microcontroller manufacturer, not all of them may be used. : The full name is: Interrupt Clear Enable Registers, which is an interrupt disable register group. The function of this register group is exactly opposite to that of ISER, which is used to clear the enable of an interrupt. The function of its corresponding bit is also the same as ISER. Here we need to set up an ICER specifically to clear the interrupt bit, instead of writing 0 to ISER to clear it, because these registers of the NVIC are valid when writing 1, and invalid when writing 0. : The full name is: Interrupt Priority Registers, which is a register group for interrupt priority control. This register set is quite important! The interrupt grouping of STM32F407 is closely related to this register group. The IP register group consists of 240 8-bit registers, and each maskable interrupt occupies 8 bits, so that a total of 240 maskable interrupts can be represented. The STM32F407 only uses 82 of them. IP[81]-IP[0] correspond to interrupts 81~0 respectively. The 8 bits occupied by each maskable interrupt are notICERIP
NVIC structure definition, from firmware library header file: core_cm3.h
ISER[8]
ICER[8]
IP [240]
All are used, but only the upper 4 bits are used. These 4 bits are divided into preemption priority and sub-priority. The preemption priority is first, and the sub-priority is last. The number of bits each of these two priorities occupies depends on the interrupt group settings in SCB->AIRCR.

//----------The above are commonly used NVIC registers. The configuration of NVIC is actually to configure these registers----------//

ISPR[8]: The full name is: Interrupt Set Pending Registers, which is an interrupt enable pending control register group. The interrupt corresponding to each bit is the same as ISER. By setting it to 1, an ongoing interrupt can be suspended and an interrupt of the same or higher level can be executed. Writing 0 has no effect.
ICPR[8]: The full name is: Interrupt Clear Pending Registers, which is an interrupt detachment control register group. Its function is opposite to ISPR, and the corresponding bits are the same as ISER. By setting 1, the pending interrupt can be unhung. Writing 0 has no effect.
IABR[8]: The full name is: Interrupt Active Bit Registers, which is an interrupt activation flag register group. The interrupt represented by the corresponding bit is the same as ISER. If it is 1, it means that the interrupt corresponding to the bit is being executed. This is a read-only register through which you can know which interrupt is currently executing. After the interrupt execution is completed, it is automatically cleared by the hardware.

Definition of priority

1. The priorities are only main priority and sub-priority.
2. The so-called priority grouping determines the high 4 bits of the IP register, which bits represent the main priority and which bits represent the sub-priority.
3. The smaller the value, the higher the priority. The higher the priority
4. Preemption priority: An interrupt with a high preemption priority can interrupt an interrupt with a low preemption priority that is being executed.
5. Response priority: The preemption priority is the same, and the interrupt with high response priority cannot interrupt the interrupt with low response priority.

Another situation is when the preemptive priority and response priority of two or more interrupts are the same, then the
natural priority is followed. Look at the interrupt sorting of the interrupt vector table. The smaller the value, the higher the priority.
先比较主优先级,再比较sub优先级,再按中断向量表的优先级序号比较
Insert image description here
The interrupt priority register NVIC_IPRx is used to configure the priority of external interrupts. The IPR width is 8 bits. In principle, the configurable priority of each external interrupt is 0~255 数值越小,优先级越高. However, most CM3 chips will streamline their design, so that the number of priority levels they actually support is reduced. In F103, only the upper 4 bits are used. The upper 4 bits will also determine how many main priorities and how many sub-priorities occupy according to the configuration of bits 10~8 of the CB->AIRCR register.
Insert image description here
The priority grouping is determined by the PRIGROUP[10:8] bits of the application interrupt and reset control register AIRCR of the core peripheral SCB. That is to say, the 4 bits used to express the priority need to be configured according to the priority grouping. Configuration of main priority and sub-priority.

The setting of priority grouping is defined by bit10~8 of SCB->AIRCR register.Insert image description hereInsert image description here

For example_set priority

Set priority: After setting the priority group, set the main priority and sub-priority
1. Set the priority group
2. Set the main priority
3. Set the sub priority

For example, bit10~8 of the SCB->AIRCR register sets the priority grouping to 3. Then for all 82 interrupts at this time, the highest 3 bits of the high four bits of the interrupt priority register of each interrupt are the preemption priority, and the lower 1 bit is the response priority. For each interrupt, you can set the preemption priority to 0~7 and the response priority to 1 or 0. Preemption priority is higher than response priority. The smaller the value, the higher the priority.

For example_ interrupt interrupt

Preemptive priority : An interrupt with a high preemptive priority can interrupt an ongoing interrupt with a low preemptive priority.
Response priority : The preemption priority is the same, and interrupts with high response priorities cannot interrupt interrupts with low priority responses.

Assume that the interrupt priority grouping is set to 2, and then the preemption priority of interrupt 3 (RTC_WKUP interrupt) is set to 2, and the response priority is 1. The preemptive priority of interrupt 6 (external interrupt 0) is 3, and the response priority is 0. The preemptive priority of interrupt 7 (external interrupt 1) is 2, and the response priority is 0. Then the priority order of these three interrupts is:
interrupt 7>interrupt 3>interrupt 6.
Both interrupt 3 and interrupt 7 in the above example can interrupt the interrupt of interrupt 6. However, interrupt 7 and interrupt 3 cannot interrupt each other!

NVIC interrupt-related library functions are in the library files misc.c and misc.h

Essentials of interrupt programming

In general, do not use library function encapsulated functions

There are three main steps in programming

1. Enable interrupts

Enable a certain interrupt of the peripheral, such as the USART transmission completion interrupt, acceptance completion interrupt, etc. These are controlled by the control register of the relevant peripheral device, and the control register is configured to enable it.这边是允许外设的具体某个中断,还需要在NVIC操作 NVIC_ISER 和 NVIC_ICER 这两个寄存器,进行中断的使能

2. Configure NVIC

Initialize NVIC_InitTypeDef structure
Insert image description here
2.1 Set interrupt source

Insert image description here
Insert image description here
2.2 Set the main priority and sub priority

2.3 Interrupt enable (ENABLE) or disable (DISABLE), the two registers NVIC_ISER and NVIC_ICER are operated.

3. Write interrupt service function

The interrupt service function is pre-defined in the startup file startup_stm32f10x_hd.s and can be written in it.

NVIC related functions

NVIC interrupt-related library functions are in the library files misc.c and misc.h (stm32f1 series). The
NVIC-related functions of the core_cm4.h file are encapsulated into the stm32f4xx_hal_cortex.c file (stm32f4 series)

Take the external interrupt EXTI as an example

The code almost means this. It needs to be modified when using it.
The process of configuring the GPIO PA0 pin as an external interrupt.

1) Enable the IO port clock.

The clock of the GPIO port must be turned on before using GPIO; the AFIO clock must be turned on when using EXTI.

GPIO_InitTypeDef GPIO_InitStructure;//
EXTI_InitTypeDef EXTI_InitStructure;//

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//打开GPIO的时钟,打开AFIO的时钟,

2) Configure interrupt priority (NVIC)

NVIC_InitTypeDef NVIC_InitStructure;
/* 配置 NVIC 为优先级组 1  所有82个中断源都属于优先级组1,主优先级0-1,子优先级0-7*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

/* 配置中断源:exti1 */
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;

/* 配置抢占优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

/* 配置子优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

3) Set the IO port mode, trigger conditions, set the mapping relationship between the IO port and the interrupt line, and enable interrupts.

# 设定GPIO模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;#浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);

#设定EXTI触发条件
/* 选择 EXTI 的信号源 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

EXTI_InitStructure.EXTI_Line = EXTI_Line0;
/* EXTI 为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 上升沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

4) Write the interrupt service function.

void EXTI0_IRQHandler(void){
    
    

	//确保是否产生了 EXTI Line 中断
	if (EXTI_GetITStatus(EXTI_Line0) != RESET){
    
    
	//Todo
	EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

Guess you like

Origin blog.csdn.net/apythonlearner/article/details/131561791