This article has participated in the Denver Nuggets Creators Camp 3 “More Productive writing” track, see details: Digg project | creators Camp 3 ongoing, “write” personal impact.

preface

In keeping with personal habits, this article will start with “What is this? “Why do we need it?” “How?” Discuss and analyze from three perspectives.

directory

  • Introduction of interruption
  • Interrupt to understand
  • Interrupt Settings in STM32
    • NVIC
    • Stm32 Interrupts the configuration
  • conclusion

Introduction of interruption

Interrupt, that is, some unexpected situations occur in the process of machine operation, and the machine needs to stop the running program and turn into the program to deal with the new situation, and then return to the original suspended program to continue running.

Understand the interrupt

Imagine this scenario:

You are typing code in earnest, your mother asks you to leave the room to eat in the living room, and threatens to unplug the Internet if you don’t. What can you do at this point? Can only obediently save a good document, and then go to just rice, just come back to open the previous document to continue to knock.

Let’s analyze the above scenario:

  • Typing code – currently executing events
  • Your mother calls you to eat — interruption source
  • You hear your mom call you for dinner — accept the break request
  • Threat – High priority
  • Save what has been written — Save the scene (interrupt response)
  • Go to the meal – perform interrupt events
  • Just return to room – interrupt return
  • Open the file and continue to type – restore the scene

The same is true for machines. Either because of a kernel problem (exception) or because of some other event that has a higher priority than the currently executing program (external interrupt), the currently running program is interrupted to do something more important.

After all, no matter how fast a machine is, it has to process events first and foremost.

Now, let’s go back to that scenario and consider the following two scenarios:

1, when you are eating, you suddenly want to go to WC to solve personal problems. At this time you will stop this action, and then go to WC to solve the problem and then come back to eat. I won’t continue until after dinner

2, when you are having dinner, you receive a message from the Courier, telling you that the verification code can be picked up. You’ll finish your meal, pick up the package (or leave it there), and then go back to your room and type code.

For situation 1, in order to avoid some embarrassing things, it is almost inevitable to go to WC first and then come back for dinner. Because it’s more urgent than eating. In case 2, the delivery is not so urgent, so generally speaking, we will have dinner first, then go to get the delivery, and finally go back to the room to type the code.

Of course, if the code to knock more urgent, then take the express naturally have to wait until we knock the code first.

From the two common scenarios above, it is easy to see that interrupts can be nested and have a priority concept.

Obviously, there are a lot of interruptions in our daily lives. What do our brains do with them? If you think about it carefully, you will find that for many events, we have already defined their priorities. And it’s our brains that define and enforce the priorities of these events.

The same is true for cpus. When there are few interruption events, there is no need to sort them out, and you can directly compare and judge the priority.

However, for the complex system with many interrupt events, the grouping and priority setting of events becomes a necessity.

Here we take the interrupt system of STM32F10X as an example to study.

Interrupt Settings in STM32

As we know, STM32 uses the Cortex-M3 kernel.

The CM3 kernel supports 256 interrupts, 256 levels of programmable Settings (i.e., priority Settings), where:

  • 16 kernel interrupts
  • 240 peripherals interrupt

But STM32 does not use all of the CM3 kernel Settings. It has only 84 interrupts and 16 levels of programmable Settings, including:

  • 16 kernel interrupts
  • Interrupts 68 peripherals

And the above configuration belongs to the top configuration of STM32, specific to F103 series only:

  • 16 kernel interrupts
  • Interrupts 44 peripherals

In the summary of the above data, it can be found that the actual number of interrupt events depends on the chip location. High-end, that is, peripherals, chip interrupt is bound to be more, vice versa is bound to be less.

NVIC

The CM3 kernel provides a solution to handle so many Interrupt events with Nested Vectored Interrupt controllers (NVIC).

NVIC first defines an address area (typically starting at address 0) to hold the address of the interrupt event service function. The address defined is called the interrupt direction table.

The above is taken from the STM32F10X Chinese Reference Manual.

You can see that each address corresponds to an interrupt event, where the gray part is the location of the kernel-specific interrupt. Each time a command is executed, the system checks to see if an interrupt event has occurred. If so, the corresponding interrupt event is found in the interrupt direction table, and the function pointed to by the address of the interrupt event is executed (that is, the interrupt function).

That is, because the address of the interrupt event stores an address, it points to the event (function) corresponding to the interrupt. So the name of the interrupt vector table is actually what it means — it’s a list of directed values.

As for defining the priority of these interrupt events and what they do, NVIC leaves it up to the developer to set them up. It only gives the set of registers that can do this.

From the firmware library header file core_cm3.h, we can find the register group mapping for the above NVIC.

If we use register programming, the most concerned register is generally:

  • ISER: Interrupt Set Enable Register
  • ICER: Interrupt Clear Enable Register Specifies whether to Clear a Register
  • IP: Interrupt Priority Register

In this, the interrupt priority register is what we need to focus on. Interestingly, the abbreviation for this register is simply IP instead of IPR when naming the firmware library, making me wonder if the two are the same thing. It was not until I consulted the manual that I was able to verify my identity.

IPR interrupt priority register

In the original CM3 design, NVIC_IPRx was used to configure the priority of external interrupts. The IPR width is 8 bits. Theoretically, the priority ranges from 0 to 255. A smaller value indicates a higher priority. But like most CM3 chips, the STM32 has a relatively lean design, using only high 4bits. That is, stM32 actually allows you to configure only 16 priorities

Preemption priority and subpriority

CM3 divides priorities into preemption priorities and sub-priorities (also known as response priorities). That is, for the same interrupt event, it has preemption priority and subpriority.

Why are we doing this?

Because if it’s just a simple one priority, it’s too broad. For example, CM3 kernel setup has 256 levels at most, and even STM32 has 16 levels. There are too many levels, and it is not convenient to use and manage without primary and secondary.

Compare it to the state in our daily life, as if there are 256 people in the society, each of whom is of different rank, and you will probably be dazzled. The solution to this problem is to classify the 256-level interrupts into hierarchies, and then manage them at the molecular level to achieve the effect of reducing the hierarchies. Such as first divided into ruling class, slave owners, slaves, etc., the same class and then divided into minor ranks.

Corresponding to interrupt grouping is to set 256 priorities according to the needs of the project, first specify the number of mid-fault (i.e., preemption priority) and the number of small levels in each layer.

It is understandable that the concept of preemption of priorities and subpriorities is introduced.

Preemption priority and subpriority comparison

Subpriorities come into play only if the preemption priorities are the same. If the sub-priority is the same, the hardware interrupt number of the two peripherals is compared, that is, the position of the interrupt in the interrupt direction table. Similarly, the smaller the number is, the higher the priority is.

Note that preemption is slightly different from subpriority:

  • Preemption priority: Compares the priority of interrupts regardless of the sequence of interrupts. Even if an interrupt signal with a higher priority is arrived after an interrupt signal with a lower priority, the event with a lower priority can be directly interrupted to preempt system resources.
  • Subpriority: When two interrupt signals have the same preemption priority, they can be considered in two cases:
    • When two signals arrive at the same time, the interrupt with higher subpriority responds first.
    • An interrupt event with a lower subpriority is occurring. As soon as the interrupt signal with a higher subpriority arrives, the interrupt signal must be executed after the current interrupt completes.

Interrupt group

As you can see from the previous discussion, the CM3 kernel uses two priority hierarchies to make interrupts more manageable.

But for different needs, we also have different requirements for the number of classes and small classes. Take the id card as an example. Before issuing the ID card, we should consider how many regions the country should be divided into in general, and then determine how many digits the regions need to be set. Familiar with computer network friends can be found, here and subnet division is actually a truth.

Here, we can also see that, in a project, we usually only set once, and only set one group at a time. Or take id card for example, you can not say one second before the first 3 id card indicates A province, the next second to say the first 4 B province? Coding uniformity is the foundation of everything.

So, we usually set up groups, if not very special needs

Only set groups once per project!!

Only set groups once per project!!

Only set groups once per project!!

It’s so important that it should be repeated for three times.

This pace-managed setting is controlled by prigroup[10:8] of the kernel peripheral SCB_AIRCR (Application interrupt and Reset control register).

Because it is controlled by three bits, it can theoretically be divided into eight groups (groups 0 to 7), each of which has a different number of preemption priorities and subpriorities.

As shown in the figure above, it can be seen that as the group number increases, the fewer bits the preemption priority can be set, the more subpriorities it has.

This grouping is designed for the case where all 8bits are used in IPR. As we know, THE NVIC of STM32 is a subset of the NVIC of CM3, and only uses the higher 4bits of IPR, so the grouping is naturally less.

With the above rational cognition, we finally entered the relaxed and happy programming configuration link ~~~

Configuration points

Based on the foregoing, with some additional resources (such as various official documents), we can conclude the following configuration process:

  • Enable an interrupt
  • Interrupt group
  • Initialize the NVIC_InitTypeDef structure
    • Setting an Interrupt Source
    • Set preemption priority and subpriority
    • Configuration interrupt Enable/disable
  • Write an interrupt service function (which tells the machine what to do when the interrupt occurs)

The NVIC_InitTypeDef structure mentioned in the flow above is this dude:

It differs from the NVIC_Type structure in that NVIC_Type is just a mapping of register groups, whereas the NVIC_InitTypeDef is abstracting from the firmware library to help simplify the configuration process.

Let’s take a look at the above process with an example.

EXTI

External Interrupt/Event Controller (EXTI) : An External interrupt/event controller that manages 20 interrupt/event lines of the controller (20 for interconnection and 19 for other types).

Relationship between NVIC and EXTI

Let’s first clarify the relationship between this thing and NVIC:

  1. NVIC is the CM3 kernel stuff, which is used for interrupt control across the chip. The EXTI is designed by ST to control peripherals. It’s not something that’s inside the kernel.
  2. EXTI leads out 20 interrupt signal lines in NVIC through magic modification, which further strengthens the control ability of external events.

Here, let’s first clarify three concepts:

  • The event
  • interrupt
  • Interrupt event

For example, a teacher is teaching students in a classroom. In class, students may do all kinds of behaviors, such as taking notes, breathing, turning the bag, talking small words, etc., we call these behaviors as incidents, some of which the teacher often just ignore and continue his class; However, some behaviors may cause the teacher to suspend class, such as small words, and give warning, criticism or correction to the student’s related behavior, and then continue the class. We understand the interruption or interrupt response in which the teacher discontinues the lesson because of some behavior of the student, resulting in a subsequent action and then continuing the lesson. We understand student behavior that may cause a teacher to interrupt class as a disruption event.

EXTI block diagram understanding

Below, we understand the above concepts in combination with the block diagram of EXTI.

First of all, we have a general understanding of the whole block diagram:

  • Green + red: Connected to peripherals. The green part is used to communicate with the blue part, and the red part is used to transmit event signals.
  • Blue part: register group, used to control the acquisition and direction of event signal.
  • Yellow: Two outputs. For event signal output, interrupt signal to NVIC, non-interrupt signal for other peripherals (such as :DMA, DMA related content, more details in a future article).

EXTI can be divided into two main functions, one is to generate interrupts, the other is to generate events, the two functions are different from the hardware.

Signal generation process

Now let’s analyze how these two things happen.

As shown in the figure above, the signal will first pass through the edge detection circuit, which detection circuit will determine which edge the signal is collected on by looking at the value of the upper edge trigger register and the lower edge trigger register. (The so-called upper edge and lower edge, i.e. the vertical edge when the level changes from low -> high or from high -> low)

After passing through the edge detection circuit, it comes to the position of 3 in the figure above. Here an or gate connects the input signal to the software interrupt event register. That is, in addition to the signal triggering the interrupt, we can also control the relevant registers to generate the interrupt event.

After step 3 or gate, there is a difference between a process that generates an interrupt and an event.

Let’s take a look at how interrupts are generated:

The interrupt request signal enters the request suspend register first. The purpose of this register is that if the interrupt occurs while the peer or higher priority interrupts are being processed, the interrupt cannot be responded to immediately and the interrupt is suspended. Suspension means to wait rather than abandon, and the suspended interrupt will not be executed until the higher-priority or first-timer interrupts are complete.

It can be seen from stM32 that position 4 is an and gate, so ask when the interrupt is pushed to the NVIC controller for execution, which is what the interrupt masking register should control.

Similarly, the event masking register is a matter of whether the event is generated or not. The difference is that there is no notion of priority, so there is no such thing as a suspended register.

Code sample


To be continued

The resources

STM32 interrupt priority grouping for beginners

STM32 “external interrupt” and “event” distinction and understanding

Brief discussion on the difference between interrupt hanging and interrupt sign