[Oberon] Debugging FPGA oberon via serial line?
schierlm at gmx.de
Sun Jan 27 00:20:59 CET 2019
while I was adding UTF-8 support to Fonts and Texts (and almost
rewriting Fonts so that a font can be loaded partially and not all
glyphs at once), I noticed that debugging such a system can be
cumbersome (as you cannot read the TRAP output any more, as well as you
have to reset the system to a previous state to be able to fix your
mistakes if the screen is too garbled to be useful, or if the system
TRAPs during boot).
By the way, here is Oberon running in the browser with UTF-8 support for
Texts (and Tahoma font):
>From other (older) systems, I know it is possible to debug them via
serial line, so I was thinking how much the FPGA oberon system needs to
be changed (hardware side/software side) to accommodate this. RS232 is
supported, so you could use one FPGA system (or emulator) to debug the
other one. And I was wondering if anybody already tried doing something
I know that Colby Russell worked on debug support in the emulator, but
no idea about how far he got.
A minimal feature set to be useful (in my opinion) would be
- Read and write memory and disk via serial port while the system is
running/idle (already possible today via ORC / PCLink)
- Set and remove software breakpoints while the system is running/idle
- When software breakpoint or trap is hit, save processor state and
allow debugging via serial port (-> suspended)
- Read and write registers and memory while the system is suspended
- Set and remove software breakpoints while the system is suspended
- Continue execution when the system is suspended
More advanced features would be single stepping (can be emulated by
having a look at the instruction and setting software breakpoints at all
following locations), or memory breakpoints. Also to be able to enter
the debugger by pressing a hardware button on the FPGA (similar to the
current reset functionality, but not resetting). And of course symbolic
Software breakpoints should be easy, just replace instruction by BL to a
fixed address. Restore the instruction before returning. For catching
TRAPs, overwrite the TRAP address.
Saving processor state might be tricky, especially SYSTEM.H and the
flags, and maybe you have problems since you need at least one spare
register to be able to save the registers to a fixed location in memory.
You will also need to switch stack to a second stack before the stack is
accessed by the code. Probably solvable by using a special compiler that
leaves a register or two unused. Restoring SYSTEM.H and Flags is also
not supported (except by searching for instructions that will result in
the desired flags or results). Also the question is whether returning to
the code will not destroy some flags again. And you need to make sure
not to set breakpoints or break at points where a BL has happened but
the link register has not been saved yet. So (similar to interrupt)
probably some hardware support is needed for this. Entering the debugger
by button also needs hardware support (since the current Reset button
forgets the PC and some other state).
Once in suspend mode, it might be hard to avoid allocating memory, since
you cannot run the GC which might collect objects that are still used by
the suspended program. But that should be feasible if the functions are
basic enough to work with a fixed buffer (e.g. number of breakpoints is
I guess memory breakpoints are only possible with hardware support for
them (I have no idea how to emulate them except emulating or setting
breakpoints at all LOAD/STORE instructions).
For symbolic debugging, the compiler would have to write some more debug
symbols. For a start,
annotates the code position for every instruction; I currently use it
for creating combined source/assembly listings like
But you would probably also need some information about the stack layout
(variable names and types) and register contents for every code
locatoin, as well as information about module/global variables, and
not-exported record types and record members.
And you would also need some client to utilize all this information so
that you can do something like "Debugger.Inspect F.vwr.dsc" :)
So I guess for my own needs, that's too much work for the benefit
(especially since I don't know if I will ever try to rewrite any of the
core modules again). But perhaps I'm missing something? Any better ideas?
More information about the Oberon