commit 377df4c3326727764f7401b94db4da8fd97deab1
parent 92a86ad93f305238ce2f4b98f08e0f0e74265e40
Author: Brian Swetland <swetland@frotz.net>
Date: Tue, 4 Aug 2015 18:00:17 -0700
debugger: initial plumbing for SWO
Diffstat:
6 files changed, 82 insertions(+), 17 deletions(-)
diff --git a/include/protocol/rswdp.h b/include/protocol/rswdp.h
@@ -56,10 +56,12 @@
#define CMD_TRACE 0x08 /* op=tracebits n=0 */
#define CMD_BOOTLOADER 0x09 /* return to bootloader for reflashing */
#define CMD_SET_CLOCK 0x0A /* set SWCLK rate to n khz */
+#define CMD_SWO_CLOCK 0x0B /* set SWOCLK rate to n khz, 0 = disable SWO */
/* valid: target to host */
#define CMD_STATUS 0x10 /* op=errorcode, arg=commands since last TXN_START */
#define CMD_SWD_DATA 0x11 /* op=0 arg=count, payload: data x count */
+#define CMD_SWO_DATA 0x12 /* op=0 arg=count, payload: count * 4 bytes */
/* valid: target to host async */
#define CMD_DEBUG_PRINT 0x20 /* arg*4 bytes of ascii debug output */
diff --git a/tools/debugger-commands.c b/tools/debugger-commands.c
@@ -409,6 +409,12 @@ int do_setclock(int argc, param *argv) {
return swdp_set_clock(argv[0].n);
}
+int do_swoclock(int argc, param *argv) {
+ if (argc < 1)
+ return -1;
+ return swo_set_clock(argv[0].n);
+}
+
int do_help(int argc, param *argv) {
struct debugger_command *cmd;
for (cmd = debugger_commands; cmd->func != NULL; cmd++) {
@@ -836,7 +842,8 @@ struct debugger_command debugger_commands[] = {
{ "print", "", do_print, "print numeric arguments" },
{ "echo", "", do_echo, "echo command line" },
{ "bootloader", "", do_bootloader, "reboot into bootloader" },
- { "setclock", "", do_setclock, "set clock rate (khz)" },
+ { "setclock", "", do_setclock, "set SWD clock rate (khz)" },
+ { "swoclock", "", do_swoclock, "set SWO clock rate (khz)" },
{ "arch", "", do_setarch, "set architecture for flash agent" },
{ "threads", "", do_threads, "thread dump" },
{ "text", "", do_text, "dump text" },
diff --git a/tools/module.mk b/tools/module.mk
@@ -10,6 +10,7 @@ M_OBJS += tools/usb.o
M_OBJS += tools/socket.o
M_OBJS += tools/gdb-bridge.o
M_OBJS += tools/lkdebug.o
+M_OBJS += tools/swo.o
M_OBJS += out/debugger-builtins.o
$(call build-host-executable)
diff --git a/tools/rswdp.c b/tools/rswdp.c
@@ -89,18 +89,18 @@ struct txn {
unsigned magic;
};
+void process_swo_data(void *data, unsigned count);
+
static void process_async(u32 *data, unsigned count) {
unsigned msg, n;
u32 tmp;
-
while (count-- > 0) {
msg = *data++;
switch (RSWD_MSG_CMD(msg)) {
case CMD_NULL:
continue;
case CMD_DEBUG_PRINT:
- //op = RSWD_MSG_OP(msg);
- n = RSWD_MSG_ARG(msg);
+ n = RSWD_MSG_ARG(msg);
if (n > count)
return;
tmp = data[n];
@@ -110,6 +110,13 @@ static void process_async(u32 *data, unsigned count) {
data += n;
count -= n;
break;
+ case CMD_SWO_DATA:
+ n = RSWD_MSG_ARG(msg);
+ if (n > count)
+ return;
+ process_swo_data(data, n * 4);
+ data += n;
+ count -= n;
default:
return;
}
@@ -312,19 +319,17 @@ restart:
query_id = 0;
process_query(data + 1, (r / 4) - 1);
swd_online = 1;
- } else if (swd_txn_status == TXN_STATUS_WAIT) {
- if (data[0] == swd_txn_id) {
- swd_txn_status = r;
- memcpy(swd_txn_data, data, r);
- pthread_cond_broadcast(&swd_event);
- } else if (data[0] == RSWD_TXN_ASYNC) {
- pthread_mutex_unlock(&swd_lock);
- process_async(data + 1, (r / 4) - 1);
- pthread_mutex_lock(&swd_lock);
- } else {
- xprintf(XSWD, "usb: rx: unexpected txn %08x (%d)\n",
- data[0], r);
- }
+ } else if (data[0] == RSWD_TXN_ASYNC) {
+ pthread_mutex_unlock(&swd_lock);
+ process_async(data + 1, (r / 4) - 1);
+ pthread_mutex_lock(&swd_lock);
+ } else if ((swd_txn_status == TXN_STATUS_WAIT) &&
+ (data[0] == swd_txn_id)) {
+ swd_txn_status = r;
+ memcpy(swd_txn_data, data, r);
+ pthread_cond_broadcast(&swd_event);
+ } else {
+ xprintf(XSWD, "usb: rx: unexpected txn %08x (%d)\n", data[0], r);
}
}
// wait for a reader to ack the shutdown (and close usb)
@@ -793,6 +798,17 @@ int swdp_set_clock(unsigned khz) {
return q_exec(&t);
}
+int swo_set_clock(unsigned khz) {
+ struct txn t;
+ if (khz > 0xFFFF)
+ return -1;
+ if (khz < 1000)
+ khz = 1000;
+ q_init(&t);
+ t.tx[t.txc++] = RSWD_MSG(CMD_SWO_CLOCK, 0, khz);
+ return q_exec(&t);
+}
+
int swdp_open(void) {
pthread_create(&swd_thread, NULL, swd_reader, NULL);
return 0;
diff --git a/tools/rswdp.h b/tools/rswdp.h
@@ -62,6 +62,7 @@ void swdp_target_reset(int enable);
int swdp_bootloader(void);
int swdp_set_clock(unsigned khz);
+int swo_set_clock(unsigned khz);
#endif
diff --git a/tools/swo.c b/tools/swo.c
@@ -0,0 +1,38 @@
+/* swo.c
+ *
+ * Copyright 2015 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <pthread.h>
+#include <fw/types.h>
+#include <debugger.h>
+
+void process_swo_data(void *_data, unsigned count) {
+ unsigned char *data = _data;
+ char buf[8192];
+ char *p = buf;
+ while (count-- > 0) {
+ p += sprintf(p, "%02x ", *data++);
+ }
+ *p++ = '\n';
+ *p++ = 0;
+ xprintf(XDATA, buf);
+}
+