Method for managing interrupt nesting based on risc-v general interrupt controller
Patent Information
- Application Number
- CN202510539746.8
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2025-04-27
- Publication Date
- 2026-10-27
AI Technical Summary
[0017]1).解决在嵌入式芯片领域,在不需要复杂的硬件中断控制器的情况下,使用方法处理中断嵌套和抢占,使高优先级中断可以打断低优先级的执行,提高中断响应速度
[0071]1).可以在没有复杂硬件中断控制器的CPU上可以支持中断抢占和中断嵌套。
Smart Images

Figure CN122985247A_ABST
Abstract
Description
Technical Field
[0001] This invention belongs to the field of microprocessor interrupt management technology, and specifically relates to a method for managing nested interrupts based on a RISC-V general interrupt controller. Background Technology
[0002] In existing technologies, the conventional non-preemptive interrupt handling process is as follows: Figure 1 As shown, an interrupt occurred during the execution of the main program, and the CPU jumped to the exception entry point for processing. Throughout the process, global interrupts were disabled, meaning the CPU could not respond to other interrupt requests. If the interrupt processing time was too long, it would affect the real-time response efficiency of the entire system, meaning it would be unable to respond to high-priority interrupts.
[0003] The non-preemptive processing flow mainly includes the following steps:
[0004] Preserve the scene
[0005] Service interruption
[0006] Restoring the scene
[0007] These three processes are executed atomically, and no other interrupts are allowed to enter. The execution time of the interrupt service is longer than that of saving and restoring the context.
[0008] To improve the response time of specific interrupts, interrupt service routines can be interrupted by specific interrupts. Therefore, interrupts should be enabled in the interrupt service routine to allow specific interrupts to enter.
[0009] Therefore, the interrupt mask bit can be controlled to enable a specific interrupt to be responded to.
[0010] Some interrupt handling methods typically use fixed priority or simple nesting mechanisms, which have the following problems:
[0011] 1. Response delay: When a low-priority interrupt service routine is executed, a high-priority interrupt cannot preempt it in time, resulting in a response delay.
[0012] 2. Hardware dependency: Some solutions require complex hardware logic (such as multi-level interrupt controllers) to implement priority management, which increases costs.
[0013] 3. Insufficient flexibility: It is difficult to dynamically adjust interrupt priorities and adapt to different application scenarios.
[0014] In other words, the shortcomings of existing technology are:
[0015] When a low-priority interrupt service routine is executed, a high-priority interrupt cannot preempt it in time, resulting in a response delay. Summary of the Invention
[0016] In order to solve the above problems, the purpose of this application is:
[0017] 1) In the field of embedded chips, a method is used to handle interrupt nesting and preemption without the need for a complex hardware interrupt controller, so that high-priority interrupts can interrupt the execution of low-priority interrupts, thereby improving interrupt response speed.
[0018] 2) Simplify hardware design. The hardware does not need to be designed with a complex interrupt controller. Only two simple register groups, Mask and Pending, are needed to manage interrupt priorities.
[0019] 3) Flexibility can compensate for the fixed priority design in some hardware designs, which makes it impossible to dynamically adjust the interrupt response priority.
[0020] 4) Based on the lookup table processing method, optimize the processing flow, improve the efficiency of general interrupt response, and enhance the system's real-time response capability.
[0021] Specifically, the present invention provides a method for managing interrupt nesting based on a RISC-V general interrupt controller, comprising the following steps:
[0022] S1, the preemptive interrupt handling process, includes:
[0023] When an interrupt occurs, the current context (SaveContext) is saved, including the register state, and the interrupt enable (IE) and mask (MASK) states are dynamically configured to allow preemption of high-priority interrupts.
[0024] Enable global interrupt MSTATUS_MIE for RISC-V and execute the interrupt service routine;
[0025] After the interrupt is handled, global interrupt enable is disabled, and the masked interrupt source and register state are restored (RestoreContext).
[0026] S2, the process of dynamically updating the irq_mask_table, includes:
[0027] The priority (prio) of the target interrupt is obtained by querying the irq_priority_table using the interrupt number (irq_number); if the current context is non-interrupt, the hardware IRQ_MASK register is configured directly.
[0028] If in interrupt context, update the mask bits in irq_mask_table with priority lower than or equal to prio, and synchronize irq_mask_table[prio] to the IRQ_MASK register with a single instruction;
[0029] S3, interruption priority determination process, includes:
[0030] Save the current interrupt priority cur_irq_priority to the stack;
[0031] Iterate through the IRQ_Pending register and perform logical AND operations on each level in conjunction with the irq_mask_table to determine the highest valid interrupt priority (prio).
[0032] Update cur_irq_priority = prio, and record any unhandled interruptions in the cur_irq_pending[prio] table;
[0033] S4, interrupt handling process, includes:
[0034] The interrupt number irq_number to be processed is obtained from the cur_irq_pending table based on cur_irq_priority; the interrupt service is executed by calling handle_irq(irq_number), during which nested execution of higher priority interrupts is allowed.
[0035] Step S1 further includes:
[0036] S1.1 When an interrupt or exception occurs, enter the exception entry point and disable global interrupts;
[0037] S1.2, save the current register state and push the currently processed interrupt priority cur_irq_priority onto the stack;
[0038] S1.3, Find and update the current interrupt priority cur_irq_priority to the new priority pr0; S1.4, Mask all interrupt sources with a priority less than or equal to cur_irq_priority;
[0039] S1.5, Enable global interrupts and execute the interrupt handling routine;
[0040] S1.6 After the interrupt handling is completed, global interrupts are disabled, and the previously saved cur_irq_priority is restored from the stack;
[0041] S1.7, restore the masked interrupt source and restore the register state;
[0042] S1.8, execute exception return, continue processing the original task or respond to higher priority interrupts. The higher priority interrupts can be nested and the steps are the same as the previous exception handling process, realizing dynamic priority switching and nested response.
[0043] Step S1 also includes:
[0044] The interrupt masking status can be dynamically configured by looking up the irq_mask_table, allowing high-priority interrupts to interrupt low-priority interrupts.
[0045] The irq_mask_table is an array structure, and its member values correspond one-to-one with the interrupt priority. The bits of each member value indicate whether interrupt response is allowed under that priority.
[0046] The Irq_mask_table update process in step S2 includes:
[0047] S2.1 When the system calls enable_irq or disable_irq, the priority of the target interrupt is obtained by querying the irq_priority_table through the irq_number index;
[0048] S2.2 If the current state is not in interrupt handling, update the corresponding bit in irq_mask_table according to the priority prio;
[0049] S2.3 Write the updated irq_mask_table content into the IRQ_MASK register to dynamically adjust the interrupt masking status;
[0050] The above steps enable or disable interrupt sources based on their priority, ensuring that high-priority interrupts are not blocked by low-priority interrupts. Dynamic priority configuration is supported, allowing the subsequent interrupt masking logic to be affected in real time by modifying the priority values in the irq_priority_table.
[0051] Step S2 also includes:
[0052] By setting or clearing the corresponding bit in the irq_mask_table below the priority level, the current and lower priority interrupts can be quickly masked.
[0053] A single instruction is needed to copy the value of irq_mask_table[prio] to the IRQ_MASK register, achieving efficient interrupt masking.
[0054] Step S3 further includes:
[0055] S3.1, save the current interrupt priority cur_irq_priority to the stack, i.e., *sp = cur_irq_priority;
[0056] S3.2, initialize the priority lookup variable prto = 0, and obtain the status of the interrupt to be processed through the IRQ_Pending register; traverse the priority mask table irq_mask_table, and perform the following operations in sequence: S3.2.1, obtain the mask irq_mask corresponding to the current priority prto from the irq_mask_table; S3.2.2, perform a logical AND operation between irq_mask and the value of the IRQ_Pending register to obtain the valid interrupt result result;
[0057] S3.2.3, if result! = 0, then update the current processing priority cur_irq_priority = prto and terminate the traversal;
[0058] S3.2.4, otherwise increment prto and continue checking the next priority;
[0059] S3.3, disable all interrupt sources with a priority less than or equal to cur_irq_priority;
[0060] S3.4, Update the interrupt handling status, i.e., the cur_irq_pending table, according to the finally determined cur_irq_priority;
[0061] Among its features, it supports multi-priority polling, dynamically determining the highest valid interrupt priority by traversing the irq_mask_table to ensure real-time response.
[0062] Step S3 also includes:
[0063] Supports multi-priority polling, determining the highest valid interrupt priority by dynamically traversing the irq_mask_table;
[0064] Use the cur_irq_pending table to record the status of unhandled interruptions to ensure real-time response.
[0065] Step S4 further includes:
[0066] Query the cur_irq_pending table based on cur_irq_priority to determine the interrupt number irq_number to be processed;
[0067] The corresponding interrupt handler function handle_irq(irq_number) is called to execute the specific interrupt service logic; through dynamic matching of priority and interrupt number, the service routine of high-priority interrupts is ensured to be executed first.
[0068] The irq_mask_table is a multidimensional array, where each element corresponds to an interrupt mask of a certain priority and is mapped one-to-one with the bits of the hardware IRQ_MASK register. It supports dynamic adjustment of the interrupt response strategy through enable_irq and disable_irq.
[0069] The method improves system real-time performance by implementing priority nesting and dynamic masking through a hardware-software collaborative mechanism and in the case of an interrupt controller. It also enables interrupt preemption and nesting without relying on a complex hardware interrupt controller, supports dynamic priority configuration, and optimizes interrupt response speed and masking efficiency through a lookup table.
[0070] Therefore, the advantage of this solution is:
[0071] 1) Interrupt preemption and interrupt nesting can be supported on CPUs without complex hardware interrupt controllers.
[0072] 2) Interrupt priorities can be set flexibly.
[0073] 3) Using irq_mask_table can speed up the determination of interrupt priorities.
[0074] 4) Using irq_mask_table can quickly mask low-priority interrupts with just one instruction.
[0075] 5) Optimized interrupt preemption handling logic, using a lookup table to speed up interrupt response. Attached Figure Description
[0076] The accompanying drawings, which are provided to further illustrate the invention and form part of this application, are not intended to limit the scope of the invention.
[0077] Figure 1 This is a standard non-preemptive interrupt handling flowchart.
[0078] Figure 2 This is a schematic diagram of the main preemptive processing flow in step S1 of the method of this application.
[0079] Figure 3 This is a schematic diagram of the interruption masking and priority update process in step S2 of the method of this application.
[0080] Figure 4 This is a schematic diagram of the dynamic interrupt priority handling and masking process in step S3 of the method of this application.
[0081] Figure 5 This is a flowchart illustrating the execution of priority interruption handling in step S4 of the method of this application.
[0082] Figure 6 This is a schematic diagram of the overall process of the method described in this application.
[0083] Figure 7 This is a schematic diagram of the key exception handling code and its expansion in step S1 of the method in this application.
[0084] Figure 8 This is a schematic diagram of the code snippet saved on-site in step S1 of the method of this application.
[0085] Figure 9 This is a schematic diagram of the code implementation of enable_irq and disable_irq for the CPU in step S2 of the method in this application.
[0086] Figure 10 This is a schematic diagram of the code snippet in step S4 of the method of this application that finds the irq_number using cur_irq_priority. Detailed Implementation
[0087] To better understand the technical content and advantages of the present invention, the present invention will now be described in further detail with reference to the accompanying drawings.
[0088] This application relates to a method for managing nested interrupts based on a RISC-V general-purpose interrupt controller. It addresses the shortcomings of existing technologies by optimizing interrupt handling processes, dynamic priority management, and hardware-software coordination mechanisms. Specifically, by optimizing interrupt priority management and dynamically configuring the interrupt Mask and Pend registers, it achieves efficient nested interrupt handling, improving system real-time performance and flexibility.
[0089] Building upon conventional interrupt handling procedures, this method allows for nested interrupt handling processes without complex hardware interrupt controllers. This provides interrupt priority management and nesting capabilities, improving the system's real-time response to high-priority interrupts. Furthermore, it innovatively optimizes the interrupt handling process using lookup tables, further enhancing interrupt response efficiency. Specifically, it includes the following steps: Figure 6 As shown:
[0090] Step S1, Preemptive Interrupt Implementation Process
[0091] Key exception handling code and its expansion, such as Figure 7 As shown:
[0092] 1. Exception handling entry point:
[0093] The exception handling entry point is defined using the assembly macro __BUILD_INTERRUPT_HANDLER_PRIORITY, including:
[0094] Declare the global label handle_\exception.
[0095] The external function do_handler is called to execute the specific exception handling logic.
[0096] SAVE_INTERRUPT_CONTEXT_PRIORITY (save the context) and RESTORE_INTERRUPT_CONTEXT_PRIORITY (restore the context) are executed before and after the call, respectively.
[0097] 2. Save the current state (SAVE_INTERRUPT_CONTEXT_PRIORITY):
[0098] Call SAVE_CONTEXT_INTERNAL to save the general-purpose register context.
[0099] Save the critical section nesting count (xCriticalNesting) to the stack.
[0100] Save mstatus (machine status register) and mepc (exception return address) to the stack. Call cpu_prio_context_save to save the priority-related context.
[0101] Check the interrupt priority level (IRQ_LEVEL_NUM). If it is the highest priority, save the current task stack pointer (sp) to the task control block (pxCurrentTCB).
[0102] Update mstatus to suppress interrupts.
[0103] 3. Execute exception handling: Call the user-defined do_handler function to handle exceptions.
[0104] 4. Restore the context (RESTORE_INTERRUPT_CONTEXT_PRIORITY):
[0105] Clear the interrupt enable bit (MIE) of mstatus.
[0106] Call cpu_prio_context_restore to restore the priority-related context.
[0107] Check the interrupt priority level. If it is the highest priority, restore the stack pointer (sp) from the task control block (pxCurrentTCB).
[0108] Restore the mepc and mstatus registers.
[0109] Restore the critical section nesting count (xCriticalNesting).
[0110] Call RESTORE_CONTEXT_INTERNAL to restore the general-purpose register context.
[0111] 5. Exit Exception: Return to the execution point before the exception occurred using mret (implied in context recovery).
[0112] The main process of the preemptive processing proposed in this invention is as follows: Figure 2 As shown, its main process is described below:
[0113] 1. SaveContext saves the current state.
[0114] Save registers
[0115] Handle IEs or MASKs at all levels, enable high-priority interrupts, and disable interrupts at the current level and the next lower level.
[0116] Enable RISCV MSTATUS_MIE to run other interrupt handling.
[0117] 2. Interruption Service Routine
[0118] 3. RestoreContext restores the current state.
[0119] Disable RISCV MSTATUS_MIE
[0120] Handle and restore interrupts at this level and below.
[0121] Restore register
[0122] The overall process is similar to the preemptive interrupt handling process. The main difference is that when saving the context, priority is determined for the interrupts that occur, and the irq_mask_table of each priority is used to mask low-priority interrupts and enable high-priority interrupts, thereby allowing high-priority interrupts to interrupt low-priority interrupts and improving the real-time response capability of the system.
[0123] Furthermore, including:
[0124] Code snippets saved on-site, such as Figure 8 As shown:
[0125] 1. Save the current interrupt priority: Store the current interrupt priority cur_irq_priority in the memory location pointed to by the pointer sp.
[0126] 2. Obtain the new interrupt priority:
[0127] Call cpu_get_irq_priority() to get the interrupt priority (prio).
[0128] If prio equals IRQ_PRIORITY_NUMS (indicating an invalid or undefined priority), then intc_get_irq_priority() is called to reacquire the priority.
[0129] 3. Update the current interrupt priority: Assign the newly acquired priority prio to cur_irq_priority and check its validity (ensure it is not equal to IRQ_PRIORITY_NUMS).
[0130] 4. Handling priority masks:
[0131] If cur_irq_priority is greater than 0, call intc_prio_irq_mask() to mask interrupts with lower priority than the current one (parameter is cur_irq_priority-1), and return MSTATUS_MIE (indicating that interrupts are enabled).
[0132] Otherwise, return 0 (indicating that the interrupt status is not changed).
[0133] Specifically, including:
[0134] S1.1 When an interrupt or exception occurs, enter the exception entry point and disable global interrupts;
[0135] S1.2, save the current register state and push the currently processed interrupt priority cur_irq_priority onto the stack;
[0136] S1.3, Find and update the current interrupt priority cur_irq_priority to the new priority pr0; S1.4, Mask all interrupt sources with a priority less than or equal to cur_irq_priority;
[0137] S1.5, Enable global interrupts and execute the interrupt handling routine;
[0138] S1.6 After the interrupt handling is completed, global interrupts are disabled, and the previously saved cur_irq_priority is restored from the stack;
[0139] S1.7, restore the masked interrupt source and restore the register state;
[0140] S1.8, execute exception return, continue processing the original task or respond to higher priority interrupt; the higher priority interrupt can be nested, and its steps are the same as the previous exception handling process, realizing dynamic priority switching and nested response.
[0141] Step S2, Irq_mask_table update process
[0142] The `irq_mask_table` determines which interrupt sources are allowed to interrupt CPU execution in the system. It is an array with a maximum value equal to the number of interrupt priorities supported by the system. For example, if the system supports a maximum of 4 interrupt priority levels, then `irq_mask_table` is defined as `uint32irq_mask_table`[4], where each member is a 32-bit value. The 0 and 1 of each bit represent whether the interrupt can be responded to at that priority. The definition of each bit member of `irq_mask_table` corresponds one-to-one with the `IRQ_MASK` register.
[0143] The following table describes a mask controller in the X2600:
[0144]
[0145] The Irq_mask_table is updated when the system calls enable_irq or disable_irq.
[0146] The definitions of enable_irq and irq_disable are as follows:
[0147] void enable_irq(int irq_number);
[0148] void disable_irq(int irq_number);
[0149] `enable_irq` and `disable_irq` are a general term for interrupt-enabled irq. Specifically, the implementation of `enable_irq` and `disable_irq` in the CPU is as follows: Figure 9 As shown:
[0150] 1. Obtain the interrupt number parameter
[0151] Calculate the interrupt number: num = irq - IRQ_CPU_BASE
[0152] Retrieve the interrupt priority from the priority table: prio = irq_priority_tbl[num]
[0153] 2. Handling enable / disable operations
[0154] Enable process:
[0155] Verify priority validity: If prio ≥ IRQ_PRIORITY_NUMS, then adjust to the maximum value (IRQ_PRIORITY_NUMS - 1).
[0156] Update priority table: irq_priority_tbl[num] = prio
[0157] Update maximum priority: If the current max_priority ≥ prio, then max_priority = prio. Set enable bits: From prio to IRQ_PRIORITY_NUMS-1, set the corresponding bits of irq_enable_tbl level by level.
[0158] Disabling process:
[0159] Clear enable bits: Clear the corresponding bits of irq_enable_tbl level by level from prio to IRQ_PRIORITY_NUMS-1. Recalculate maximum priority: Scan all interrupt priorities and update max_priority to the minimum value. 3. Update the machine interrupt enable register (MIE).
[0160] Check for non-interrupt environments: if(!in_interrupts())
[0161] Read the current MIE value
[0162] When enabling: OR the value of the highest priority enable table with the MIE.
[0163] When disabled: Invert the value of the highest priority enable table and then compare it with the MIE.
[0164] Write back to MIE register
[0165] 4. Jointly conclude the process
[0166] The operation is complete, and the function returns.
[0167] Because the system supports interrupt preemption, `enable_irq` and `disable_irq` can be called in both interrupt and non-interrupt handling flows. When the CPU is running in a non-interrupt handling flow (i.e., main program context), the hardware `IRQ_MASK` register is configured directly. It's important to note that the `IRQ_MASK` register is a type of register that enables masked interrupts and may have different names on different controllers. For example, at the CPU level, `IRQ_MASK` corresponds to `MSTATUS_MIE`, while at the interrupt controller level, it corresponds to the `INTC_MASK` register. When the CPU is running in an interrupt handling flow (i.e., interrupt context), the `irq_mask_table` is primarily updated to ensure that the `IRQ_MASK` register is correctly updated during interrupt priority determination and restoration, thus enabling interrupt preemption. Figure 3 As shown, the enable_irq and disable_irq processes are described below:
[0168] 1. Find the interrupt priority corresponding to irq_number from irq_priority_table by inputting the irq_number parameter.
[0169] 2. By checking if the value of prio is less than the lowest priority, if it is less than the lowest priority, the system is in a non-interrupt context and the IRQ_MASK register is set directly to mask interrupts.
[0170] 3. If the value of prio is greater than the lowest priority, then the current context is interrupted. The prio index is used to access the irq_mask_table, and the value is updated.
[0171] a) The design here cleverly sets or clears all the bits corresponding to irq_mask_table below prio.
[0172] b) The advantage of this approach is that once the interrupt priority is determined, interrupts of the current priority and those below it can be quickly masked. This requires only one instruction to copy the value of irq_mask_table[prio] to the irq_mask register.
[0173] Furthermore, including:
[0174] S2.1 In the enable_irq or disable_irq process, query the irq_priority_table through the irq_number index to obtain the priority of the target interrupt, prio.
[0175] S2.2 If the current interrupt handling state is not present (in_interrupt is not present), then update the corresponding bit (prio0 to prio3) in irq_mask_table according to the priority prio.
[0176] S2.3 Write the updated irq_mask_table content into the IRQ_MASK register to dynamically adjust the interrupt masking status;
[0177] The above steps enable or disable interrupt sources based on their priority, ensuring that high-priority interrupts are not blocked by low-priority interrupts. Dynamic priority configuration is supported, allowing the subsequent interrupt masking logic to be affected in real time by modifying the priority values in the irq_priority_table.
[0178] Step S3, Interrupt Priority Determination Process
[0179] 4. Interrupt priority determination occurs at the exception entry point. The context is saved, and the interrupt source is identified. This primarily determines the priority of currently occurring interrupts and saves unprocessed interrupts to the `cur_irq_pending[prio]` table. This `cur_irq_pending[prio]` table will be used in subsequent interrupt handling processes. For example... Figure 4 As shown:
[0180] 1. Save the interrupt priority before entering the interrupt to the stack, *sp = cur_irq_priority.
[0181] 2. Iterate through the IRQ_PENDING register of the interrupt controller to determine which interrupt priority caused the interrupt, thereby confirming the priority of the interrupt to be processed. The specific process is as follows:
[0182] a) Read the value of the IRQ_Pending register.
[0183] b) Iterate through the irq_mask_table and retrieve the value of irq_mask.
[0184] c) Check if the value of IRQ_Pending & irq_mask is 0.
[0185] d) If it is not 0, it means that there is an enabled interrupt for this priority, and this priority is confirmed as the highest priority to be processed. That is, the prio in the flowchart.
[0186] 3. Using the determined prio, retrieve the corresponding irq_mask value from the irq_mask_table, perform a bitwise AND operation with the value of the IRQ_Pending register, and update the table cur_irq_pending[prio].
[0187] 4. Update cur_irq_priority=prio.
[0188] Furthermore, including:
[0189] S3.1, save the current interrupt priority cur_irq_priority to the stack (*sp = cur_irq_priority);
[0190] S3.2, initialize the priority lookup variable prto = 0, and obtain the status of the interrupt to be processed through the IRQ_Pending register; traverse the priority mask table irq_mask_table, and perform the following operations in sequence: S3.2.1, obtain the mask irq_mask corresponding to the current priority prto from the irq_mask_table; S3.2.2, perform a logical AND operation between irq_mask and the value of the IRQ_Pending register to obtain the valid interrupt result result;
[0191] S3.2.3, if result! = 0, then update the current processing priority cur_irq_priority = prto and terminate the traversal;
[0192] S3.2.4, otherwise increment prto and continue checking the next priority;
[0193] S3.3, disable all interrupt sources with a priority less than or equal to cur_irq_priority;
[0194] S3.4 Update the interrupt handling status (cur_irq_pending table) based on the final determined cur_irq_priority.
[0195] Among them, it supports multi-priority polling, dynamically determining the highest effective interrupt priority by traversing the irq_mask_table (prto0 to prto3) to ensure real-time response.
[0196] Step S4, Interruption Handling Process
[0197] The code snippet that finds irq_number using cur_irq_priority is as follows, where irq_number is the value of off+__ffs(cur_irq_flags[cur_irq_priority] in the code snippet. Figure 10 As shown: The interrupt handler first calculates the basic offset off by adding the current interrupt priority group number multiplied by 32 to the basic offset IRQ_INTC_BASE. Then, it uses the __ffs function to find the least significant bit from the current interrupt flags. Finally, it adds the two bits together and uses them as parameters to call the handle_irq function to process the specific interrupt request.
[0198] Based on the updated values of the cur_irq_pending[] table and cur_irq_priority in the above process, the interrupt number irq_number to be processed is determined. The specific process is as follows: Figure 5 As shown, the main process is described below:
[0199] 1. Use the cur_irq_priority determined in the above process to obtain the corresponding irq_number from the cur_irq_pending table.
[0200] 2. Iterate through the set bits in cur_irq_pending to identify unprocessed interrupts.
[0201] 3. Convert the interrupt number to irq_number.
[0202] 4. Call handle_irq(irq_number) to handle the interrupt.
[0203] In the interrupt handling process, a high-priority interrupt can interrupt the execution of a low-priority interrupt.
[0204] Furthermore, including:
[0205] S4.1 In the interrupt handling routine, based on the current interrupt priority cur_irq_priority, the cur_irq_pending table is queried to determine the interrupt number irq_number to be processed;
[0206] S4.2, call the corresponding interrupt handling function handle_irq(irq_number) to execute the specific interrupt service logic associated with the interrupt number;
[0207] S4.3 ensures that service routines for high-priority interrupts are executed first by dynamically matching priority with interrupt numbers.
[0208] Among them, priority-driven interrupt scheduling is supported, and the cur_irq_pending table is indexed by cur_irq_priority to achieve efficient distribution of interrupt handling.
[0209] In summary, the method of this invention achieves efficient interrupt nesting through dynamic priority determination, mask table updating, and hardware-software collaboration. The method includes: preemptive context saving and restoration, dynamic priority configuration, and rapid interrupt number distribution, significantly improving the real-time response capability of high-priority interrupts. It is suitable for resource-constrained embedded systems and can achieve:
[0210] 1. It can support interrupt preemption and interrupt nesting on CPUs without complex hardware interrupt controllers.
[0211] 2. Interrupt priorities can be set flexibly.
[0212] 3. Using irq_mask_table can speed up the determination of interrupt priorities.
[0213] 4. Using the irq_mask_table method, low-priority interrupts can be quickly masked. This can be achieved with just one instruction.
[0214] 5. Optimized interrupt preemption handling logic, using a lookup table to speed up interrupt response.
[0215] This technical solution can be applied to all series of chips from Ingenic Semiconductor and similar chips.
[0216] The above description is merely a preferred embodiment of the present invention and is not intended to limit the present invention. For those skilled in the art, various modifications and variations can be made to the embodiments of the present invention. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of the present invention should be included within the protection scope of the present invention.
Claims
1. A method for managing nested interrupts based on a RISC-V general-purpose interrupt controller, characterized in that, Includes the following steps: S1, the preemptive interrupt handling process, includes: When an interrupt occurs, the current context (SaveContext) is saved, including the register state, and the interrupt enable (IE) and mask (MASK) states are dynamically configured to allow preemption of high-priority interrupts. Enable global interrupt MSTATUS_MIE for RISC-V and execute the interrupt service routine; After the interrupt is handled, global interrupt enable is disabled, and the masked interrupt source and register state are restored (RestoreContext). S2, the process of dynamically updating the irq_mask_table, includes: The priority (prio) of the target interrupt is obtained by querying the irq_priority_table using the interrupt number (irq_number); if the current context is non-interrupt, the hardware IRQ_MASK register is configured directly. If in interrupt context, update the mask bits in irq_mask_table with priority lower than or equal to prio, and synchronize irq_mask_table[prio] to the IRQ_MASK register with a single instruction; S3, interruption priority determination process, includes: Save the current interrupt priority cur_irq_priority to the stack; Iterate through the IRQ_Pending register and perform logical AND operations on each level in conjunction with the irq_mask_table to determine the highest valid interrupt priority (prio). Update cur_irq_priority = prio, and record any unhandled interruptions in the cur_irq_pending[prio] table; S4, interrupt handling process, includes: The interrupt number irq_number to be processed is obtained from the cur_irq_pending table based on cur_irq_priority; the interrupt service is executed by calling handle_irq(irq_number), during which nested execution of higher priority interrupts is allowed.
2. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, Step S1 further includes: S1.1 When an interrupt or exception occurs, enter the exception entry point and disable global interrupts; S1.2, save the current register state and push the currently processed interrupt priority cur_irq_priority onto the stack; S1.3, Find and update the current interrupt priority cur_irq_priority to the new priority pr0; S1.4, Mask all interrupt sources with a priority less than or equal to cur_irq_priority; S1.5, Enable global interrupts and execute the interrupt handling routine; S1.6 After the interrupt handling is completed, global interrupts are disabled, and the previously saved cur_irq_priority is restored from the stack; S1.7, restore the masked interrupt source and restore the register state; S1.8, execute exception return, continue processing the original task or respond to higher priority interrupts. The higher priority interrupts can be nested and the steps are the same as the previous exception handling process, realizing dynamic priority switching and nested response.
3. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, Step S1 also includes: The interrupt masking status can be dynamically configured by looking up the irq_mask_table, allowing high-priority interrupts to interrupt low-priority interrupts. The irq_mask_table is an array structure, and its member values correspond one-to-one with the interrupt priority. The bits of each member value indicate whether interrupt response is allowed under that priority.
4. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, The Irq_mask_table update process in step S2 includes: S2.1, when the system calls enable_irq or disable_irq, query the irq_priority_table through the irq_number index to obtain the priority of the target interrupt; S2.2 If the current state is not in interrupt handling, update the corresponding bit in irq_mask_table according to the priority prio; S2.3 Write the updated irq_mask_table content into the IRQ_MASK register to dynamically adjust the interrupt masking status; The above steps enable or disable interrupt sources based on their priority, ensuring that high-priority interrupts are not blocked by low-priority interrupts. Dynamic priority configuration is supported, allowing the subsequent interrupt masking logic to be affected in real time by modifying the priority values in the irq_priority_table.
5. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 4, characterized in that, Step S2 also includes: By setting or clearing the corresponding bit in the irq_mask_table below the priority level, the current and lower priority interrupts can be quickly masked. A single instruction is needed to copy the value of irq_mask_table[prio] to the IRQ_MASK register, achieving efficient interrupt masking.
6. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, Step S3 further includes: S3.1, save the current interrupt priority cur_irq_priority to the stack, i.e., *sp = cur_irq_priority; S3.2, initialize the priority lookup variable prto = 0, and obtain the status of the interrupt to be processed through the IRQ_Pending register; traverse the priority mask table irq_mask_table, and perform the following operations in sequence: S3.2.1, obtain the mask irq_mask corresponding to the current priority prto from the irq_mask_table; S3.2.2, perform a logical AND operation between irq_mask and the value of the IRQ_Pending register to obtain the valid interrupt result result; S3.2.3, if result! = 0, then update the current processing priority cur_irq_priority = prto and terminate the traversal; S3.2.4, otherwise increment prto and continue checking the next priority; S3.3, disable all interrupt sources with a priority less than or equal to cur_irq_priority; S3.4, Update the interrupt handling status, i.e., the cur_irq_pending table, according to the finally determined cur_irq_priority; Among its features, it supports multi-priority polling, dynamically determining the highest valid interrupt priority by traversing the irq_mask_table to ensure real-time response.
7. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 6, characterized in that, Step S3 also includes: Supports multi-priority polling, determining the highest valid interrupt priority by dynamically traversing the irq_mask_table; Use the cur_irq_pending table to record the status of unhandled interruptions to ensure real-time response.
8. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, Step S4 further includes: Query the cur_irq_pending table based on cur_irq_priority to determine the interrupt number irq_number to be processed; The corresponding interrupt handler function handle_irq(irq_number) is called to execute the specific interrupt service logic; through dynamic matching of priority and interrupt number, the service routine of high-priority interrupts is ensured to be executed first.
9. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, The irq_mask_table is a multidimensional array, where each element corresponds to an interrupt mask of a certain priority and is mapped one-to-one with the bits of the hardware IRQ_MASK register. It supports dynamic adjustment of the interrupt response strategy through enable_irq and disable_irq.
10. The method for managing nested interrupts based on a RISC-V general-purpose interrupt controller according to claim 1, characterized in that, The method improves system real-time performance by implementing priority nesting and dynamic masking through a hardware-software collaborative mechanism and in the case of an interrupt controller. It also enables interrupt preemption and nesting without relying on a complex hardware interrupt controller, supports dynamic priority configuration, and optimizes interrupt response speed and masking efficiency through a lookup table.