The public interface to the GdbServerSC
class
is its constructor and destructor. The constructor arguments include
the start and end address of Flash memory, the port on which RSP
TCP/IP connections will be accepted and a pointer to the JTAG
FIFO for TAP actions.
The constructor instantiates a new instance of
RspConnection
to handle the RSP TCP/IP
interface (see Section 4.2) and a new
instance of DebugUnitSC
to model the interface
to the OpenRISC 1000 Debug Unit and drive the JTAG interface (see Section 4.3). It creates an instance of
RspPacket
to hold the data associated with
the packet currently in use.
The GDB server needs to keep track of breakpoints and watchpoints
(collectively known as matchpoints) which have been
inserted. These use OpenRISC 1000 l.trap
instructions. Class MpHash
holds details of
each matchpoint: its type, address and the instruction that was
replaced by l.trap
. The
GdbServerSC
constructor creates an instance
of this class.
Finally the constructor declares the private function
rspServer
as a new SystemC THREAD.
On start up, the OpenRISC 1000 model loads an image from Flash memory which initializes the exception vectors in RAM, sets up any caches and then jumps to the reset vector (location 0x100). GDB debugging should not start until this initialization has occurred.
This is achieved by detecting when the processor first tries to access a location outside Flash memory (hence the need for this addresses to be passed to the constructor). At start up, the thread resets the JTAG interface of the Debug Unit, then waits until the next program counter has a value outside the flash memory address range.
This is followed by the main loop. The first part of the loop checks if a connection to a GDB client has been established, and if not loops trying to listen. When a new connection is established it immediately stalls the processor, pending instructions from the client.
The second part of the loop waits until the processor has stalled
(it will already be stalled on first connection). Once it has
stalled it notifies the GDB client, then processes the next
RSP packet from the client using the function
rspClientRequest
. The majority of packets
will leave the CPU unstalled, so subsequent moves round the loop
will immediately come back to the same point and call
rspClientRequest
again.
The exceptions are continue, step and restart packets which unstall the processor. There will be no further RSP packets processed until the processor stalls again. This will either be due to hitting a breakpoint or the connection being dropped and reconnected.
Note | |
---|---|
This loop relies on detecting a stalled processor (using the
variable |
The processing of individual packets by
rspClientRequest
follows the same approach
described in Embecosm Application Note 4 Howto: GDB
Remote Serial Protocol: Writing a RSP Server [8]. The only difference is the code is in
C++ rather than C. The details of individual packet actions are
not described further in this application note. All the actions
use reading and writing of SPRs and memory in the same
way. However for this application they use the functions provided
by the Debug Unit class, DebugUnitSC
.