| |||
Home > Debug > Using the debug functionality > Debug communications channel |
There are two ways that an external debugger can send data to or receive data from the processor:
The debug communications channel, when the processor is not in debug state. It is defined as the set of resources used for communicating between the external debugger and software running on the processor.
The mechanism for forcing the processor to execute ARM instructions, when the processor is in debug state. For more information, see Executing instructions in debug state.
At the processor side, the debug communications channel resources are:
CP14 Debug Register c5 (DTR, comprising DBGDTRTXint and DBGDTRRXint)
CP14 Debug Register c1 (DBGDSCRint).
The ARMv7 debug architecture is implemented on the processor so that:
If a read of the DBGDSCRint
returns 1 for the RXfull flag, a following read of the DBGDTRRXint
returns valid data and RXfull is cleared. No ISB
is
required between these two CP14 instructions.
If a read of the CP14 DBGDSCRint returns 1 for the TXfull flag, a following write to the DBGDTRTXext is Unpredictable.
If a read of the CP14 DBGDSCRint returns 0 for the RXfull flag, a following read of the CP14 DTR returns an Unpredictable value.
If a read of the CP14 DBGDSCRint returns 0 for the
TXfull flag, a following write to the CP14 DTR writes the intended
32-bit word, and sets TXfull to 1. No ISB
is required between
these two CP14 instructions.
When Nonblocking mode is selected for DTR accesses, the following conditions are true for memory-mapped DBGDSCR, DBGDTRRXext, and DBGDTRTXext registers:
If a read of the DBGDSCRext returns 0 for the TXfull flag, a following read of the memory-mapped DBGDTRTX is ignored. The content of TXfull is unchanged and the read returns an UNKNOWN value.
If a read of the DBGDSCRext returns 0 for the RXfull flag, a following write of the memory-mapped DBGDTRRX passes valid data to the processor and sets RXfull to 1.
If a read of the DBGDSCRext returns 1 for the TXfull flag, a following read of the DBGDTRTXext returns valid data and clears TXfull.
If a read of the DBGDSCRext returns 1 for the RXfull flag, a following write of the memory-mapped DBGDTRRXext is ignored, that is, both RXfull and DBGDTRRX contents are unchanged.
Software running on the processor that sends data to the debugger through the target-to-host channel can use the sequence of instructions that Example 12.2 shows.
Example 12.2. Target to host data transfer (target end)
; r0 -> word to send to the debugger
WriteDCC MRC p14, 0, PC, c0, c1, 0
BEQ WriteDCC
MCR p14, 0, Rd, c0, c5, 0
BX lr
Example 12.3 shows the sequence of instructions for sending data to the debugger through the host-to-target channel.
Example 12.3. Host to target data transfer (target end)
; r0 -> word sent by the debugger
ReadDCC MRC p14, 0, PC, c0, c1, 0
BCC ReadDCC
MRC p14, 0, Rd, c0, c5, 0
BX lr
A debugger can access the DCC through the external interface. The following examples show the pseudo-code operations for these accesses.
Example 12.4 shows the code for target-to-host data transfer.
Example 12.4. Target to host data transfer (host end)
uint32 ReadDCC()
{
// Step 1. Poll DBGDSCR until TXfull is set to 1.
repeat
{
dbgdscr := ReadDebugRegister(34);
}
until (dbgdscr & (1<<29));
// Step 2. Read the value from DBGDTRTX.
dtr_val := ReadDebugRegister(35);
return dtr_val;
}
Example 12.5 shows the code for host-to-target data transfer.
Example 12.5. Host to target data transfer (host end)
WriteDCC(uint32 dtr_val)
{
// Step 1. Poll DBGDSCR until RXfull is clear.
repeat
{
dbgdscr := ReadDebugRegister(34);
}
until (!(dbgdscr & (1<<30)));
// Step 2. Write the value to DBGDTRRX.
WriteDebugRegister(32, dtr_val);
}
While the processor is running, if the DCC is used as a data channel, it might be appropriate to poll the DCC regularly.
Example 12.6 shows the code for polling the DCC.
Example 12.6. Polling the DCC (host end)
PollDCC
{
dbgdscr := ReadDebugRegister(34);
if (dbgdscr & (1<<29))
{
// DBGDTRTX (target -> host transfer register) full
dtr := ReadDebugRegister(35)
ProcessTargetToHostWord(dtr);
}
if (!(dbgdscr & (1<<30)))
{
// DBGDTRRX (host -> target transfer register) empty
dtr := GetNextHostToTargetWord()
WriteDebugRegister(32, dtr);
}
}