Merge branch 'upmaster' into ft2232_gpio_danger
[openocd/dsp568013.git] / src / transport / swd.c
blob118d603b978497043fe16472883f5422fca34cec
1 /*
2 * $Id$
4 * SWD Transport Body File for OpenOCD.
6 * Copyright (C) 2010-2011, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * 3. Neither the name of the Tomasz Boleslaw CEDRO nor the names of its
17 * contributors may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
28 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.*
32 * Written by Tomasz Boleslaw CEDRO <cederom@tlen.pl>, 2010-2011;
36 /** \file swd.c SWD Transport Body File for OpenOCD.
37 * SWD Transport Layer creates bridge between target and the interface driver
38 * functions. Target functions create high level operations on the device's
39 * DAP (Debug Access Port), while interface driver passes electrical signals
40 * in and out of the physical device. Transport is implemented using LibSWD,
41 * and external open-source SWD framework.
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
48 #include <transport/swd.h>
49 #include <target/arm_adi_v5.h>
50 #include <jtag/interface.h> //we want this here to use extern global *interface
51 #include <transport/transport.h>
53 ///Unfortunalety OpenOCD use globals to pass information so we need to use it too.
54 extern struct jtag_interface *jtag_interface;
55 extern const struct dap_ops swd_dp_ops;
56 static struct transport swd_transport;
58 /** @{ swd_arm_adi_v5 Function set to support existing ARM ADI v5 target's
59 * infrastructure.
62 int swd_queue_idcode_read(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data){
63 int retval;
64 retval=swd_dp_read_idcode(dap->ctx, SWD_OPERATION_ENQUEUE, (int **)&data);
65 if (retval<0) {
66 LOG_ERROR("swd_dp_read_idcode() error: %s ", swd_error_string(retval));
67 return ERROR_FAIL;
68 } else return ERROR_OK;
71 int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
72 int retval;
73 retval=swd_dp_read((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, reg, (int **)&data);
74 if (retval<0){
75 LOG_ERROR("swd_dp_read() error: %s ", swd_error_string(retval));
76 return ERROR_FAIL;
78 return ERROR_OK;
81 int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
82 int retval;
83 retval=swd_dp_write((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int *) &data);
84 if (retval<0){
85 LOG_ERROR("swd_dp_write() error: %s ", swd_error_string(retval));
86 return ERROR_FAIL;
88 return ERROR_OK;
91 int swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data){
92 int retval;
93 retval=swd_ap_read((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int **) &data);
94 if (retval<0){
95 LOG_ERROR("swd_ap_read() error: %s ", swd_error_string(retval));
96 return ERROR_FAIL;
98 return ERROR_OK;
101 int swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg, uint32_t data){
102 int retval;
103 retval=swd_ap_write((swd_ctx_t *)dap->ctx, SWD_OPERATION_ENQUEUE, (char) reg, (int *) &data);
104 if (retval<0){
105 LOG_ERROR("swd_ap_write() error: %s ", swd_error_string(retval));
106 return ERROR_FAIL;
108 return ERROR_OK;
111 int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack){
112 //int retval;
113 //char reg=SWD_DP_ABORT_ADDR;
114 LOG_ERROR("not yet implemented");
115 return ERROR_FAIL;
118 int swd_run(struct adiv5_dap *dap){
119 int retval;
120 retval=swd_cmdq_flush((swd_ctx_t *)dap->ctx, SWD_OPERATION_EXECUTE);
121 if (retval<0){
122 LOG_ERROR("swd_cmdq_flush() error: %s", swd_error_string(retval));
123 return retval;
124 } else return ERROR_OK;
127 const struct dap_ops swd_dap_ops = {
128 .is_swd = true,
130 .queue_idcode_read = swd_queue_idcode_read,
131 .queue_dp_read = swd_queue_dp_read,
132 .queue_dp_write = swd_queue_dp_write,
133 .queue_ap_read = swd_queue_ap_read,
134 .queue_ap_write = swd_queue_ap_write,
135 .queue_ap_abort = swd_queue_ap_abort,
136 .run = swd_run,
140 // Transport select prepares selected transport for later use and bus/target initialization.
141 // TODO: We are operating on global interface pointer, change it into function parameter asap.
142 int swd_transport_init(struct command_context *ctx){
143 LOG_DEBUG("%s",__func__);
144 int retval, *idcode;
147 * Initialize the driver to work with selected transport.
148 * Because we can work on existing context there is no need to destroy it,
149 * as it can be used on next try.
151 retval=swd_dap_detect((swd_ctx_t *)jtag_interface->transport->ctx, SWD_OPERATION_EXECUTE, &idcode);
152 if (retval<0) {
153 LOG_ERROR("swd_dap_detect() error %d (%s)", retval, swd_error_string(retval));
154 return retval;
157 LOG_INFO("SWD transport initialization complete. Found IDCODE=0x%08X.", *idcode);
158 return ERROR_OK;
162 * Select SWD transport on interface pointed by global *jtag_interface structure.
163 * Select is assumed to be called before transport init. It prepares everything,
164 * including interface buffers, context memory and command set for higher layers,
165 * but does not interrogate target device (with IDCODE read).
167 int swd_transport_select(struct command_context *ctx){
168 LOG_DEBUG("%s",__func__);
169 int retval;
171 jtag_interface->transport=&swd_transport;
173 // Create SWD_CTX if nesessary
174 if (!jtag_interface->transport->ctx){
175 /** Transport was not yet initialized. */
176 jtag_interface->transport->ctx=swd_init();
177 if (jtag_interface->transport->ctx==NULL) {
178 LOG_ERROR("Cannot initialize SWD context!");
179 return ERROR_FAIL;
181 LOG_INFO("New SWD context initialized at 0x%08X", (int)&jtag_interface->transport->ctx);
182 } else LOG_INFO("Working on existing transport context at 0x%0X...", (int)&jtag_interface->transport->ctx);
184 // Select SWD DAP by sending JTAG-TO-SWD sequence on the transport layer
185 retval=swd_dap_select((swd_ctx_t *)jtag_interface->transport->ctx, SWD_OPERATION_EXECUTE);
186 if (retval<0) {
187 LOG_ERROR("swd_dap_select() error: %s", swd_error_string(retval));
188 return ERROR_FAIL;
191 LOG_DEBUG("SWD Transport selection complete...");
192 return ERROR_OK;
197 static struct transport swd_transport = {
198 .name = "swd",
199 .select = swd_transport_select,
200 .init = swd_transport_init,
201 .ctx = NULL,
202 .next = NULL
205 static void swd_constructor(void) __attribute__((constructor));
206 static void swd_constructor(void)
208 transport_register(&swd_transport);
211 /** Returns true if the current debug session
212 * * is using SWD as its transport.
213 * */
214 //bool transport_is_swd(void)
216 // return get_current_transport() == &swd_transport;
225 ///////////////////////////////////////////////////////////////////////////////
226 // BELOW UGLY FUNCTIONS TO MAKE OLD THINGS WORK AND COMPILE, REMOVE THEM ASAP
227 ///////////////////////////////////////////////////////////////////////////////
229 #include <target/arm.h>
232 * This represents the bits which must be sent out on TMS/SWDIO to
233 * switch a DAP implemented using an SWJ-DP module into SWD mode.
234 * These bits are stored (and transmitted) LSB-first.
236 * See the DAP-Lite specification, section 2.2.5 for information
237 * about making the debug link select SWD or JTAG. (Similar info
238 * is in a few other ARM documents.)
240 static const uint8_t jtag2swd_bitseq[] = {
241 /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
242 * putting both JTAG and SWD logic into reset state.
244 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
245 /* Switching sequence enables SWD and disables JTAG
246 * NOTE: bits in the DP's IDCODE may expose the need for
247 * an old/obsolete/deprecated sequence (0xb6 0xed).
249 0x9e, 0xe7,
250 /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
251 * putting both JTAG and SWD logic into reset state.
253 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
259 * Put the debug link into SWD mode, if the target supports it.
260 * The link's initial mode may be either JTAG (for example,
261 * with SWJ-DP after reset) or SWD.
263 * @param target Enters SWD mode (if possible).
265 * Note that targets using the JTAG-DP do not support SWD, and that
266 * some targets which could otherwise support it may have have been
267 * configured to disable SWD signaling
269 * @return ERROR_OK or else a fault code.
271 int dap_to_swd(struct target *target)
273 struct arm *arm = target_to_arm(target);
274 int retval;
276 LOG_DEBUG("Enter SWD mode");
278 /* REVISIT it's ugly to need to make calls to a "jtag"
279 * subsystem if the link may not be in JTAG mode...
282 retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq),
283 jtag2swd_bitseq, TAP_INVALID);
284 if (retval == ERROR_OK)
285 retval = jtag_execute_queue();
287 /* set up the DAP's ops vector for SWD mode. */
288 arm->dap->ops = &swd_dap_ops;
290 return retval;
295 /** @} */