@@ -173,7 +173,7 @@ _nmi_vector:
173173
174174// -----------------------------------------------------------------------
175175// Offset 0x300 — Kernel exception
176- // Diagnostic: steady 1s ON / 1s OFF blink .
176+ // Writes EXCCAUSE + EPC1 to RTC STORE regs , then triggers software reset .
177177// -----------------------------------------------------------------------
178178 .org _vector_table + 0x300
179179_kernel_vector:
@@ -192,17 +192,39 @@ _level1_vector:
192192
193193// -----------------------------------------------------------------------
194194// Offset 0x3C0 — Double exception
195- // Diagnostic: solid LED ON (no blinking).
195+ // Diagnostic: write magic to RTC STORE regs , then halt.
196+ // RTC_CNTL_STORE0 = 0x60008050 , STORE1 = 0x60008054
196197// -----------------------------------------------------------------------
197198 .org _vector_table + 0x3C0
198199_double_vector:
199- movi a0 , 1
200- slli a0 , a0 , 21
201- movi a1 , 6
202- slli a1 , a1 , 28
203- addmi a1 , a1 , 0x4000
204- s32i a0 , a1 , 0x0C // LED ON permanently
205- 1 : j 1b // spin forever
200+ // Write 0x55550000 + EXCCAUSE to RTC_CNTL_STORE0 ( 0x60008050 )
201+ // Build address: 0x60008050 = 6 << 28 + 0x4000 + 0x4000 + 0x50
202+ movi a0 , 6
203+ slli a0 , a0 , 28 // a0 = 0x60000000
204+ addmi a0 , a0 , 0x4000 // a0 = 0x60004000
205+ addmi a0 , a0 , 0x4000 // a0 = 0x60008000
206+ addi a0 , a0 , 0x50 // a0 = 0x60008050
207+ rsr a1 , EXCCAUSE
208+ movi a2 , 0x555
209+ slli a2 , a2 , 20 // a2 = 0x55500000
210+ movi a3 , 5
211+ slli a3 , a3 , 16 // a3 = 0x00050000
212+ or a2 , a2 , a3 // a2 = 0x55550000
213+ or a1 , a2 , a1 // a1 = 0x5555xxxx
214+ s32i a1 , a0 , 0 // STORE0
215+ rsr a1 , DEPC
216+ s32i a1 , a0 , 4 // STORE1 = DEPC
217+ rsr a1 , EPC1
218+ s32i a1 , a0 , 8 // STORE2 = EPC1
219+ // Trigger software system reset (preserves RTC STORE regs).
220+ // RTC_CNTL_OPTIONS0_REG = 0x60008000 , bit 31 = SW_SYS_RST
221+ addi a0 , a0 , - 0x50 // a0 = 0x60008000
222+ l32i a1 , a0 , 0
223+ movi a2 , 1
224+ slli a2 , a2 , 31
225+ or a1 , a1 , a2
226+ s32i a1 , a0 , 0 // trigger reset
227+ 1 : j 1b // wait for reset
206228
207229// -----------------------------------------------------------------------
208230// Level - 1 interrupt handler — lives outside the vector table so there
@@ -232,6 +254,13 @@ _double_vector:
232254 .balign 4
233255.LhandleInterrupt_addr:
234256 . word handleInterrupt
257+ .Luser_exception_addr:
258+ . word espradio_user_exception
259+
260+ // Make espradio_user_exception a weak reference so programs th at don't
261+ // link espradio (e.g. blinky) still build. The default handler below
262+ // is used when no strong definition is provided.
263+ .weak espradio_user_exception
235264
236265// -----------------------------------------------------------------------
237266// Kernel exception handler ( out - of - table).
@@ -243,25 +272,30 @@ _double_vector:
243272// 29 blinks = cause 28 (LoadProhibitedCause)
244273// -----------------------------------------------------------------------
245274_handle_kernel_exc:
246- // Steady 1 - second ON / 1 - second OFF blink.
247- // This is the KERNEL exception handler.
248- movi a0 , 1
249- slli a0 , a0 , 21 // a0 = GPIO21 bit
250- movi a1 , 6
251- slli a1 , a1 , 28
252- addmi a1 , a1 , 0x4000 // a1 = 0x60004000
253- _hke_blink:
254- s32i a0 , a1 , 0x0C // LED ON
255- movi a2 , 5
256- slli a2 , a2 , 23 // ~1s @40MHz
257- 1 : addi a2 , a2 , - 1
258- bnez a2 , 1b
259- s32i a0 , a1 , 0x08 // LED OFF
260- movi a2 , 5
261- slli a2 , a2 , 23 // ~1s @40MHz
262- 1 : addi a2 , a2 , - 1
263- bnez a2 , 1b
264- j _hke_blink
275+ // Write 0x55560000 + EXCCAUSE to RTC_CNTL_STORE0 ( 0x60008050 )
276+ movi a0 , 6
277+ slli a0 , a0 , 28
278+ addmi a0 , a0 , 0x4000
279+ addmi a0 , a0 , 0x4000
280+ addi a0 , a0 , 0x50 // a0 = 0x60008050
281+ rsr a1 , EXCCAUSE
282+ movi a2 , 0x555
283+ slli a2 , a2 , 20
284+ movi a3 , 6
285+ slli a3 , a3 , 16
286+ or a2 , a2 , a3 // a2 = 0x55560000
287+ or a1 , a2 , a1
288+ s32i a1 , a0 , 0 // STORE0
289+ rsr a1 , EPC1
290+ s32i a1 , a0 , 4 // STORE1 = EPC1
291+ // Trigger software system reset (preserves RTC STORE regs).
292+ addi a0 , a0 , - 0x50 // a0 = 0x60008000
293+ l32i a1 , a0 , 0
294+ movi a2 , 1
295+ slli a2 , a2 , 31
296+ or a1 , a1 , a2
297+ s32i a1 , a0 , 0 // trigger reset
298+ 1 : j 1b // wait for reset
265299
266300 . global _handle_level1
267301_handle_level1:
@@ -312,6 +346,26 @@ _handle_level1:
312346 wsr a2 , PS
313347 rsync
314348
349+ // Check if this is an exception ( not an interrupt).
350+ // EXCCAUSE == 4 means level - 1 interrupt ; anything else is an exception.
351+ rsr a2 , EXCCAUSE
352+ movi a3 , 4
353+ beq a2 , a3 , .Lis_interrupt
354+
355+ // --- It's an exception , not an interrupt ---
356+ // Call the C exception handler: espradio_user_exception(cause , epc , excvaddr , frame)
357+ // Using callx4 (same convention as handleInterrupt).
358+ mov a6 , a2 // a6 = EXCCAUSE (will be a2 after window rotate)
359+ l32i a7 , a1 , 68 // a7 = EPC1 (saved earlier)
360+ rsr a8 , EXCVADDR // a8 = faulting address
361+ mov a9 , a1 // a9 = frame pointer (callee a5)
362+ mov a5 , a1 // callee stack
363+ l32r a2 , .Luser_exception_addr
364+ callx4 a2
365+ // Does not return — loops forever in the C handler.
366+
367+ .Lis_interrupt:
368+
315369 // Call the Go interrupt dispatcher via callx4.
316370 // callx4 explicitly sets PS.CALLINC= 1 and puts the return address
317371 // (with top 2 bits = 01 ) in a4. After entry rotates the window by
@@ -357,3 +411,16 @@ _handle_level1:
357411 l32i a1 , a1 , 4 // restores original SP (deallocates frame)
358412
359413 rfe
414+
415+ // -----------------------------------------------------------------------
416+ // Default weak espradio_user_exception: infinite loop halt.
417+ // Overridden by the strong definition in espradio's isr.c when linked.
418+ // -----------------------------------------------------------------------
419+ . section .iram1 , "ax"
420+ .balign 4
421+ .weak espradio_user_exception
422+ .type espradio_user_exception , @function
423+ espradio_user_exception:
424+ waiti 0
425+ j espradio_user_exception
426+ .size espradio_user_exception , . - espradio_user_exception
0 commit comments