11#!/usr/bin/env python3
2- #
2+ #
33# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44#
55
66import ctypes
7+ from qiling .arch .cortex_m_const import IRQ
78
89from qiling .hw .peripheral import QlPeripheral
910
@@ -28,11 +29,11 @@ class Type(ctypes.Structure):
2829
2930 def __init__ (self , ql , label ):
3031 super ().__init__ (ql , label )
31-
32+
3233 # reference:
3334 # https://www.youtube.com/watch?v=uFBNf7F3l60
34- # https://developer.arm.com/documentation/ddi0439/b/Nested-Vectored-Interrupt-Controller
35-
35+ # https://developer.arm.com/documentation/ddi0439/b/Nested-Vectored-Interrupt-Controller
36+
3637 self .instance = self .struct ()
3738
3839 ## The max number of interrupt request
@@ -50,8 +51,8 @@ def __init__(self, ql, label):
5051 (self .struct .ICPR , self .clear_pending ),
5152 ]
5253
53- self .intrs = []
54- self .interrupt_handler = self .ql .arch .interrupt_handler
54+ self .intrs = []
55+ self .interrupt_handler = self .ql .arch .interrupt_handler
5556
5657 def enable (self , IRQn ):
5758 if IRQn >= 0 :
@@ -79,7 +80,7 @@ def set_pending(self, IRQn):
7980 self .instance .ICPR [IRQn >> self .OFFSET ] |= 1 << (IRQn & self .MASK )
8081 else :
8182 self .ql .hw .scb .set_pending (IRQn )
82-
83+
8384 if self .get_enable (IRQn ):
8485 self .intrs .append (IRQn )
8586
@@ -100,19 +101,33 @@ def get_priority(self, IRQn):
100101 if IRQn >= 0 :
101102 return self .instance .IPR [IRQn ]
102103 else :
103- return self .ql .hw .scb .get_priority (IRQn )
104-
104+ return self .ql .hw .scb .get_priority (IRQn )
105+
105106 def step (self ):
106107 if not self .intrs :
107108 return
108109
109- self .intrs .sort (key = lambda x : self .get_priority (x ))
110-
110+ self .intrs .sort (key = lambda x : self .get_priority (x ))
111+
112+ postponed = []
113+
111114 while self .intrs :
112115 IRQn = self .intrs .pop (0 )
116+
117+ basepri = self .ql .arch .regs .basepri & 0xF0
118+ if (
119+ (basepri and basepri <= self .get_priority (IRQn ))
120+ or (IRQn > IRQ .HARD_FAULT and (self .ql .arch .regs .primask & 0x1 ))
121+ or (IRQn != IRQ .NMI and (self .ql .arch .regs .faultmask & 0x1 ))
122+ ):
123+ postponed .append (IRQn )
124+ continue
125+
113126 self .clear_pending (IRQn )
114127 self .interrupt_handler (self .ql , IRQn )
115128
129+ self .intrs = postponed
130+
116131 @QlPeripheral .monitor ()
117132 def read (self , offset : int , size : int ) -> int :
118133 buf = ctypes .create_string_buffer (size )
@@ -132,13 +147,13 @@ def write_byte(ofs, byte):
132147 ipr = self .struct .IPR
133148 if ipr .offset <= ofs < ipr .offset + ipr .size :
134149 byte &= 0xf0 # IPR[3: 0] reserved
135-
136- ctypes .memmove (ctypes .addressof (self .instance ) + ofs , bytes ([byte ]), 1 )
150+
151+ ctypes .memmove (ctypes .addressof (self .instance ) + ofs , bytes ([byte ]), 1 )
137152
138153 for ofs in range (offset , offset + size ):
139154 write_byte (ofs , value & 0xff )
140155 value >>= 8
141156
142157 @property
143158 def region (self ):
144- return [(0 , self .struct .RESERVED5 .offset ), (self .struct .STIR .offset , ctypes .sizeof (self .struct ))]
159+ return [(0 , self .struct .RESERVED5 .offset ), (self .struct .STIR .offset , ctypes .sizeof (self .struct ))]
0 commit comments