From 5832d8a42a16b862462d7cd91f2b986198a08ed5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 1 Jul 2016 11:51:17 +1200 Subject: [PATCH] Clean up common SWD stuff. --- src/Makefile | 3 +- src/adiv5_swdp.c | 10 ++ src/include/swdptap.h | 8 +- src/platforms/{stm32 => common}/swdptap.c | 103 +++--------------- src/platforms/libftdi/swdptap.c | 97 ++--------------- src/platforms/tm4c/swdptap.c | 124 ---------------------- src/swdptap_generic.c | 79 ++++++++++++++ 7 files changed, 120 insertions(+), 304 deletions(-) rename src/platforms/{stm32 => common}/swdptap.c (57%) delete mode 100644 src/platforms/tm4c/swdptap.c create mode 100644 src/swdptap_generic.c diff --git a/src/Makefile b/src/Makefile index 7080875..5549277 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) -VPATH += platforms/common $(PLATFORM_DIR) +VPATH += $(PLATFORM_DIR) platforms/common ENABLE_DEBUG ?= ifneq ($(V), 1) @@ -53,6 +53,7 @@ SRC = \ stm32l0.c \ stm32l4.c \ swdptap.c \ + swdptap_generic.c \ target.c \ include $(PLATFORM_DIR)/Makefile.inc diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index f396c7d..d62a18e 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -50,6 +50,16 @@ int adiv5_swdp_scan(void) ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); swdptap_init(); + + /* Switch from JTAG to SWD mode */ + swdptap_seq_out(0xFFFF, 16); + for(int i = 0; i < 50; i++) + swdptap_bit_out(1); + swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + for(int i = 0; i < 50; i++) + swdptap_bit_out(1); + swdptap_seq_out(0, 16); + /* Read the SW-DP IDCODE register to syncronise */ /* This could be done with adiv_swdp_low_access(), but this doesn't * allow the ack to be checked here. */ diff --git a/src/include/swdptap.h b/src/include/swdptap.h index 3263a1d..c51a28c 100644 --- a/src/include/swdptap.h +++ b/src/include/swdptap.h @@ -22,10 +22,14 @@ #define __SWDPTAP_H int swdptap_init(void); -void swdptap_reset(void); +/* Primitive functions */ +bool swdptap_bit_in(void); +void swdptap_bit_out(bool val); + +/* High level functions, provided as weak in swdptap_generic.c */ uint32_t swdptap_seq_in(int ticks); -uint8_t swdptap_seq_in_parity(uint32_t *data, int ticks); +bool swdptap_seq_in_parity(uint32_t *data, int ticks); void swdptap_seq_out(uint32_t MS, int ticks); void swdptap_seq_out_parity(uint32_t MS, int ticks); diff --git a/src/platforms/stm32/swdptap.c b/src/platforms/common/swdptap.c similarity index 57% rename from src/platforms/stm32/swdptap.c rename to src/platforms/common/swdptap.c index e7049d3..bcc3ccb 100644 --- a/src/platforms/stm32/swdptap.c +++ b/src/platforms/common/swdptap.c @@ -20,24 +20,24 @@ /* This file implements the low-level SW-DP interface. */ -#include - #include "general.h" - #include "swdptap.h" -#include "gdb_packet.h" +int swdptap_init(void) +{ + return 0; +} static void swdptap_turnaround(uint8_t dir) { static uint8_t olddir = 0; - DEBUG("%s", dir ? "\n-> ":"\n<- "); - /* Don't turnaround if direction not changing */ if(dir == olddir) return; olddir = dir; + DEBUG("%s", dir ? "\n-> ":"\n<- "); + if(dir) SWDIO_MODE_FLOAT(); gpio_set(SWCLK_PORT, SWCLK_PIN); @@ -46,10 +46,12 @@ static void swdptap_turnaround(uint8_t dir) SWDIO_MODE_DRIVE(); } -static uint8_t swdptap_bit_in(void) +bool swdptap_bit_in(void) { uint16_t ret; + swdptap_turnaround(1); + ret = gpio_get(SWDIO_PORT, SWDIO_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); @@ -59,95 +61,14 @@ static uint8_t swdptap_bit_in(void) return ret != 0; } -static void swdptap_bit_out(uint8_t val) +void swdptap_bit_out(bool val) { DEBUG("%d", val); + swdptap_turnaround(0); + gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); } -int swdptap_init(void) -{ - /* This must be investigated in more detail. - * As described in STM32 Reference Manual... */ - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); - - return 0; -} - - -void swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) swdptap_bit_out(1); -} - - -uint32_t swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) ret |= index; - index <<= 1; - } - - return ret; -} - - -uint8_t swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if(swdptap_bit_in()) parity ^= 1; - - return parity; -} - - -void swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - - -void swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} - diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index 6aafa7d..c48fb1a 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -29,9 +29,7 @@ #include "general.h" #include "swdptap.h" -static void swdptap_turnaround(uint8_t dir); -static uint8_t swdptap_bit_in(void); -static void swdptap_bit_out(uint8_t val); +static uint8_t olddir = 0; int swdptap_init(void) { @@ -46,33 +44,17 @@ int swdptap_init(void) } assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2); - - /* This must be investigated in more detail. - * As described in STM32 Reference Manual... */ - swdptap_seq_out(0xFFFF, 16); - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); + olddir = 0; return 0; } -void swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) - swdptap_bit_out(1); -} - static void swdptap_turnaround(uint8_t dir) { - static uint8_t olddir = 0; - platform_buffer_flush(); - if(dir == olddir) return; + if (dir == olddir) + return; olddir = dir; if(dir) /* SWDIO goes to input */ @@ -85,10 +67,12 @@ static void swdptap_turnaround(uint8_t dir) assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0); } -static uint8_t swdptap_bit_in(void) +bool swdptap_bit_in(void) { uint8_t ret; + swdptap_turnaround(1); + ftdi_read_pins(ftdic, &ret); ret &= 0x08; ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2); @@ -96,75 +80,16 @@ static uint8_t swdptap_bit_in(void) return ret; } -static void swdptap_bit_out(uint8_t val) +void swdptap_bit_out(bool val) { uint8_t buf[3] = "\xA0\xA1\xA0"; - if(val) { + swdptap_turnaround(0); + + if (val) { for(int i = 0; i < 3; i++) buf[i] |= 0x08; } platform_buffer_write(buf, 3); } -uint32_t swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while (ticks--) { - if (swdptap_bit_in()) - ret |= index; - index <<= 1; - } - - return ret; -} - -uint8_t swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while (ticks--) { - if (swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if (swdptap_bit_in()) - parity ^= 1; - - return parity; -} - -void swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while (ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - -void swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while (ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} - diff --git a/src/platforms/tm4c/swdptap.c b/src/platforms/tm4c/swdptap.c deleted file mode 100644 index 058f6ba..0000000 --- a/src/platforms/tm4c/swdptap.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "general.h" -#include "swdptap.h" - -static void swdptap_turnaround(uint8_t dir) -{ - static uint8_t olddir = 0; - - DEBUG("%s", dir ? "\n-> ":"\n<- "); - - /* Don't turnaround if direction not changing */ - if(dir == olddir) return; - olddir = dir; - - if(dir) - SWDIO_MODE_FLOAT(); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); - if(!dir) - SWDIO_MODE_DRIVE(); -} - -static uint8_t swdptap_bit_in(void) -{ - uint16_t ret; - - ret = gpio_get(SWDIO_PORT, SWDIO_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); - - DEBUG("%d", ret?1:0); - - return ret != 0; -} - -static void swdptap_bit_out(uint8_t val) -{ - DEBUG("%d", val); - - gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); -} - -int -swdptap_init(void) -{ - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); - - return 0; -} - -void -swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) swdptap_bit_out(1); -} - -uint32_t -swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) ret |= index; - index <<= 1; - } - - return ret; -} - -uint8_t -swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if(swdptap_bit_in()) parity ^= 1; - - return parity; -} - -void -swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - -void -swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} diff --git a/src/swdptap_generic.c b/src/swdptap_generic.c new file mode 100644 index 0000000..13ee02f --- /dev/null +++ b/src/swdptap_generic.c @@ -0,0 +1,79 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2016 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "general.h" +#include "swdptap.h" + +uint32_t __attribute__((weak)) +swdptap_seq_in(int ticks) +{ + uint32_t index = 1; + uint32_t ret = 0; + + while (ticks--) { + if (swdptap_bit_in()) + ret |= index; + index <<= 1; + } + + return ret; +} + +bool __attribute__((weak)) +swdptap_seq_in_parity(uint32_t *ret, int ticks) +{ + uint32_t index = 1; + uint8_t parity = 0; + *ret = 0; + + while (ticks--) { + if (swdptap_bit_in()) { + *ret |= index; + parity ^= 1; + } + index <<= 1; + } + if (swdptap_bit_in()) + parity ^= 1; + + return parity; +} + +void __attribute__((weak)) +swdptap_seq_out(uint32_t MS, int ticks) +{ + while (ticks--) { + swdptap_bit_out(MS & 1); + MS >>= 1; + } +} + +void __attribute__((weak)) +swdptap_seq_out_parity(uint32_t MS, int ticks) +{ + uint8_t parity = 0; + + while (ticks--) { + swdptap_bit_out(MS & 1); + parity ^= MS; + MS >>= 1; + } + swdptap_bit_out(parity & 1); +} +