alvieboy

ZPUino debugger - is it possible ?

Recommended Posts

Hi all.

 

For a long time people have requested some debugging (at CPU/hardware level) for ZPUino and ZPU. Several approaches have been tried so far, but none actually was able to meet all the requirements such a system must implement.

 

Although not many, the requirements can pose some problems. Some are mandatory, and they really need to be present, and some are optional, whose implementation might not be present at all, or can be implemented in an indirect way. They are:

  • Ability to halt CPU at any point during execution (mandatory - but see note 1)
  • Ability to halt IO device clock (optional)
  • Ability to retrieve internal CPU "registers" (mandatory - only for PC [program counter] and SP [stack pointer])
  • Ability to read memory/stack (mandatory - but can be implemented indirectly, if the system has ... [see next item])
  • Ability to inject opcodes/instructions (optional)
  • Ability to single-step (mandatory - but see note 1)
  • Simple to integrate with debugger (mandatory)
  • Ability to use existing hardware in order to debug, i.e., no need to buy extra hardware (mandatory)
  • Ability to reset CPU and IO devices (mandatory)
  • Ability to change internal CPU "registers" (mandatory - only for PC and SP)
  • Ability to set software breakpoints (mandatory)
  • Ability to set hardware breakpoints (optional)
  • Ability to set memory watchpoints (optional)
  • Ability to change memory contents (mandatory)

(note 1 - ZPU uses some sequenced instructions that cannot be executed unless their order and the internal state is maintained - they are called IM (IMmediate load), and depending on the debugger architecture they might need to be all executed in sequence prior to "halting" the CPU, or somehow the debugger needs to save the so-called IM flag and restore it when CPU resumes normal execution).

 

These are roughly the requirements for such a debugger.

 

A few approaches have been tried so far, but none of them really proved to satisfy all of the mandatory requirements:

  • Internal BSCAN, debugging using JTAG already provided by FTDI. The internal debug infrastructure is still inside ZPUino 1.0 and 2.0, but the approach was found to not be ideal:
    • There's no native support on GDB to use JTAG,
    • OpenOCD proved very tricky to use a dual-layer approach (FTDI JTAG, then BSCAN JTAG on top of it)
    • Some overhead exist on HDL, cause most operations require injecting opcodes on the pipeline,
    • Injecting opcodes and freezing/single-stepping is hard to get right - ZPU Extreme core uses a 5-stage pipeline, it's far from trivial to accomplish all this w/o lots of tweaks on HDL side, which end up using a lot of FPGA resources, and also affect timing.
  • Normal JTAG debugging
    • Requires extra HW.
    • Most all of the above points still apply.

So, after thinking a bit about all this, and experimenting with some implementations I wrote during the last few days,. something came to my mind:

 

Why not let ZPU debug itself through the normal serial port?

 

Might look a bit odd, but that's what I call a Hardware-assisted Software Debugger. And this is how it is supposed to work:

 

  • Non-maskable interrupt (NMI) support is added to the System Controller. This interrupt is propagated even when interrupts are disabled.
  • Halting the ZPU core is done by issuing a specially crafted sequence of bytes at a very unusual baud rate. This sequence can trigger an NMI to ZPU, which then triggers a "breakpoint" instruction (instead of a normal interrupt).
  • The "breakpoint" instruction is modified so that it behaves like an interrupt, jumping to a known and specially crafted memory area in the bootloader code.
  • The bootloader code which is responsible for handing the breakpoint uses the serial port to read commands, and these commands can modify the code flow, and read all of the relevant data, and this can fulfill most of the mandatory requirements.

This requires minor modifications on HDL, and there's still some room on the bootloader to implement the functionality.

 

If GCC plays well with debugging (I will need to write a small gdbserver for it), then I think it can become the de-facto debugger for ZPUino.

 

Let me know your ideas, comments, and suggestions.

 

Alvie

Share this post


Link to post
Share on other sites

Sort of, yes. Let's say that it's a "trap" handler that can be invoked by hardware, by "soft" breakpoints, and perhaps in the future even by hardware breakpoints and watchpoints.

 

If this proves stable I may consider backporting it to ZPU 1.0 also.

Share this post


Link to post
Share on other sites

A simple handler that shows the "exception" (GHDL simulation). This was done by injecting a soft breakpoint at a specific program address:

Handler called, sp 0x80001fd4 at PC 0x000007b7Stack dump:80001fd8: 0a00000080001fdc: 0000002c80001fe0: ffffffff80001fe4: 00000000Code: 80 84 0c 80 f2 71 0c *00 

Here's the disassembly of that relevant part:

 7b3:   80              im 0 7b4:   f2              im -14 7b5:   71              loadsp 4 7b6:   0c              store 7b7:   00              breakpoint /* Here's the soft breakpoint instruction */ 7b8:   8a              im 10 7b9:   a7              im 39 7ba:   2d              call

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now