ARM Cortex-M3 interrupt jump process

Publisher:彩虹微笑Latest update time:2018-12-03 Source: eefocusKeywords:ARM  Cortex-M3 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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.


Keywords:ARM  Cortex-M3 Reference address:ARM Cortex-M3 interrupt jump process

Previous article:The difference and understanding of STM32's "exception", "interrupt" and "event"
Next article:STM32 interrupt priority setting

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号