@@ -34,9 +34,9 @@ func (i Interrupt) Enable() error {
3434 // Set pulse interrupt type (rising edge detection)
3535 esp .INTERRUPT_CORE0 .CPU_INT_TYPE .SetBits (1 << i .num )
3636
37- // Set default threshold to 5
37+ // Set default threshold to defaultThreshold
3838 reg := (* volatile .Register32 )(unsafe .Pointer ((uintptr (unsafe .Pointer (& esp .INTERRUPT_CORE0 .CPU_INT_PRI_0 )) + uintptr (i .num )* 4 )))
39- reg .Set (5 )
39+ reg .Set (defaultThreshold )
4040
4141 // Reset interrupt before reenabling
4242 esp .INTERRUPT_CORE0 .CPU_INT_CLEAR .SetBits (1 << i .num )
@@ -47,19 +47,136 @@ func (i Interrupt) Enable() error {
4747 return nil
4848}
4949
50+ // Adding pseudo function calls that is replaced by the compiler with the actual
51+ // functions registered through interrupt.New.
52+ //go:linkname callHandlers runtime/interrupt.callHandlers
53+ func callHandlers (num int )
54+
55+ const (
56+ IRQNUM_1 = 1 + iota
57+ IRQNUM_2
58+ IRQNUM_3
59+ IRQNUM_4
60+ IRQNUM_5
61+ IRQNUM_6
62+ IRQNUM_7
63+ IRQNUM_8
64+ IRQNUM_9
65+ IRQNUM_10
66+ IRQNUM_11
67+ IRQNUM_12
68+ IRQNUM_13
69+ IRQNUM_14
70+ IRQNUM_15
71+ IRQNUM_16
72+ IRQNUM_17
73+ IRQNUM_18
74+ IRQNUM_19
75+ IRQNUM_20
76+ IRQNUM_21
77+ IRQNUM_22
78+ IRQNUM_23
79+ IRQNUM_24
80+ IRQNUM_25
81+ IRQNUM_26
82+ IRQNUM_27
83+ IRQNUM_28
84+ IRQNUM_29
85+ IRQNUM_30
86+ IRQNUM_31
87+ )
88+
89+ const (
90+ defaultThreshold = 5
91+ disableThreshold = 10
92+ )
93+
94+ //go:inline
95+ func callHandler (n int ) {
96+ switch n {
97+ case IRQNUM_1 :
98+ callHandlers (IRQNUM_1 )
99+ case IRQNUM_2 :
100+ callHandlers (IRQNUM_2 )
101+ case IRQNUM_3 :
102+ callHandlers (IRQNUM_3 )
103+ case IRQNUM_4 :
104+ callHandlers (IRQNUM_4 )
105+ case IRQNUM_5 :
106+ callHandlers (IRQNUM_5 )
107+ case IRQNUM_6 :
108+ callHandlers (IRQNUM_6 )
109+ case IRQNUM_7 :
110+ callHandlers (IRQNUM_7 )
111+ case IRQNUM_8 :
112+ callHandlers (IRQNUM_8 )
113+ case IRQNUM_9 :
114+ callHandlers (IRQNUM_9 )
115+ case IRQNUM_10 :
116+ callHandlers (IRQNUM_10 )
117+ case IRQNUM_11 :
118+ callHandlers (IRQNUM_11 )
119+ case IRQNUM_12 :
120+ callHandlers (IRQNUM_12 )
121+ case IRQNUM_13 :
122+ callHandlers (IRQNUM_13 )
123+ case IRQNUM_14 :
124+ callHandlers (IRQNUM_14 )
125+ case IRQNUM_15 :
126+ callHandlers (IRQNUM_15 )
127+ case IRQNUM_16 :
128+ callHandlers (IRQNUM_16 )
129+ case IRQNUM_17 :
130+ callHandlers (IRQNUM_17 )
131+ case IRQNUM_18 :
132+ callHandlers (IRQNUM_18 )
133+ case IRQNUM_19 :
134+ callHandlers (IRQNUM_19 )
135+ case IRQNUM_20 :
136+ callHandlers (IRQNUM_20 )
137+ case IRQNUM_21 :
138+ callHandlers (IRQNUM_21 )
139+ case IRQNUM_22 :
140+ callHandlers (IRQNUM_22 )
141+ case IRQNUM_23 :
142+ callHandlers (IRQNUM_23 )
143+ case IRQNUM_24 :
144+ callHandlers (IRQNUM_24 )
145+ case IRQNUM_25 :
146+ callHandlers (IRQNUM_25 )
147+ case IRQNUM_26 :
148+ callHandlers (IRQNUM_26 )
149+ case IRQNUM_27 :
150+ callHandlers (IRQNUM_27 )
151+ case IRQNUM_28 :
152+ callHandlers (IRQNUM_28 )
153+ case IRQNUM_29 :
154+ callHandlers (IRQNUM_29 )
155+ case IRQNUM_30 :
156+ callHandlers (IRQNUM_30 )
157+ case IRQNUM_31 :
158+ callHandlers (IRQNUM_31 )
159+ }
160+ }
161+
50162//export handleInterrupt
51163func handleInterrupt () {
52164 mcause := riscv .MCAUSE .Get ()
53165 exception := mcause & (1 << 31 ) == 0
54166 interruptNumber := uint32 (mcause & 0x1f )
55167
56168 if ! exception && interruptNumber > 0 {
57- // save mepc, which could be overwritten by another CPU interrupt
169+ // save MSTATUS & MEPC, which could be overwritten by another CPU interrupt
170+ mstatus := riscv .MSTATUS .Get ()
58171 mepc := riscv .MEPC .Get ()
172+ // Useing threshold to temporary disable this interrupts.
173+ // FYI: using CPU interrupt enable bit make runtime to loose interrupts.
174+ reg := (* volatile .Register32 )(unsafe .Pointer ((uintptr (unsafe .Pointer (& esp .INTERRUPT_CORE0 .CPU_INT_PRI_0 )) + uintptr (interruptNumber )* 4 )))
175+ thresholdSave := reg .Get ()
176+ reg .Set (disableThreshold )
177+ riscv .Asm ("fence" )
59178
60- // disable interrupt
61179 interruptBit := uint32 (1 << interruptNumber )
62- esp .INTERRUPT_CORE0 .CPU_INT_ENABLE .ClearBits (interruptBit )
63180
64181 // reset pending status interrupt
65182 if esp .INTERRUPT_CORE0 .CPU_INT_TYPE .Get ()& interruptBit != 0 {
@@ -72,23 +189,22 @@ func handleInterrupt() {
72189 }
73190
74191 // enable CPU interrupts
75- riscv .MSTATUS .SetBits (0x8 )
192+ riscv .MSTATUS .SetBits (1 << 3 )
76193
77194 // Call registered interrupt handler(s)
78- esp . HandleInterrupt (int (interruptNumber ))
195+ callHandler (int (interruptNumber ))
79196
80197 // disable CPU interrupts
81- riscv .MSTATUS .ClearBits (0x8 )
198+ riscv .MSTATUS .ClearBits (1 << 3 )
82199
83- // mpie must be set to 1 to resume interrupts after 'MRET'
84- riscv .MSTATUS .SetBits (0x80 )
200+ // restore interrupt threshold to enable interrupt again
201+ reg .Set (thresholdSave )
202+ riscv .Asm ("fence" )
85203
86- // restore MEPC
204+ // restore MSTATUS & MEPC
205+ riscv .MSTATUS .Set (mstatus )
87206 riscv .MEPC .Set (mepc )
88207
89- // enable this interrupt
90- esp .INTERRUPT_CORE0 .CPU_INT_ENABLE .SetBits (interruptBit )
91-
92208 // do not enable CPU interrupts now
93209 // the 'MRET' in src/device/riscv/handleinterrupt.S will copies the state of MPIE back into MIE, and subsequently clears MPIE.
94210 // riscv.MSTATUS.SetBits(0x8)
@@ -104,6 +220,16 @@ func handleException(mcause uintptr) {
104220 println ("*** Exception: pc:" , riscv .MEPC .Get ())
105221 println ("*** Exception: code:" , uint32 (mcause & 0x1f ))
106222 println ("*** Exception: mcause:" , mcause )
223+ switch uint32 (mcause & 0x1f ) {
224+ case 1 :
225+ println ("*** virtual addess:" , riscv .MTVAL .Get ())
226+ case 2 :
227+ println ("*** opcode:" , riscv .MTVAL .Get ())
228+ case 5 :
229+ println ("*** read address:" , riscv .MTVAL .Get ())
230+ case 7 :
231+ println ("*** write address:" , riscv .MTVAL .Get ())
232+ }
107233 for {
108234 riscv .Asm ("wfi" )
109235 }
0 commit comments