From e54a826745ae298a4eb555f3d76dfcdd571211b9 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 23 Jan 2018 20:15:16 +0100 Subject: [PATCH] common/swdptap.c: Speed up by "unrolling" swd.._seq_...() for GPIO. Try to have sensible setup/hold times by evenntually duplicated or logically useless port commands. Loading code to RAM on a STM32L476 got up from 46 to 83 kB/sec. --- src/platforms/common/swdptap.c | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/platforms/common/swdptap.c b/src/platforms/common/swdptap.c index 64cdc58a..321ce5b2 100644 --- a/src/platforms/common/swdptap.c +++ b/src/platforms/common/swdptap.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* This file implements the low-level SW-DP interface. */ +/* This file implements the SW-DP interface. */ #include "general.h" #include "swdptap.h" @@ -43,6 +43,7 @@ static void swdptap_turnaround(uint8_t dir) if(dir) SWDIO_MODE_FLOAT(); gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); if(!dir) SWDIO_MODE_DRIVE(); @@ -56,6 +57,7 @@ bool swdptap_bit_in(void) ret = gpio_get(SWDIO_PORT, SWDIO_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); #ifdef DEBUG_SWD_BITS @@ -65,6 +67,64 @@ bool swdptap_bit_in(void) return ret != 0; } +uint32_t +swdptap_seq_in(int ticks) +{ + uint32_t index = 1; + uint32_t ret = 0; + int len = ticks; + + swdptap_turnaround(1); + while (len--) { + int res; + res = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + if (res) + ret |= index; + index <<= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } + +#ifdef DEBUG_SWD_BITS + for (int i = 0; i < len; i++) + DEBUG("%d", (ret & (1 << i)) ? 1 : 0); +#endif + return ret; +} + +bool +swdptap_seq_in_parity(uint32_t *ret, int ticks) +{ + uint32_t index = 1; + uint8_t parity = 0; + uint32_t res = 0; + bool bit; + int len = ticks; + + swdptap_turnaround(1); + while (len--) { + bit = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + if (bit) { + res |= index; + parity ^= 1; + } + index <<= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } + bit = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + if (bit) + parity ^= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); +#ifdef DEBUG_SWD_BITS + for (int i = 0; i < len; i++) + DEBUG("%d", (res & (1 << i)) ? 1 : 0); +#endif + *ret = res; + return parity; +} + void swdptap_bit_out(bool val) { #ifdef DEBUG_SWD_BITS @@ -75,6 +135,48 @@ void swdptap_bit_out(bool val) gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); } +void +swdptap_seq_out(uint32_t MS, int ticks) +{ + int data = MS & 1; +#ifdef DEBUG_SWD_BITS + for (int i = 0; i < ticks; i++) + DEBUG("%d", (MS & (1 << i)) ? 1 : 0); +#endif + swdptap_turnaround(0); + while (ticks--) { + gpio_set_val(SWDIO_PORT, SWDIO_PIN, data); + gpio_set(SWCLK_PORT, SWCLK_PIN); + MS >>= 1; + data = MS & 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } +} +void +swdptap_seq_out_parity(uint32_t MS, int ticks) +{ + uint8_t parity = 0; + int data = MS & 1; +#ifdef DEBUG_SWD_BITS + for (int i = 0; i < ticks; i++) + DEBUG("%d", (MS & (1 << i)) ? 1 : 0); +#endif + swdptap_turnaround(0); + + while (ticks--) { + gpio_set_val(SWDIO_PORT, SWDIO_PIN, data); + gpio_set(SWCLK_PORT, SWCLK_PIN); + parity ^= MS; + MS >>= 1; + data = MS & 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } + gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity & 1); + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_clear(SWCLK_PORT, SWCLK_PIN); +}