DCC or debug communication channel is a quick way to get debug output from a program running on a target device to the JTAG host device.  Unfortunately I found that the cortex-m3 doesn’t exactly have a DCC.

What it does have however is a general purpose data register (DCRDR) that gets used by the debugger for reading/writing registers, etc, etc, and  while there is no specification from ARM as to how to use it to accomplish something like DCC, it is possible and there’s already basic support for it in OpenOCD.

I ran into problems, however, getting all of my characters output.  It looks to me as if OpenOCD has a clever way of making the most out of the 32bit DCC register that makes use of all of the bits instead of just the lower 8 which is needed for basic single character DCC output.   For cortex-m3/DCRDR, it is necessary to use at least one bit for signalling between the target / host, so the OpenOCD code attempts to read 4 consecutive writes to build up a 32bit value.  One day, I may fully understand the 32bit format for the data and want to use it, but I’d like to have the simple single character output as well, so I made the following change to cortex_m3.c in the function cortex_m3_handle_target_request:


cortex_m3_dcc_read(swjdp, &data, &ctrl);


/* check if we have single char data */
if (ctrl & (1 << 1))
{
uint32_t request;


/* during this poll cycle read as much as we can from target */
while (ctrl & (1<<1))
{
request = data;
target_request(target, request);
cortex_m3_dcc_read(swjdp, &data, &ctrl);
}
}
else
if (ctrl & (1 << 0))

Then I’m using this code on the stm32:

volatile uint32_t *DCRDR = 0xe000edf8;

void DCC_write_byte(char cbyte)
{

static uint32_t waitCount = 0;

/* wait for host to read & clear value or timeout */
while (((*DCRDR)&0x1)&&(++waitCount<100000))
{
asm("nop");
}

/* only reset the timeout if the value was read,
otherwise next time will immediately timeout (no host connected) */
if (((*DCRDR)&0x1)==0)
waitCount=0;

*DCRDR=(cbyte<<8)|3;
}

And this command to the rebuilt OpenOCD:

/usr/local/bin/openocd -d0 -f /usr/local/share/openocd/scripts/interface/vsllink-swd.cfg -f /usr/local/share/openocd/scripts/target/stm32vl.cfg -c init -c targets -c "target_request debugmsgs charmsg"

I don’t plan on submitting this to OpenOCD at this time since I’m using the version built from a script in the previous post, anxiously awaiting SWD support in a future release.