Add initial try for OpenOCD patch.
[bbg-swd.git] / 0001-initial-patch-for-BBG-SWD.patch
1 From 54d479761de86a235d4c9f05479df07b5ea11573 Mon Sep 17 00:00:00 2001
2 From: NIIBE Yutaka <gniibe@fsij.org>
3 Date: Mon, 21 Mar 2016 04:38:39 +0000
4 Subject: [PATCH] initial patch for BBG-SWD
5
6 ---
7  configure.ac                 |  13 ++
8  src/jtag/drivers/Makefile.am |   3 +
9  src/jtag/drivers/bbg-swd.c   | 439 +++++++++++++++++++++++++++++++++++++++++++
10  src/jtag/drivers/bbg-swd.h   |  44 +++++
11  src/jtag/interfaces.c        |   6 +
12  5 files changed, 505 insertions(+)
13  create mode 100644 src/jtag/drivers/bbg-swd.c
14  create mode 100644 src/jtag/drivers/bbg-swd.h
15
16 diff --git a/configure.ac b/configure.ac
17 index fb01e1b..d7f4ed9 100644
18 --- a/configure.ac
19 +++ b/configure.ac
20 @@ -527,6 +527,10 @@ AC_ARG_ENABLE([remote-bitbang],
21    AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
22    [build_remote_bitbang=$enableval], [build_remote_bitbang=no])
23  
24 +AC_ARG_ENABLE([bbg-swd],
25 +  AS_HELP_STRING([--enable-bbg-swd], [Enable building support for BBG-SWD.]),
26 +  [build_bbg_swd=$enableval], [build_bbg_swd=no])
27 +
28  AC_MSG_CHECKING([whether to enable dummy minidriver])
29  if test $build_minidriver_dummy = yes; then
30    if test $build_minidriver = yes; then
31 @@ -818,6 +822,14 @@ if test $build_sysfsgpio = yes; then
32  else
33    AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.])
34  fi
35 +
36 +if test $build_bbg_swd = yes; then
37 +  build_bbg_swd=yes
38 +  LIBS="$LIBS -lprussdrv"
39 +  AC_DEFINE([BUILD_BBG_SWD], [1], [1 if you want the BBG-SWD driver.])
40 +else
41 +  AC_DEFINE([BUILD_BBG_SWD], [0], [0 if you don't want the BBG-SWD driver.])
42 +fi
43  #-- Deal with MingW/Cygwin FTD2XX issues
44  
45  if test $is_win32 = yes; then
46 @@ -1230,6 +1242,7 @@ AM_CONDITIONAL([IS_WIN32], [test $is_win32 = yes])
47  AM_CONDITIONAL([IS_DARWIN], [test $is_darwin = yes])
48  AM_CONDITIONAL([BITQ], [test $build_bitq = yes])
49  AM_CONDITIONAL([CMSIS_DAP], [test $use_hidapi = yes])
50 +AM_CONDITIONAL([BBG_SWD], [test $build_bbg_swd = yes])
51  
52  AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes])
53  AM_CONDITIONAL([MINIDRIVER_DUMMY], [test $build_minidriver_dummy = yes])
54 diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
55 index 2aaf8fd..4a87324 100644
56 --- a/src/jtag/drivers/Makefile.am
57 +++ b/src/jtag/drivers/Makefile.am
58 @@ -143,6 +143,9 @@ endif
59  if CMSIS_DAP
60  DRIVERFILES += cmsis_dap_usb.c
61  endif
62 +if BBG_SWD
63 +DRIVERFILES += bbg-swd.c
64 +endif
65  
66  noinst_HEADERS = \
67         bitbang.h \
68 diff --git a/src/jtag/drivers/bbg-swd.c b/src/jtag/drivers/bbg-swd.c
69 new file mode 100644
70 index 0000000..3cfb312
71 --- /dev/null
72 +++ b/src/jtag/drivers/bbg-swd.c
73 @@ -0,0 +1,439 @@
74 +/***************************************************************************
75 + *   Copyright (C) 2016  Flying Stone Technology                           *
76 + *   Author: NIIBE Yutaka <gniibe@fsij.org>                                *
77 + *                                                                         *
78 + *   This program is free software; you can redistribute it and/or modify  *
79 + *   it under the terms of the GNU General Public License as published by  *
80 + *   the Free Software Foundation; either version 2 of the License, or     *
81 + *   (at your option) any later version.                                   *
82 + *                                                                         *
83 + *   This program is distributed in the hope that it will be useful,       *
84 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
85 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
86 + *   GNU General Public License for more details.                          *
87 + *                                                                         *
88 + *   You should have received a copy of the GNU General Public License     *
89 + *   along with this program; if not, write to the                         *
90 + *   Free Software Foundation, Inc.,                                       *
91 + *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
92 + ***************************************************************************/
93 +
94 +#ifdef HAVE_CONFIG_H
95 +#include "config.h"
96 +#endif
97 +
98 +#include <jtag/interface.h>
99 +#include <jtag/commands.h>
100 +#include <jtag/swd.h>
101 +
102 +#include <prussdrv.h>
103 +#include <pruss_intc_mapping.h>
104 +
105 +#define PRU_NUM         0
106 +
107 +extern struct jtag_interface *jtag_interface;
108 +static void bbg_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
109 +static int bbg_swd_switch_seq(enum swd_special_seq seq);
110 +
111 +static void pru_request_cmd(uint32_t *p)
112 +{
113 +       /* Wakeup the PRU0 which sleeps.  */
114 +       prussdrv_pru_send_event(ARM_PRU0_INTERRUPT);
115 +
116 +       /* Wait PRU0 response.  */
117 +       prussdrv_pru_wait_event(PRU_EVTOUT_0);
118 +       prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
119 +       LOG_DEBUG("Request of command execution (%08x)", *p);
120 +}
121 +
122 +static int queued_retval;
123 +
124 +#define PRU_SWD_PROGRAM_PATH PKGDATADIR "/bbg-swd/pru-swd.bin"
125 +
126 +static uint32_t *pru_data_ram;
127 +static tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
128 +
129 +static int bbg_swd_open(void)
130 +{
131 +       int r;
132 +
133 +       LOG_DEBUG("bbg_swd_init");
134 +
135 +       /* Initialize the PRUSS driver.  */
136 +       prussdrv_init();
137 +
138 +       /* Open PRU interrupt to Host.  */
139 +       r = prussdrv_open(PRU_EVTOUT_0);
140 +       if (r < 0) {
141 +               LOG_ERROR("prussdrv_open open failed: %d", r);
142 +               return ERROR_FAIL;
143 +       }
144 +
145 +       /* Initialize PRU interrupt controller.  */
146 +       prussdrv_pruintc_init(&pruss_intc_initdata);
147 +
148 +       /* Initialize PRU memory access from Host.  */
149 +       r = prussdrv_map_prumem(PRUSS0_PRU0_DATARAM, (void **)&pru_data_ram);
150 +       if (r < 0) {
151 +               prussdrv_exit();
152 +               LOG_ERROR("prussdrv_map_prumem failed: %d", r);
153 +               return ERROR_FAIL;
154 +       }
155 +
156 +       /* Execute example on PRU */
157 +       LOG_DEBUG("Executing PRU-SWU program on PRUSS");
158 +       r = prussdrv_exec_program(PRU_NUM, PRU_SWD_PROGRAM_PATH);
159 +       if (r < 0) {
160 +               prussdrv_exit();
161 +               LOG_ERROR("prussdrv_exec_program failed: %d", r);
162 +               return ERROR_FAIL;
163 +       }
164 +       return ERROR_OK;
165 +}
166 +
167 +
168 +static int bbg_swd_close(void)
169 +{
170 +       /* Disable PRU.  */
171 +       prussdrv_pru_disable(PRU_NUM);
172 +       prussdrv_exit();
173 +       return ERROR_OK;
174 +}
175 +
176 +
177 +static int bbg_swd_gpio_srst(int on)
178 +{
179 +       /* XXX: not yet implemented */
180 +       return ERROR_OK;
181 +}
182 +
183 +static bool swd_mode;
184 +
185 +static int bbg_swd_interface_init(void)
186 +{
187 +       int retval;
188 +       enum reset_types jtag_reset_config = jtag_get_reset_config();
189 +
190 +       if (swd_mode) {
191 +               retval = bbg_swd_open();
192 +               if (retval != ERROR_OK)
193 +                       return retval;
194 +       }
195 +
196 +       if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
197 +               if (jtag_reset_config & RESET_SRST_NO_GATING) {
198 +                       retval = bbg_swd_gpio_srst(0);
199 +                       if (retval != ERROR_OK)
200 +                               return ERROR_FAIL;
201 +                       LOG_INFO("Connecting under reset");
202 +               }
203 +       }
204 +
205 +       LOG_INFO("BBG-SWD: Interface ready");
206 +
207 +       return ERROR_OK;
208 +}
209 +
210 +static int bbg_swd_interface_quit(void)
211 +{
212 +       bbg_swd_close();
213 +       return ERROR_OK;
214 +}
215 +
216 +static int bbg_swd_swd_init(void)
217 +{
218 +       swd_mode = true;
219 +       return ERROR_OK;
220 +}
221 +
222 +enum {
223 +       CMD_HALT = 0,
224 +       CMD_BLINK,
225 +       CMD_GPIO_OUT,
226 +       CMD_GPIO_IN,
227 +       CMD_SIG_IDLE,
228 +       CMD_SIG_GEN,
229 +       CMD_READ_REG,
230 +       CMD_WRITE_REG
231 +};
232 +
233 +#define BBG_SWS_RESULT 16
234 +
235 +/* 
236 + * Signal patterns are defined in:
237 + *     ARM Debug Interface Architecture Specification (ADI)
238 + */
239 +static const uint8_t seq_jtag_to_swd[] = { 0xde, 0xf9 };
240 +static const int seq_jtag_to_swd_len = 16;
241 +static const uint8_t seq_swd_to_seq[] = { 0x3c, 0xe7 };
242 +static const int seq_swd_to_jtag_len = 16;
243 +
244 +static void bbg_swd_idle(int count)
245 +{
246 +       pru_data_ram[0] = CMD_SIG_IDLE;
247 +       pru_data_ram[1] = count;
248 +       pru_request_cmd(pru_data_ram);
249 +}
250 +
251 +static int bbg_swd_switch_seq(enum swd_special_seq seq)
252 +{
253 +       LOG_DEBUG("bbg_swd_switch_seq");
254 +
255 +       switch (seq) {
256 +       case LINE_RESET:
257 +               LOG_DEBUG("SWD line reset");
258 +               pru_data_ram[0] = CMD_SIG_GEN | (swd_seq_line_reset_len << 8);
259 +               memcpy (&pru_data_ram[1], swd_seq_line_reset, swd_seq_line_reset_len);
260 +               pru_request_cmd(pru_data_ram);
261 +               break;
262 +       case JTAG_TO_SWD:
263 +               LOG_DEBUG("JTAG-to-SWD");
264 +               pru_data_ram[0] = CMD_SIG_GEN | (swd_seq_jtag_to_swd_len << 8);
265 +               memcpy (&pru_data_ram[1], swd_seq_jtag_to_swd, swd_seq_jtag_to_swd_len);
266 +               pru_request_cmd(pru_data_ram);
267 +               break;
268 +       case SWD_TO_JTAG:
269 +               LOG_DEBUG("JTAG-to-SWD");
270 +               pru_data_ram[0] = CMD_SIG_GEN | (swd_seq_swd_to_jtag_len << 8);
271 +               memcpy (&pru_data_ram[1], swd_seq_swd_to_jtag, swd_seq_swd_to_jtag_len);
272 +               pru_request_cmd(pru_data_ram);
273 +               break;
274 +       default:
275 +               LOG_ERROR("Sequence %d not supported", seq);
276 +               return ERROR_FAIL;
277 +       }
278 +
279 +       return ERROR_OK;
280 +}
281 +
282 +static void bbg_swd_clear_sticky_errors(void)
283 +{
284 +       bbg_swd_write_reg(swd_cmd(false,  false, DP_ABORT),
285 +               STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
286 +}
287 +
288 +
289 +static void bbg_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
290 +{
291 +       LOG_DEBUG("bbg_swd_read_reg");
292 +       assert(cmd & SWD_CMD_RnW);
293 +       assert(ap_delay_clk < 256);
294 +
295 +       if (queued_retval != ERROR_OK) {
296 +               LOG_DEBUG("Skip bbg_swd_read_reg because queued_retval=%d", queued_retval);
297 +               return;
298 +       }
299 +
300 +       for (;;) {
301 +               int ack;
302 +               int parity;
303 +               uint32_t data;
304 +               uint32_t delay = 0;
305 +
306 +               if (cmd & SWD_CMD_APnDP)
307 +                       delay = ap_delay_clk;
308 +
309 +               cmd |= 0x81;
310 +               pru_data_ram[0] = CMD_READ_REG | (cmd << 8) | (delay << 24);
311 +               pru_request_cmd(pru_data_ram);
312 +               ack = pru_data_ram[BBG_SWS_RESULT] & 0x07;
313 +               parity = (pru_data_ram[BBG_SWS_RESULT] & 0x80000000) != 0;
314 +               data = pru_data_ram[BBG_SWS_RESULT+1];
315 +
316 +               LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
317 +                         ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
318 +                         cmd & SWD_CMD_APnDP ? "AP" : "DP",
319 +                         cmd & SWD_CMD_RnW ? "read" : "write",
320 +                         (cmd & SWD_CMD_A32) >> 1,
321 +                         data);
322 +
323 +               switch (ack) {
324 +               case SWD_ACK_OK:
325 +                       if (parity != parity_u32(data)) {
326 +                               LOG_DEBUG("Wrong parity detected (%d)", parity);
327 +                               queued_retval = ERROR_FAIL;
328 +                               return;
329 +                       }
330 +                       if (value)
331 +                               *value = data;
332 +                       return;
333 +               case SWD_ACK_WAIT:
334 +                       LOG_DEBUG("SWD_ACK_WAIT");
335 +                       bbg_swd_clear_sticky_errors();
336 +                       break;
337 +               case SWD_ACK_FAULT:
338 +                       LOG_DEBUG("SWD_ACK_FAULT");
339 +                       queued_retval = ack;
340 +                       return;
341 +               default:
342 +                       LOG_DEBUG("No valid acknowledge: ack=%d", ack);
343 +                       queued_retval = ack;
344 +                       return;
345 +               }
346 +       }
347 +}
348 +
349 +static void bbg_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
350 +{
351 +       LOG_DEBUG("bbg_swd_write_reg");
352 +       assert(!(cmd & SWD_CMD_RnW));
353 +
354 +       if (queued_retval != ERROR_OK) {
355 +               LOG_DEBUG("Skip bbg_swd_write_reg because queued_retval=%d", queued_retval);
356 +               return;
357 +       }
358 +
359 +       for (;;) {
360 +               int ack;
361 +               int parity = parity_u32(value);
362 +               uint32_t delay = 0;
363 +
364 +               assert(ap_delay_clk < 256);
365 +               if (cmd & SWD_CMD_APnDP)
366 +                       delay = ap_delay_clk;
367 +
368 +               cmd |= 0x81;
369 +               pru_data_ram[0] = CMD_WRITE_REG | (cmd << 8) | (parity << 16) | (delay << 24);
370 +               pru_data_ram[1] = value;
371 +               pru_request_cmd(pru_data_ram);
372 +               ack = pru_data_ram[BBG_SWS_RESULT] & 0x07;
373 +
374 +               LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
375 +                         ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
376 +                         cmd & SWD_CMD_APnDP ? "AP" : "DP",
377 +                         cmd & SWD_CMD_RnW ? "read" : "write",
378 +                         (cmd & SWD_CMD_A32) >> 1,
379 +                         value);
380 +
381 +               switch (ack) {
382 +               case SWD_ACK_OK:
383 +                       return;
384 +               case SWD_ACK_WAIT:
385 +                       LOG_DEBUG("SWD_ACK_WAIT");
386 +                       bbg_swd_clear_sticky_errors();
387 +                       break;
388 +               case SWD_ACK_FAULT:
389 +                       LOG_DEBUG("SWD_ACK_FAULT");
390 +                       queued_retval = ack;
391 +                       return;
392 +               default:
393 +                       LOG_DEBUG("No valid acknowledge: ack=%d", ack);
394 +                       queued_retval = ack;
395 +                       return;
396 +               }
397 +       }
398 +}
399 +
400 +static int bbg_swd_run_queue(void)
401 +{
402 +       LOG_DEBUG("bbg_swd_run_queue");
403 +       bbg_swd_idle(8);
404 +
405 +       int retval = queued_retval;
406 +       queued_retval = ERROR_OK;
407 +       LOG_DEBUG("SWD queue return value: %02x", retval);
408 +       return retval;
409 +}
410 +
411 +const struct swd_driver bbg_swd = {
412 +       .init = bbg_swd_swd_init,
413 +       .switch_seq = bbg_swd_switch_seq,
414 +       .read_reg = bbg_swd_read_reg,
415 +       .write_reg = bbg_swd_write_reg,
416 +       .run = bbg_swd_run_queue,
417 +};
418 +
419 +
420 +static const char * const bbg_swd_transport[] = { "swd", NULL };
421 +
422 +
423 +COMMAND_HANDLER(bbg_swd_handle_hello_command)
424 +{
425 +       puts("Hello!");
426 +       return ERROR_OK;
427 +}
428 +
429 +static const struct command_registration bbg_swd_command_handlers[] = {
430 +       {
431 +               .name = "bbg_swd_hello",
432 +               .handler = &bbg_swd_handle_hello_command,
433 +               .mode = COMMAND_CONFIG,
434 +               .help = "hello command for BBG-SWD",
435 +               .usage = "<cmd>",
436 +       },
437 +       COMMAND_REGISTRATION_DONE
438 +};
439 +
440 +static void bbg_swd_execute_reset(struct jtag_command *cmd)
441 +{
442 +       bbg_swd_gpio_srst(cmd->cmd.reset->srst ? 0: 1);
443 +}
444 +
445 +static void bbg_swd_execute_sleep(struct jtag_command *cmd)
446 +{
447 +       jtag_sleep(cmd->cmd.sleep->us);
448 +}
449 +
450 +static void bbg_swd_execute_command(struct jtag_command *cmd)
451 +{
452 +       switch (cmd->type) {
453 +               case JTAG_RESET:
454 +                       bbg_swd_execute_reset(cmd);
455 +                       break;
456 +               case JTAG_SLEEP:
457 +                       bbg_swd_execute_sleep(cmd);
458 +                       break;
459 +               default:
460 +                       LOG_ERROR("BUG: unknown JTAG command type encountered");
461 +                       exit(-1);
462 +       }
463 +}
464 +
465 +static int bbg_swd_interface_execute_queue(void)
466 +{
467 +       struct jtag_command *cmd = jtag_command_queue;
468 +
469 +       while (cmd != NULL) {
470 +               bbg_swd_execute_command(cmd);
471 +               cmd = cmd->next;
472 +       }
473 +
474 +       return ERROR_OK;
475 +}
476 +
477 +static int bbg_swd_interface_speed(int speed)
478 +{
479 +       return ERROR_OK;
480 +}
481 +
482 +static int bbg_swd_interface_speed_div(int speed, int *khz)
483 +{
484 +       *khz = speed;
485 +       return ERROR_OK;
486 +}
487 +
488 +static int bbg_swd_interface_khz(int khz, int *jtag_speed)
489 +{
490 +       *jtag_speed = khz;
491 +       return ERROR_OK;
492 +}
493 +
494 +struct jtag_interface bbg_swd_interface = {
495 +       .name = "bbg-swd",
496 +       .commands = bbg_swd_command_handlers,
497 +       .swd = &bbg_swd,
498 +       .transports = bbg_swd_transport,
499 +
500 +       .execute_queue = bbg_swd_interface_execute_queue,
501 +       .speed = bbg_swd_interface_speed,
502 +       .speed_div = bbg_swd_interface_speed_div,
503 +       .khz = bbg_swd_interface_khz,
504 +
505 +       .init = bbg_swd_interface_init,
506 +       .quit = bbg_swd_interface_quit,
507 +};
508 +/*
509 + * Local Variables:
510 + * c-file-style: "linux"
511 + * End:
512 + */
513 diff --git a/src/jtag/drivers/bbg-swd.h b/src/jtag/drivers/bbg-swd.h
514 new file mode 100644
515 index 0000000..f0c92b3
516 --- /dev/null
517 +++ b/src/jtag/drivers/bbg-swd.h
518 @@ -0,0 +1,44 @@
519 +/***************************************************************************
520 + *   Copyright (C) 2016  Flying Stone Technology                           *
521 + *   Author: NIIBE Yutaka <gniibe@fsij.org>                                *
522 + *                                                                         *
523 + *   This program is free software; you can redistribute it and/or modify  *
524 + *   it under the terms of the GNU General Public License as published by  *
525 + *   the Free Software Foundation; either version 2 of the License, or     *
526 + *   (at your option) any later version.                                   *
527 + *                                                                         *
528 + *   This program is distributed in the hope that it will be useful,       *
529 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
530 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
531 + *   GNU General Public License for more details.                          *
532 + *                                                                         *
533 + *   You should have received a copy of the GNU General Public License     *
534 + *   along with this program; if not, write to the                         *
535 + *   Free Software Foundation, Inc.,                                       *
536 + *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
537 + ***************************************************************************/
538 +
539 +#ifndef BBG_SWD_H
540 +#define BBG_SWD_H
541 +
542 +#include <jtag/swd.h>
543 +
544 +struct bbg_swd_interface {
545 +       /* low level callbacks (for bbg_swd)
546 +        */
547 +       int (*read)(void);
548 +       void (*write)(int tck, int tms, int tdi);
549 +       void (*reset)(int trst, int srst);
550 +       void (*blink)(int on);
551 +       int (*swdio_read)(void);
552 +       void (*swdio_drive)(bool on);
553 +};
554 +
555 +const struct swd_driver bbg_swd_swd;
556 +
557 +int bbg_swd_execute_queue(void);
558 +
559 +extern struct jtag_interface bbg_swd_interface;
560 +int bbg_swd_swd_switch_seq(enum swd_special_seq seq);
561 +
562 +#endif /* BBG_SWD_H */
563 diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
564 index 62c5d45..b3fb2bd 100644
565 --- a/src/jtag/interfaces.c
566 +++ b/src/jtag/interfaces.c
567 @@ -131,6 +131,9 @@ extern struct jtag_interface bcm2835gpio_interface;
568  #if BUILD_CMSIS_DAP == 1
569  extern struct jtag_interface cmsis_dap_interface;
570  #endif
571 +#if BUILD_BBG_SWD == 1
572 +extern struct jtag_interface bbg_swd_interface;
573 +#endif
574  #endif /* standard drivers */
575  
576  /**
577 @@ -230,6 +233,9 @@ struct jtag_interface *jtag_interfaces[] = {
578  #if BUILD_CMSIS_DAP == 1
579                 &cmsis_dap_interface,
580  #endif
581 +#if BUILD_BBG_SWD == 1
582 +               &bbg_swd_interface,
583 +#endif
584  #endif /* standard drivers */
585                 NULL,
586         };
587 -- 
588 2.1.4
589