When learning about CM3, I carefully studied the interrupt jump process of CM3 and found that embedded MCUs are basically the same in this regard. Of course, MCUs with different architectures also have their own characteristics.
Let me introduce the interrupt jump process of CM3. First, assume that an interrupt occurs and the CM3 core begins to respond to the interrupt. Since CM3s from different manufacturers may be slightly different, but the CM3 core is definitely the same, we start the discussion under this premise and temporarily put aside things like interrupt mask bits and flag bits.
Now let's introduce the interrupt response process:
1. Pushing the stack. From this point of view, almost all processors are the same, using the stack to protect the scene. Which registers are pushed into, and in what order? For most C language programming, this is not a very important topic. However, the characteristics of the CM3 stack registers allow us to see the characteristics of ARM design. The stacking order is shown in the figure below. Please note that the address order and time order of stacking are not the same.
Address (SP) | register | Protected order (time order) |
N-0 | Previously pushed content | |
N-4 | xPSR | 2 |
N-8 | PC | 1 |
N-12 | LR | 8 |
N-16 | R12 | 7 |
N-20 | R3 | 6 |
N-24 | R2 | 5 |
N-28 | R1 | 4 |
N-32 | R0 | 3 |
This is very peculiar from the perspective of ordinary coding. There is no necessary connection between the stack space and the stack push time, which is very different from our "last in, first out" concept. Obviously, the "stack" here is not the stack in our traditional sense. ARM does not elaborate on how to implement it, but just says that they can do this.
We can see that PC, xPSR, R0, R1, R2, and R3 are pushed onto the stack first (in terms of time). The purpose of this is to allow the compiler to use the stacked registers first to save intermediate results (if the program is too large, R4-R11 may also be used, and the compiler is responsible for generating code to push them). This is also the reason why ISRs are required to be as short as possible, using fewer registers to speed up response.
2. Find the interrupt vector table. In fact, this step is parallel to the first step, but the serial numbers are listed just to introduce them separately. ARM has two buses, D-Code (data bus) and I-Code (instruction bus). You can see that PC is the first one to be pushed onto the stack. At this time, the data bus is busy with the stacking operation. At the same time, the instruction bus can find the interrupt vector table and query the entry address of the interrupt service program. In CM3, the interrupt vector table is located in a storage space starting at address 0x00000000, and each table entry occupies one word (4 bytes). This is the case when the interrupt vector table is not relocated. Of course, the interrupt vector table can also be relocated, that is, stored elsewhere. This requires setting the corresponding registers. I personally think it is better to keep it fixed at this default position to avoid unexpected situations. When looking at the interrupt vector table, I encountered a very interesting problem:
The entry address of the interrupt service function is 0x67C (as shown in Figure 1), but the address stored in the interrupt vector table is 0x67D (as shown in Figure 2), which is increased by 1.
This puzzled me for a long time, and then an expert in ARM7 answered my question. When the lowest bit of ARM's PC is 0, ARM will enter ARM mode, but when the lowest bit is 1, it will enter thumb mode. However, our CM only supports thumb mode, so the lowest bit of PC must be 1. Moreover, the thumb instruction set is 16 bits, so 0x67D points to the instruction stored in 0x67C, but subtracting one does not work, so it becomes the instruction stored in the previous address in the instruction space.
I have written down the CM3 interrupt jump process to share with you. If there is anything wrong, I hope you can correct me.
Figure 1 The box in Figure 1 is the corresponding interrupt service function entry point
Figure 2 The box shows the entry address of the interrupt service function in the interrupt vector table
*************************************************** *************************
I remember that in DSP TMS32F2812, the initialization of the interrupt vector is completed by a section of address copy code. In STM32 (Cortex-M3), there is no displayed code copy, only the startup code initializes the vector. I always thought that the compiler completed the copy of the relevant vector in the program image, that is, copied to the fixed NVIC area. In fact, this is not the case. Cortex-m3 does not have a place dedicated to storing the NVIC vector table. This table is actually stored at the beginning of the code (program image). The following is an explanation from the Cortex-M3 authoritative guide:
When an exception occurs and to respond to it, CM3 needs to locate the entry address of its service routine. These entry addresses are stored in the so-called "(exception) vector table". By default, CM3 assumes that the table is located at address zero and that each vector occupies 4 bytes. Therefore, each table entry occupies 4 bytes, as shown in Table 7.6.
Because the boot code should be stored at address 0, it is usually mapped to Flash or ROM devices, and their values must not be changed at runtime. However, in order to support dynamic redistribution of interrupts, CM3 allows the vector table to be relocated-locating each exception vector from other addresses. The area corresponding to these addresses can be the code area, but more often in the RAM area. The entry address of the vector can be modified in the RAM area. In order to achieve this function, there is a register in the NVIC called the "vector table offset register" (at address 0xE000_ED08), and the vector table can be relocated by modifying its value. But it must be noted that there are requirements for the starting address of the vector table: you must first find out how many vectors there are in the system, and then "round" this number up to an integer power of 2, and the starting address must be aligned to the latter's boundary. For example, if there are 32 interrupts, there are 32+16 (system exceptions) = 48 vectors, which is rounded up to the power of 2 to 64. Therefore, the address of the vector table relocation must be divisible by 64*4=256, so the legal starting address can be: 0x0, 0x100, 0x200, etc. The definition of the vector table offset register is shown in Table 7.7.
If the vector table needs to be changed dynamically, the beginning of the vector table must contain the following vectors for any device:
The initial value of the main stack pointer (MSP)
Reset vector
NMI
Hard fault service routine
The latter two are also necessary because it is possible for both of these exceptions to occur during the boot process.
A space can be opened in SRAM to store the vector table. Each vector is filled in during the boot process, and then after the boot is completed, the new vector table in memory can be enabled, thus realizing the ability of the vector to be dynamically adjusted.
Previous article:The difference and understanding of STM32's "exception", "interrupt" and "event"
Next article:STM32 interrupt priority setting
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Low power mode of msp430f149
- GaN Reference Designs
- How to get started with embedded development?
- [Perf-V Review] Transplanting the Hummingbird E203 open source SOC to the FPGA board
- How to control a switch with stm32
- Design USB3.1 high-speed SD Card reader based on Genesys GL3224
- If you want to make the three-pole tube work in the amplification area, what is the idea? You need to calculate the static working point ib ic VCE three...
- How to save the bricks with the RVB2601 board
- 77Ghz single-chip millimeter wave sensor enables automatic parking
- What is the function of this circuit in ESP32_Audio_kit?