I've tried following the program flow and have a few observations:
Handling procedure (INT is interrupt_handler in assembly):
Code: Select all
f() > INT > ak_interrupt() > RTS > INT > RTE > f()
- INT calls ak_interrupt using JSR so we are inside a "new" exception-handling context (overwritten PR, saved R15).
- We are not taking interrupts now. When ak_interrupt returns to us, PR and R15 have been clobbered by further function calls e.g. puts(). Their last value is probably at or just after the RTE instruction… I believe
- we "did" use PR during exception handling so a call to RTS without a proper JSR will come here
- e.g. gfx_clear() > INT > gfx_clear() > RTS > ???
- should we save PR during exception handling?
- Should we restore R15? (STC SGR, R15). Probably not important here.
- RTE unblocks exceptions.
- back to where we were
Now following the actual program...
startup
Code: Select all
init() > unblock > INT > init() > ???
main() might never be reached and the program would be infinitely stuck here. Suggest moving enable_intr inside main()...
main loop
This looks okay. I'd just check the handler to make sure we can come back to main().
Another issue could be that you are setting RN_BANK1 for normal code instead of RN_BANK0 when you unblock.
SR bits: 31 30 29 28 > __ MD RB BL
4 > 0 1 0 0 > Privileged+Bank0+unblock
6 > 0 1 1 0 > Privileged+Bank1+unblock
When an interrupt happens, you overwrite everything because you are already using Bank1.
At startup, KOS loads 0x500000F0 ( 0 1 0 1 ) which sets Privileged+Bank0+Block. I see KOS does an AND of 0xEFFFFF0F ( 1 1 1 0 ) in the kernel to enable interrupts which has a 1 for the Bank bit but I think this is just to preserve whatever the coder is using. This AND would still restore the CPU to Bank0 if that's what it was before the interrupt.
I don't know how IMASK works.