1 /***************************************************************************
2 * Copyright (C) 2013 by mike brown *
3 * mike@theshedworks.org.uk *
5 * Copyright (C) 2013 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
26 * Utilities to support ARM "CMSIS-DAP", The CoreSight Debug Access Port.
27 * This is coupled to recent versions of ARM's "CoreSight" debug framework.
28 * This specific code is a transport level interface, with
29 * "target/arm_adi_v5.[hc]" code understanding operation semantics,
30 * shared with the SWD & JTAG transports.
38 #include "arm_adi_v5.h"
39 #include <helper/time_support.h>
41 #include <transport/transport.h>
42 #include <jtag/interface.h>
46 #define CMSIS_CMD_DP (0 << 0) /* set only for AP access */
47 #define CMSIS_CMD_AP (1 << 0) /* set only for AP access */
48 #define CMSIS_CMD_READ (1 << 1) /* set only for read access */
49 #define CMSIS_CMD_WRITE (0 << 1) /* set only for read access */
50 #define CMSIS_CMD_A32(n) ((n)&0x0C) /* bits A[3:2] of register addr */
51 #define CMSIS_CMD_VAL_MATCH (1 << 4) /* Value Match */
52 #define CMSIS_CMD_MATCH_MSK (1 << 5) /* Match Mask */
54 /* YUK! - but this is currently a global.... */
55 extern struct jtag_interface *jtag_interface;
57 static int cmsis_dap_clear_sticky_errors(struct adiv5_dap *dap)
59 LOG_DEBUG("CMSIS-ADI: %s", __func__);
61 const struct swd_driver *swd = jtag_interface->swd;
64 return swd->write_reg(swd_cmd(false, false, DP_ABORT),
65 STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR);
68 static int cmsis_dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
70 LOG_DEBUG("CMSIS-ADI: %s", __func__);
72 const struct swd_driver *swd = jtag_interface->swd;
75 return swd->write_reg(swd_cmd(false, false, DP_ABORT),
76 DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR);
79 static int cmsis_dap_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data)
81 LOG_DEBUG("CMSIS-ADI: cmsis_dap_queue_dp_read %d", reg);
83 int retval = jtag_interface->swd->read_reg(
84 (CMSIS_CMD_DP | CMSIS_CMD_READ | CMSIS_CMD_A32(reg)), data);
86 if (retval != ERROR_OK)
87 cmsis_dap_clear_sticky_errors(dap);
92 static int (cmsis_dap_queue_dp_write)(struct adiv5_dap *dap, unsigned reg, uint32_t data)
94 LOG_DEBUG("CMSIS-ADI: cmsis_dap_queue_dp_write %d 0x%08" PRIx32, reg, data);
96 /* setting the ORUNDETECT bit causes issues for some targets,
97 * disable until we find out why */
98 if (reg == DP_CTRL_STAT) {
99 LOG_DEBUG("disabling overrun detection");
100 data &= ~CORUNDETECT;
103 int retval = jtag_interface->swd->write_reg(
104 (CMSIS_CMD_DP | CMSIS_CMD_WRITE | CMSIS_CMD_A32(reg)), data);
106 if (retval != ERROR_OK)
107 cmsis_dap_clear_sticky_errors(dap);
112 /** Select the AP register bank matching bits 7:4 of reg. */
113 static int cmsis_dap_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg)
115 uint32_t select_ap_bank = reg & 0x000000F0;
117 if (select_ap_bank == dap->ap_bank_value)
120 dap->ap_bank_value = select_ap_bank;
121 select_ap_bank |= dap->ap_current;
123 return cmsis_dap_queue_dp_write(dap, DP_SELECT, select_ap_bank);
126 static int (cmsis_dap_queue_ap_read)(struct adiv5_dap *dap, unsigned reg, uint32_t *data)
128 int retval = cmsis_dap_ap_q_bankselect(dap, reg);
129 if (retval != ERROR_OK)
132 LOG_DEBUG("CMSIS-ADI: cmsis_dap_queue_ap_read %d", reg);
134 retval = jtag_interface->swd->read_reg(
135 (CMSIS_CMD_AP | CMSIS_CMD_READ | CMSIS_CMD_A32(reg)), data);
137 if (retval != ERROR_OK)
138 cmsis_dap_clear_sticky_errors(dap);
143 static int (cmsis_dap_queue_ap_write)(struct adiv5_dap *dap, unsigned reg, uint32_t data)
147 /* TODO: CSW_DBGSWENABLE (bit31) causes issues for some targets
148 * disable until we find out why */
149 if (reg == AP_REG_CSW)
150 data &= ~CSW_DBGSWENABLE;
152 int retval = cmsis_dap_ap_q_bankselect(dap, reg);
153 if (retval != ERROR_OK)
156 LOG_DEBUG("CMSIS-ADI: cmsis_dap_queue_ap_write %d 0x%08" PRIx32, reg, data);
158 retval = jtag_interface->swd->write_reg(
159 (CMSIS_CMD_AP | CMSIS_CMD_WRITE | CMSIS_CMD_A32(reg)), data);
161 if (retval != ERROR_OK)
162 cmsis_dap_clear_sticky_errors(dap);
167 /** Executes all queued DAP operations. */
168 static int cmsis_dap_run(struct adiv5_dap *dap)
170 LOG_DEBUG("CMSIS-ADI: cmsis_dap_run");
171 /* FIXME: for now the CMSIS-DAP interface hard-wires a zero-size queue. */
176 const struct dap_ops cmsis_dap_ops = {
178 .queue_dp_read = cmsis_dap_queue_dp_read,
179 .queue_dp_write = cmsis_dap_queue_dp_write,
180 .queue_ap_read = cmsis_dap_queue_ap_read,
181 .queue_ap_write = cmsis_dap_queue_ap_write,
182 .queue_ap_abort = cmsis_dap_queue_ap_abort,
183 .run = cmsis_dap_run,
186 static const struct command_registration cmsis_dap_commands[] = {
189 * Set up SWD and JTAG targets identically, unless/until
190 * infrastructure improves ... meanwhile, ignore all
191 * JTAG-specific stuff like IR length for SWD.
193 * REVISIT can we verify "just one SWD DAP" here/early?
196 .jim_handler = jim_jtag_newtap,
197 .mode = COMMAND_CONFIG,
198 .help = "declare a new CMSIS-DAP"
200 COMMAND_REGISTRATION_DONE
203 static const struct command_registration cmsis_dap_handlers[] = {
207 .help = "cmsis_dap command group",
208 .chain = cmsis_dap_commands,
210 COMMAND_REGISTRATION_DONE
213 static int cmsis_dap_select(struct command_context *ctx)
215 LOG_DEBUG("CMSIS-ADI: cmsis_dap_select");
217 int retval = register_commands(ctx, NULL, cmsis_dap_handlers);
219 if (retval != ERROR_OK)
222 /* FIXME: This needs a real overhaul!! FIXME
223 * be sure driver is in SWD mode; start
224 * with hardware default TRN (1), it can be changed later
225 * we use a bogus 'swd' driver to implement cmsis-dap as it is quite similar */
227 const struct swd_driver *swd = jtag_interface->swd;
228 if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
229 LOG_ERROR("no SWD driver?");
233 retval = swd->init(1);
234 if (retval != ERROR_OK) {
235 LOG_ERROR("unable to init CMSIS-DAP driver");
242 static int cmsis_dap_init(struct command_context *ctx)
244 struct target *target = get_current_target(ctx);
245 struct arm *arm = target_to_arm(target);
246 struct adiv5_dap *dap = arm->dap;
250 LOG_DEBUG("CMSIS-ADI: cmsis_dap_init");
252 /* Force the DAP's ops vector for CMSIS-DAP mode.
253 * messy - is there a better way? */
254 arm->dap->ops = &cmsis_dap_ops;
256 /* FIXME validate transport config ... is the
257 * configured DAP present (check IDCODE)?
258 * Is *only* one DAP configured?
263 /* Note, debugport_init() does setup too */
266 const struct swd_driver *swd = jtag_interface->swd;
267 if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
268 LOG_ERROR("no SWD driver?");
272 int retval = swd->init(1);
273 if (retval != ERROR_OK) {
274 LOG_ERROR("unable to init CMSIS-DAP driver");
279 status = cmsis_dap_queue_dp_read(dap, DP_IDCODE, &idcode);
281 if (status == ERROR_OK)
282 LOG_INFO("IDCODE 0x%08" PRIx32, idcode);
284 /* force clear all sticky faults */
285 cmsis_dap_clear_sticky_errors(dap);
287 /* this is a workaround to get polling working */
288 jtag_add_reset(0, 0);
293 static struct transport cmsis_dap_transport = {
295 .select = cmsis_dap_select,
296 .init = cmsis_dap_init,
299 static void cmsis_dap_constructor(void) __attribute__((constructor));
300 static void cmsis_dap_constructor(void)
302 transport_register(&cmsis_dap_transport);
305 /** Returns true if the current debug session
306 * is using CMSIS-DAP as its transport.
308 bool transport_is_cmsis_dap(void)
310 return get_current_transport() == &cmsis_dap_transport;