Analyzing the interrupt behavior of gd32vf103 from the underlying principle of RISC-V[Copy link]
1. Overview
2. Interrupt vector table initialization
3. Detailed analysis of irq_entry
4. Understanding of the gd32vf103 interrupt programming model
1. Overview
When dealing with RISCv processor interrupts, two concepts need to be clarified:
1. Vector interrupt
2. Non-vectored interrupts
For vector interrupts, after an interrupt occurs, the PC pointer will jump to the address of base address + interrupt number * 4 according to the type of interrupt to execute the interrupt handler. Those who have worked with stm32 should have a clear idea of what vector interrupts look like. Of course, riscv also supports this type of vector interrupt, so that a specific interrupt handler function will be arranged at each address. When an interrupt occurs, it can jump to the specific function to execute.
For non-vector interrupts, it means that there is only one entry after the interrupt occurs, and the specific interrupt number needs to be determined in this interrupt. This behavior can be seen in common mips processors and sparc processors.
Since riscv supports these two interrupt handling methods, and the library functions of gd32vf103 also implement these two mechanisms, let's thoroughly analyze the implementation strategies.
2. Interrupt vector table initialization
Any code will specify the base address of the vector when it is initialized at the initial assembly level. Of course, riscv is no exception.
The understanding here is to store it in the mtvt register vector_base, which stores the vector address entry. When each vector interrupt occurs, the corresponding function is executed according to the offset.
According to the riscv data model, it is divided into I data model and E data model, which is described in the riscv MISA register. In short, the E data model has half as many registers as the I data model. The E data model is specifically designed for embedded application scenarios. Fewer registers means faster stack push and pop, and better real-time performance.
The I data model has a total of 32 registers, while the E data model has 16 registers.
Therefore, when the interrupt is pushed into the stack, the E data model will push 10 registers.
Caller represents the registers that can be used by the interrupt upper function, so
x1,x5,x6,x7,x10,x11,x12,x13,x14,x15
These 10 registers will be saved, and the above program saves x4 more.
Let's understand the interrupt processing and csrrw ra, CSR_JALMNXTI, raanalyze it through this instruction.
It is not difficult to find that this is a custom extended instruction from the core. CSR_JALMNXTIThe register can be parsed by gdb to see the following data
So how does an instruction implement interrupt processing?
In fact, this instruction will first determine whether there is an unprocessed interrupt pending in the current eclic. If not, this instruction will be executed downward and will not process anything. Once it exists, it will jump to the entry of the interrupt vector of the eclic, which is the key point.
It should also be noted that when entering the interrupt by default, the interrupt is turned off when saving the scene. When this statement is executed, the interrupt will be turned on, and then it will be determined whether there are any unresponsive interrupts, so that the interrupt tail effect can be achieved.
And when the interrupt handling function is executed, it will return to the instruction and execute it again to determine whether the interrupt needs to be handled. All these actions are completed by hardware, which greatly improves the efficiency of interrupt handling.
On-site recovery is the reverse process of interrupt processing and will not be described here.
4. Understanding of the gd32vf103 interrupt programming model
For processors such as cortex-m3, the underlying model of riscv seems to be more complicated, but in fact, csrrw ra, CSR_JALMNXTI, raafter figuring out the riscv interrupt handling model, eclic interrupt handling mechanism, as well as vector interrupts, non-vector interrupts and an interrupt handling instruction, it will not be very difficult to understand.
When playing with gd32vf103, the interrupt processing at the riscv bottom assembly level generally does not require much modification, and you can just understand it. What you need to use is the eclic configuration, as well as the configuration of the related gpio interrupt pins. After completing the interrupt line and eclic configuration, you can implement your own business logic in the specific interrupt processing function, without much learning cost.