diff options
-rw-r--r-- | src/transport/Makefile.am | 8 | ||||
-rw-r--r-- | src/transport/swd.c | 93 | ||||
-rw-r--r-- | src/transport/swd.h | 18 | ||||
-rw-r--r-- | src/transport/swd_libswd_drv_openocd.c | 65 |
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; +} |