summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/Makefile.am8
-rw-r--r--src/transport/swd.c93
-rw-r--r--src/transport/swd.h18
-rw-r--r--src/transport/swd_libswd_drv_openocd.c65
4 files changed, 126 insertions, 58 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 123687bd..b080ae85 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -1,13 +1,15 @@
include $(top_srcdir)/common.mk
-#METASOURCES = AUTO
+METASOURCES = AUTO
noinst_LTLIBRARIES = libtransport.la
libtransport_la_SOURCES = \
transport.c \
- swd.c
+ swd.c \
+ swd_libswd_drv_openocd.c
noinst_HEADERS = \
transport.h \
- swd.h
+ swd.h \
+ swd_libswd_drv_openocd.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/transport/swd.c b/src/transport/swd.c
index 16ee41a8..85014cad 100644
--- a/src/transport/swd.c
+++ b/src/transport/swd.c
@@ -3,7 +3,8 @@
*
* SWD Transport Body File for OpenOCD.
*
- * Copyright (C) 2010-2011, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
+ * Copyright (C) 2011 Tomasz Boleslaw CEDRO
+ * cederom@tlen.pl, http://www.tomek.cedro.info
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,20 +47,17 @@
#endif
#include <transport/swd.h>
-#include <target/arm_adi_v5.h>
#include <jtag/interface.h> //we want this here to use extern global *interface
-#include <transport/transport.h>
+#include <unistd.h>
///Unfortunalety OpenOCD use globals to pass information so we need to use it too.
extern struct jtag_interface *jtag_interface;
-extern const struct dap_ops swd_dp_ops;
-static struct transport swd_transport;
/** @{ swd_arm_adi_v5 Function set to support existing ARM ADI v5 target's
* infrastructure.
*/
-int swd_queue_idcode_read(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data){
+int oocd_swd_queue_idcode_read(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data){
int retval;
retval=swd_dp_read_idcode(dap->ctx, SWD_OPERATION_ENQUEUE, (int **)&data);
if (retval<0) {
@@ -68,7 +66,7 @@ int swd_queue_idcode_read(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data){
} else return ERROR_OK;
}
-int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
+int oocd_swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
int retval;
retval=swd_dp_read((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, reg, (int **)&data);
if (retval<0){
@@ -78,7 +76,7 @@ int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
return ERROR_OK;
}
-int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
+int oocd_swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
int retval;
retval=swd_dp_write((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int *) &data);
if (retval<0){
@@ -88,7 +86,7 @@ int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
return ERROR_OK;
}
-int swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
+int oocd_swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
int retval;
retval=swd_ap_read((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int **) &data);
if (retval<0){
@@ -98,7 +96,7 @@ int swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
return ERROR_OK;
}
-int swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
+int oocd_swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
int retval;
retval=swd_ap_write((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int *) &data);
if (retval<0){
@@ -108,14 +106,14 @@ int swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
return ERROR_OK;
}
-int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack){
+int oocd_swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack){
//int retval;
//char reg=SWD_DP_ABORT_ADDR;
LOG_ERROR("not yet implemented");
return ERROR_FAIL;
}
-int swd_run(struct adiv5_dap *dap){
+int oocd_swd_run(struct adiv5_dap *dap){
int retval;
retval=swd_cmdq_flush((swd_ctx_t *)dap->ctx, SWD_OPERATION_EXECUTE);
if (retval<0){
@@ -124,23 +122,11 @@ int swd_run(struct adiv5_dap *dap){
} else return ERROR_OK;
}
-const struct dap_ops swd_dap_ops = {
- .is_swd = true,
-
- .queue_idcode_read = swd_queue_idcode_read,
- .queue_dp_read = swd_queue_dp_read,
- .queue_dp_write = swd_queue_dp_write,
- .queue_ap_read = swd_queue_ap_read,
- .queue_ap_write = swd_queue_ap_write,
- .queue_ap_abort = swd_queue_ap_abort,
- .run = swd_run,
-};
-
// Transport select prepares selected transport for later use and bus/target initialization.
// TODO: We are operating on global interface pointer, change it into function parameter asap.
-int swd_transport_init(struct command_context *ctx){
- LOG_DEBUG("%s",__func__);
+int oocd_swd_transport_init(struct command_context *ctx){
+ LOG_DEBUG("entering function...");
int retval, *idcode;
//struct target *target = get_current_target(ctx);
@@ -165,14 +151,16 @@ int swd_transport_init(struct command_context *ctx){
/**
* Select SWD transport on interface pointed by global *jtag_interface structure.
* Select is assumed to be called before transport init. It prepares everything,
- * including interface buffers, context memory and command set for higher layers,
- * but does not interrogate target device (with IDCODE read).
+ * including context memory and command set for higher layers, but not hardware
+ * and does not interrogate target device (with IDCODE read that is done by
+ * transport init call). This function does not touch the hardware because
+ * hardware use signals that are not yet read from config file at this point!
*/
-int swd_transport_select(struct command_context *ctx){
- LOG_DEBUG("%s",__func__);
+int oocd_swd_transport_select(struct command_context *ctx){
+ LOG_DEBUG("entering function...");
int retval;
- jtag_interface->transport=&swd_transport;
+ jtag_interface->transport=(struct transport *)&oocd_transport_swd;
//struct target *target = get_current_target(ctx);
// retval = register_commands(ctx, NULL, swd_handlers);
@@ -184,34 +172,47 @@ int swd_transport_select(struct command_context *ctx){
LOG_ERROR("Cannot initialize SWD context!");
return ERROR_FAIL;
}
- LOG_INFO("New SWD context initialized at 0x%08X", (int)&jtag_interface->transport->ctx);
+ LOG_INFO("New SWD context initialized at 0x%08X", (int)jtag_interface->transport->ctx);
} else LOG_INFO("Working on existing transport context at 0x%0X...", (int)&jtag_interface->transport->ctx);
- // Select SWD DAP by sending JTAG-TO-SWD sequence on the transport layer
- retval=swd_dap_select((swd_ctx_t *)jtag_interface->transport->ctx, SWD_OPERATION_EXECUTE);
- if (retval<0) {
- LOG_ERROR("swd_dap_select() error: %s", swd_error_string(retval));
+ retval=swd_log_level_inherit(jtag_interface->transport->ctx, debug_level);
+ if (retval<0){
+ LOG_ERROR("Unable to set log level: %s", swd_error_string(retval));
return ERROR_FAIL;
}
-
LOG_DEBUG("SWD Transport selection complete...");
return ERROR_OK;
}
-
-static struct transport swd_transport = {
+struct transport oocd_transport_swd = {
.name = "swd",
- .select = swd_transport_select,
- .init = swd_transport_init,
+ .select = oocd_swd_transport_select,
+ .init = oocd_swd_transport_init,
.ctx = NULL,
- .next = NULL
+ .next = NULL,
};
+const struct dap_ops oocd_dap_ops_swd = {
+ .is_swd = true,
+
+ .queue_idcode_read = oocd_swd_queue_idcode_read,
+ .queue_dp_read = oocd_swd_queue_dp_read,
+ .queue_dp_write = oocd_swd_queue_dp_write,
+ .queue_ap_read = oocd_swd_queue_ap_read,
+ .queue_ap_write = oocd_swd_queue_ap_write,
+ .queue_ap_abort = oocd_swd_queue_ap_abort,
+ .run = oocd_swd_run,
+};
+
+
+
+
+/** Register SWD Transport at program startup. */
static void swd_constructor(void) __attribute__((constructor));
static void swd_constructor(void)
{
- transport_register(&swd_transport);
+ transport_register((struct transport *)&oocd_transport_swd);
}
/** Returns true if the current debug session
@@ -219,7 +220,7 @@ static void swd_constructor(void)
*/
bool transport_is_swd(void)
{
- return get_current_transport() == &swd_transport;
+ return get_current_transport() == &oocd_transport_swd;
}
/** Returns true if the current debug session
@@ -227,7 +228,7 @@ bool transport_is_swd(void)
* */
//bool transport_is_swd(void)
//{
-// return get_current_transport() == &swd_transport;
+// return get_current_transport() == &oocd_transport_swd;
//}
@@ -299,7 +300,7 @@ int dap_to_swd(struct target *target)
retval = jtag_execute_queue();
/* set up the DAP's ops vector for SWD mode. */
- arm->dap->ops = &swd_dap_ops;
+ arm->dap->ops = &oocd_dap_ops_swd;
return retval;
}
diff --git a/src/transport/swd.h b/src/transport/swd.h
index 4d7edc2a..cd908169 100644
--- a/src/transport/swd.h
+++ b/src/transport/swd.h
@@ -3,7 +3,8 @@
*
* SWD Transport Header File for OpenOCD.
*
- * Copyright (C) 2010-2011, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
+ * Copyright (C) 2011 Tomasz Boleslaw CEDRO
+ * cederom@tle.pl, http://www.tomek.cedro.info
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,4 +37,19 @@
/** \file swd.h SWD Transport Header File for OpenOCD. */
#include <libswd.h>
+#include <transport/transport.h>
+#include <target/arm_adi_v5.h>
+
+int oocd_swd_queue_idcode_read(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data);
+int oocd_swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data);
+int oocd_swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data);
+int oocd_swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data);
+int oocd_swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data);
+int oocd_swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack);
+int oocd_swd_run(struct adiv5_dap *dap);
+int oocd_swd_transport_init(struct command_context *ctx);
+int oocd_swd_transport_select(struct command_context *ctx);
+
+extern struct transport oocd_transport_swd;
+extern const struct dap_ops oocd_dap_ops_swd;
diff --git a/src/transport/swd_libswd_drv_openocd.c b/src/transport/swd_libswd_drv_openocd.c
index 19c8f9c8..c503a9a2 100644
--- a/src/transport/swd_libswd_drv_openocd.c
+++ b/src/transport/swd_libswd_drv_openocd.c
@@ -3,7 +3,8 @@
*
* Driver Bridge between LibSWD and OpenOCD.
*
- * Copyright (C) 2010-2011, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
+ * Copyright (C) 2010-2011 Tomasz Boleslaw CEDRO
+ * cederom@tlen.pl, http://www.tomek.cedro.info
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,7 @@
#include <helper/log.h>
#include <jtag/interface.h>
#include <helper/log.h>
+#include <helper/command.h>
/** OpenOCD as for now use global pointer to driver structure. */
extern struct jtag_interface *jtag_interface;
@@ -56,6 +58,7 @@ extern struct jtag_interface *jtag_interface;
* \return data count transferred, or negative SWD_ERROR code on failure.
*/
int swd_drv_mosi_8(swd_ctx_t *swdctx, swd_cmd_t *cmd, char *data, int bits, int nLSBfirst){
+ LOG_DEBUG("OpenOCD's swd_drv_mosi_8(swdctx=@0x%08X, cmd=@0x%08X, data=0x%08X, bits=%d, nLSBfirst=0x%02X)", (int)swdctx, (int)cmd, *data, bits, nLSBfirst);
if (data==NULL) return SWD_ERROR_NULLPOINTER;
if (bits<0 && bits>8) return SWD_ERROR_PARAM;
if (nLSBfirst!=0 && nLSBfirst!=1) return SWD_ERROR_PARAM;
@@ -67,7 +70,7 @@ int swd_drv_mosi_8(swd_ctx_t *swdctx, swd_cmd_t *cmd, char *data, int bits, int
/* Split output data into char array. */
for (i=0;i<8;i++) mosidata[(nLSBfirst==SWD_DIR_LSBFIRST)?(i):(7-i)]=((1<<i)&(*data))?1:0;
/* Then send that array into interface hardware. */
- res=jtag_interface->transfer(NULL, bits, mosidata, misodata);
+ res=jtag_interface->transfer(NULL, bits, mosidata, misodata, 0);
if (res<0) return SWD_ERROR_DRIVER;
return i;
@@ -84,6 +87,7 @@ int swd_drv_mosi_8(swd_ctx_t *swdctx, swd_cmd_t *cmd, char *data, int bits, int
* \return data count transferred, or negative SWD_ERROR code on failure.
*/
int swd_drv_mosi_32(swd_ctx_t *swdctx, swd_cmd_t *cmd, int *data, int bits, int nLSBfirst){
+ LOG_DEBUG("OpenOCD's swd_drv_mosi_32(swdctx=@0x%08X, cmd=@0x%02X, data=0x%08X, bits=%d, nLSBfirst=0x%02X)", (int)swdctx, (int)cmd, *data, bits, nLSBfirst);
if (data==NULL) return SWD_ERROR_NULLPOINTER;
if (bits<0 && bits>8) return SWD_ERROR_PARAM;
if (nLSBfirst!=0 && nLSBfirst!=1) return SWD_ERROR_PARAM;
@@ -94,7 +98,7 @@ int swd_drv_mosi_32(swd_ctx_t *swdctx, swd_cmd_t *cmd, int *data, int bits, int
//UrJTAG drivers shift data LSB-First.
for (i=0;i<32;i++) mosidata[(nLSBfirst==SWD_DIR_LSBFIRST)?(i):(31-i)]=((1<<i)&(*data))?1:0;
- res=jtag_interface->transfer(NULL, bits, mosidata, misodata);
+ res=jtag_interface->transfer(NULL, bits, mosidata, misodata, 0);
if (res<0) return SWD_ERROR_DRIVER;
return i;
}
@@ -118,11 +122,13 @@ int swd_drv_miso_8(swd_ctx_t *swdctx, swd_cmd_t *cmd, char *data, int bits, int
static signed int res;
static char misodata[8], mosidata[8];
- res=jtag_interface->transfer(NULL, bits, mosidata, misodata);
+ // This function sends and reveice MSb-first.
+ res=jtag_interface->transfer(NULL, bits, mosidata, misodata, 0);
if (res<0) return SWD_ERROR_DRIVER;
/* Now we need to reconstruct the data byte from shifted in LSBfirst byte array. */
*data=0;
for (i=0;i<bits;i++) *data|=(misodata[(nLSBfirst==SWD_DIR_LSBFIRST)?(bits-1-i):(i)]?(1<<i):0);
+ LOG_DEBUG("OpenOCD's swd_drv_miso_8(swdctx=@0x%08X, cmd=@0x%08X, data=@0x%08X, bits=%d, nLSBfirst=0x%02X) reads: 0x%08X", (int)swdctx, (int)cmd, (int)data, bits, nLSBfirst, *data);
return i;
}
@@ -145,11 +151,13 @@ int swd_drv_miso_32(swd_ctx_t *swdctx, swd_cmd_t *cmd, int *data, int bits, int
static signed int res;
static char misodata[32], mosidata[32];
- res=jtag_interface->transfer(NULL, bits, mosidata, misodata);
+ res=jtag_interface->transfer(NULL, bits, mosidata, misodata, 0);
if (res<0) return SWD_ERROR_DRIVER;
/* Now we need to reconstruct the data byte from shifted in LSBfirst byte array. */
*data=0;
for (i=0;i<bits;i++) *data|=(misodata[(nLSBfirst==SWD_DIR_LSBFIRST)?(bits-1-i):(i)]?(1<<i):0);
+ LOG_DEBUG("OpenOCD's swd_drv_miso_32(swdctx=@0x%08X, cmd=@0x%02X, data=@0x08%X, bits=%d, nLSBfirst=0x%02X) reads: 0x%08X", (int)swdctx, (int)cmd, (int)data, bits, nLSBfirst, *data);
+ LOG_DEBUG("OpenOCD's swd_drv_miso_32() reads: 0x%08X\n", *data);
return i;
}
@@ -163,6 +171,7 @@ int swd_drv_miso_32(swd_ctx_t *swdctx, swd_cmd_t *cmd, int *data, int bits, int
* \return number of bits transmitted or negative SWD_ERROR code on failure.
*/
int swd_drv_mosi_trn(swd_ctx_t *swdctx, int bits){
+ LOG_DEBUG("OpenOCD's swd_drv_mosi_trn(swdctx=@0x%08X, bits=%d)\n", (int)swdctx, bits);
if (bits<SWD_TURNROUND_MIN_VAL && bits>SWD_TURNROUND_MAX_VAL)
return SWD_ERROR_TURNAROUND;
@@ -173,7 +182,7 @@ int swd_drv_mosi_trn(swd_ctx_t *swdctx, int bits){
if (res<0) return SWD_ERROR_DRIVER;
/* Clock specified number of bits for proper TRN transaction. */
- res=jtag_interface->transfer(NULL, bits, buf, buf);
+ res=jtag_interface->transfer(NULL, bits, buf, buf, 0);
if (res<0) return SWD_ERROR_DRIVER;
return bits;
@@ -189,6 +198,7 @@ int swd_drv_mosi_trn(swd_ctx_t *swdctx, int bits){
* \return number of bits transmitted or negative SWD_ERROR code on failure.
*/
int swd_drv_miso_trn(swd_ctx_t *swdctx, int bits){
+ LOG_DEBUG("OpenOCD's swd_drv_miso_trn(swdctx=@0x%08X, bits=%d)\n", (int)swdctx, bits);
if (bits<SWD_TURNROUND_MIN_VAL && bits>SWD_TURNROUND_MAX_VAL)
return SWD_ERROR_TURNAROUND;
@@ -196,11 +206,11 @@ int swd_drv_miso_trn(swd_ctx_t *swdctx, int bits){
static char buf[SWD_TURNROUND_MAX_VAL];
/* Use driver method to set high (read) signal named RnW. */
- res=jtag_interface->bitbang(NULL, "RnW", 0, &val);
+ res=jtag_interface->bitbang(NULL, "RnW", 0xFFFFFFFF, &val);
if (res<0) return SWD_ERROR_DRIVER;
/* Clock specified number of bits for proper TRN transaction. */
- res=jtag_interface->transfer(NULL, bits, buf, buf);
+ res=jtag_interface->transfer(NULL, bits, buf, buf, 0);
if (res<0) return SWD_ERROR_DRIVER;
return bits;
@@ -215,6 +225,7 @@ int swd_drv_miso_trn(swd_ctx_t *swdctx, int bits){
* \return SWD_OK on success, negative SWD_ERROR code on failure.
*/
int swd_log_level_inherit(swd_ctx_t *swdctx, int loglevel){
+ LOG_DEBUG("OpenOCD's swd_log_level_inherit(swdctx=@0x%08X, loglevel=%d)\n", (int)swdctx, loglevel);
if (swdctx==NULL){
LOG_WARNING("swd_log_level_inherit(): SWD Context not (yet) initialized...\n");
return SWD_OK;
@@ -252,4 +263,42 @@ int swd_log_level_inherit(swd_ctx_t *swdctx, int loglevel){
} else return SWD_OK;
}
+/** We will use OpenOCD's logging mechanisms to show LibSWD messages. */
+int swd_log(swd_ctx_t *swdctx, swd_loglevel_t loglevel, char *msg, ...){
+ if (swdctx==NULL) return SWD_ERROR_NULLCONTEXT;
+ if (loglevel > SWD_LOGLEVEL_MAX) return SWD_ERROR_PARAM;
+
+ if (loglevel > swdctx->config.loglevel) return SWD_OK;
+ int res;
+ va_list ap;
+ va_start(ap, msg);
+ res=vprintf(msg, ap);
+ va_end(ap);
+ return res;
+
+
+ LOG_DEBUG("swdctx=0x%08X, loglevel=0x%02X, msg=%s\n", (int)swdctx, (int)loglevel, msg);
+ switch(loglevel){
+ case SWD_LOGLEVEL_NORMAL:
+ LOG_USER(msg, ap);
+ break;
+ case SWD_LOGLEVEL_ERROR:
+ LOG_ERROR(msg, ap);
+ break;
+ case SWD_LOGLEVEL_WARNING:
+ LOG_WARNING(msg, ap);
+ break;
+ case SWD_LOGLEVEL_INFO:
+ printf(msg, ap);
+ break;
+ case SWD_LOGLEVEL_DEBUG:
+ LOG_DEBUG(msg, ap);
+ break;
+ default:
+ LOG_USER(msg, ap);
+ }
+ va_end(ap);
+
+ return SWD_OK;
+}