4 * SWD Transport Body File for OpenOCD.
6 * Copyright (C) 2010-2011, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
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.
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
62 int swd_queue_idcode_read(struct adiv5_dap
*dap
, uint8_t *ack
, uint32_t *data
){
64 retval
=swd_dp_read_idcode(dap
->ctx
, SWD_OPERATION_ENQUEUE
, (int **)&data
);
66 LOG_ERROR("swd_dp_read_idcode() error: %s ", swd_error_string(retval
));
68 } else return ERROR_OK
;
71 int swd_queue_dp_read(struct adiv5_dap
*dap
, unsigned reg
, uint32_t *data
){
73 retval
=swd_dp_read((swd_ctx_t
*)dap
->ctx
, SWD_OPERATION_ENQUEUE
, reg
, (int **)&data
);
75 LOG_ERROR("swd_dp_read() error: %s ", swd_error_string(retval
));
81 int swd_queue_dp_write(struct adiv5_dap
*dap
, unsigned reg
, uint32_t data
){
83 retval
=swd_dp_write((swd_ctx_t
*)dap
->ctx
, SWD_OPERATION_ENQUEUE
, (char) reg
, (int *) &data
);
85 LOG_ERROR("swd_dp_write() error: %s ", swd_error_string(retval
));
91 int swd_queue_ap_read(struct adiv5_dap
*dap
, unsigned reg
, uint32_t *data
){
93 retval
=swd_ap_read((swd_ctx_t
*)dap
->ctx
, SWD_OPERATION_ENQUEUE
, (char) reg
, (int **) &data
);
95 LOG_ERROR("swd_ap_read() error: %s ", swd_error_string(retval
));
101 int swd_queue_ap_write(struct adiv5_dap
*dap
, unsigned reg
, uint32_t data
){
103 retval
=swd_ap_write((swd_ctx_t
*)dap
->ctx
, SWD_OPERATION_ENQUEUE
, (char) reg
, (int *) &data
);
105 LOG_ERROR("swd_ap_write() error: %s ", swd_error_string(retval
));
111 int swd_queue_ap_abort(struct adiv5_dap
*dap
, uint8_t *ack
){
113 //char reg=SWD_DP_ABORT_ADDR;
114 LOG_ERROR("not yet implemented");
118 int swd_run(struct adiv5_dap
*dap
){
120 retval
=swd_cmdq_flush((swd_ctx_t
*)dap
->ctx
, SWD_OPERATION_EXECUTE
);
122 LOG_ERROR("swd_cmdq_flush() error: %s", swd_error_string(retval
));
124 } else return ERROR_OK
;
127 const struct dap_ops swd_dap_ops
= {
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
,
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__
);
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
);
153 LOG_ERROR("swd_dap_detect() error %d (%s)", retval
, swd_error_string(retval
));
157 LOG_INFO("SWD transport initialization complete. Found IDCODE=0x%08X.", *idcode
);
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__
);
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!");
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
);
187 LOG_ERROR("swd_dap_select() error: %s", swd_error_string(retval
));
191 LOG_DEBUG("SWD Transport selection complete...");
197 static struct transport swd_transport
= {
199 .select
= swd_transport_select
,
200 .init
= swd_transport_init
,
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.
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).
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
);
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
;