From 1ca9f234f7527396da91bfc1f98cb05c305c6472 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 19 Nov 2020 21:36:59 +0100 Subject: [PATCH] Infrastructure for setting maximum SWJ frequency. Implement for BMP/firmware on STM32. --- src/command.c | 27 ++++++ src/include/general.h | 4 + src/include/platform_support.h | 3 + src/include/timing.h | 1 + src/platforms/common/jtagtap.c | 110 +++++++++++++++------ src/platforms/common/swdptap.c | 124 ++++++++++++++++-------- src/platforms/hosted/bmp_remote.c | 34 +++++++ src/platforms/hosted/bmp_remote.h | 2 + src/platforms/hosted/platform.c | 28 ++++++ src/platforms/launchpad-icdi/platform.c | 11 +++ src/platforms/launchpad-icdi/platform.h | 1 + src/platforms/pc/cl_utils.c | 20 +++- src/platforms/pc/cl_utils.h | 1 + src/platforms/stm32/timing_stm32.c | 27 ++++++ src/platforms/stm32/timing_stm32.h | 1 + src/remote.c | 9 ++ src/remote.h | 4 + 17 files changed, 338 insertions(+), 69 deletions(-) diff --git a/src/command.c b/src/command.c index 6f7f1f00..9f15c211 100644 --- a/src/command.c +++ b/src/command.c @@ -49,6 +49,7 @@ static bool cmd_help(target *t, int argc, char **argv); static bool cmd_jtag_scan(target *t, int argc, char **argv); static bool cmd_swdp_scan(target *t, int argc, char **argv); +static bool cmd_frequency(target *t, int argc, char **argv); static bool cmd_targets(target *t, int argc, char **argv); static bool cmd_morse(target *t, int argc, char **argv); static bool cmd_halt_timeout(target *t, int argc, const char **argv); @@ -70,6 +71,7 @@ const struct command_s cmd_list[] = { {"help", (cmd_handler)cmd_help, "Display help for monitor commands"}, {"jtag_scan", (cmd_handler)cmd_jtag_scan, "Scan JTAG chain for devices" }, {"swdp_scan", (cmd_handler)cmd_swdp_scan, "Scan SW-DP for devices" }, + {"frequency", (cmd_handler)cmd_frequency, "set minimum high and low times" }, {"targets", (cmd_handler)cmd_targets, "Display list of available targets" }, {"morse", (cmd_handler)cmd_morse, "Display morse error message" }, {"halt_timeout", (cmd_handler)cmd_halt_timeout, "Timeout (ms) to wait until Cortex-M is halted: (Default 2000)" }, @@ -258,6 +260,31 @@ bool cmd_swdp_scan(target *t, int argc, char **argv) } +bool cmd_frequency(target *t, int argc, char **argv) +{ + (void)t; + if (argc == 2) { + char *p; + uint32_t frequency = strtol(argv[1], &p, 10); + switch(*p) { + case 'k': + frequency *= 1000; + break; + case 'M': + frequency *= 1000*1000; + break; + } + platform_max_frequency_set(frequency); + } + uint32_t freq = platform_max_frequency_get(); + if (freq == FREQ_FIXED) + gdb_outf("SWJ freq fixed\n"); + else + gdb_outf("Max SWJ freq %08" PRIx32 "\n", freq); + return true; + +} + static void display_target(int i, target *t, void *context) { (void)context; diff --git a/src/include/general.h b/src/include/general.h index 429bf58f..ba86da22 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -37,6 +37,8 @@ #include "platform.h" #include "platform_support.h" +extern uint32_t delay_cnt; + enum BMP_DEBUG { BMP_DEBUG_NONE = 0, BMP_DEBUG_INFO = 1, @@ -48,6 +50,8 @@ enum BMP_DEBUG { BMP_DEBUG_STDOUT = 0x8000, }; +#define FREQ_FIXED 0xffffffff + #if PC_HOSTED == 0 /* For BMP debug output on a firmware BMP platform, using * BMP PC-Hosted is the preferred way. Printing DEBUG_WARN diff --git a/src/include/platform_support.h b/src/include/platform_support.h index 968440a5..59720cb4 100644 --- a/src/include/platform_support.h +++ b/src/include/platform_support.h @@ -45,5 +45,8 @@ bool platform_srst_get_val(void); bool platform_target_get_power(void); void platform_target_set_power(bool power); void platform_request_boot(void); +void platform_max_frequency_set(uint32_t frequency); +uint32_t platform_max_frequency_get(void); + #endif diff --git a/src/include/timing.h b/src/include/timing.h index 4a55f185..2d235081 100644 --- a/src/include/timing.h +++ b/src/include/timing.h @@ -24,6 +24,7 @@ struct platform_timeout { uint32_t time; }; +extern int32_t swj_delay_cnt; uint32_t platform_time_ms(void); #endif /* __TIMING_H */ diff --git a/src/platforms/common/jtagtap.c b/src/platforms/common/jtagtap.c index a319a6b2..24c858ff 100644 --- a/src/platforms/common/jtagtap.c +++ b/src/platforms/common/jtagtap.c @@ -70,12 +70,15 @@ static void jtagtap_reset(void) static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI) { uint16_t ret; + register volatile int32_t cnt; gpio_set_val(TMS_PORT, TMS_PIN, dTMS); gpio_set_val(TDI_PORT, TDI_PIN, dTDI); gpio_set(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); ret = gpio_get(TDO_PORT, TDO_PIN); gpio_clear(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt - 2; cnt > 0; cnt--); //DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %d\n", dTMS, dTDI, ret); @@ -86,13 +89,27 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks) { gpio_set_val(TDI_PORT, TDI_PIN, 1); int data = MS & 1; - while(ticks) { - gpio_set_val(TMS_PORT, TMS_PIN, data); - gpio_set(TCK_PORT, TCK_PIN); - MS >>= 1; - data = MS & 1; - ticks--; - gpio_clear(TCK_PORT, TCK_PIN); + register volatile int32_t cnt; + if (swd_delay_cnt) { + while(ticks) { + gpio_set_val(TMS_PORT, TMS_PIN, data); + gpio_set(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); + MS >>= 1; + data = MS & 1; + ticks--; + gpio_clear(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); + } + } else { + while(ticks) { + gpio_set_val(TMS_PORT, TMS_PIN, data); + gpio_set(TCK_PORT, TCK_PIN); + MS >>= 1; + data = MS & 1; + ticks--; + gpio_clear(TCK_PORT, TCK_PIN); + } } } @@ -102,42 +119,81 @@ static void jtagtap_tdi_tdo_seq( uint8_t index = 1; gpio_set_val(TMS_PORT, TMS_PIN, 0); uint8_t res = 0; - while(ticks > 1) { - gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); - gpio_set(TCK_PORT, TCK_PIN); - if (gpio_get(TDO_PORT, TDO_PIN)) { - res |= index; + register volatile int32_t cnt; + if (swd_delay_cnt) { + while(ticks > 1) { + gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); + gpio_set(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); + if (gpio_get(TDO_PORT, TDO_PIN)) { + res |= index; + } + if(!(index <<= 1)) { + *DO = res; + res = 0; + index = 1; + DI++; DO++; + } + ticks--; + gpio_clear(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); } - if(!(index <<= 1)) { - *DO = res; - res = 0; - index = 1; - DI++; DO++; + } else { + while(ticks > 1) { + gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); + gpio_set(TCK_PORT, TCK_PIN); + if (gpio_get(TDO_PORT, TDO_PIN)) { + res |= index; + } + if(!(index <<= 1)) { + *DO = res; + res = 0; + index = 1; + DI++; DO++; + } + ticks--; + gpio_clear(TCK_PORT, TCK_PIN); } - ticks--; - gpio_clear(TCK_PORT, TCK_PIN); } gpio_set_val(TMS_PORT, TMS_PIN, final_tms); gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); gpio_set(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); if (gpio_get(TDO_PORT, TDO_PIN)) { res |= index; } *DO = res; gpio_clear(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); } static void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t index = 1; - while(ticks--) { - gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms); - gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); - gpio_set(TCK_PORT, TCK_PIN); - if(!(index <<= 1)) { - index = 1; - DI++; + register volatile int32_t cnt; + if (swd_delay_cnt) { + while(ticks--) { + gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms); + gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); + gpio_set(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); + if(!(index <<= 1)) { + index = 1; + DI++; + } + gpio_clear(TCK_PORT, TCK_PIN); + for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--); + } + } else { + while(ticks--) { + gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms); + gpio_set_val(TDI_PORT, TDI_PIN, *DI & index); + gpio_set(TCK_PORT, TCK_PIN); + if(!(index <<= 1)) { + index = 1; + DI++; + } + gpio_clear(TCK_PORT, TCK_PIN); } - gpio_clear(TCK_PORT, TCK_PIN); } } diff --git a/src/platforms/common/swdptap.c b/src/platforms/common/swdptap.c index 65f863ec..8043d8f8 100644 --- a/src/platforms/common/swdptap.c +++ b/src/platforms/common/swdptap.c @@ -22,6 +22,7 @@ #include "general.h" #include "swdptap.h" +#include "timing.h" enum { SWDIO_STATUS_FLOAT = 0, @@ -39,6 +40,7 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks) static void swdptap_turnaround(int dir) { static int olddir = SWDIO_STATUS_FLOAT; + register volatile int32_t cnt; /* Don't turnaround if direction not changing */ if(dir == olddir) return; @@ -51,10 +53,9 @@ static void swdptap_turnaround(int dir) if(dir == SWDIO_STATUS_FLOAT) SWDIO_MODE_FLOAT(); gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); if(dir == SWDIO_STATUS_DRIVE) SWDIO_MODE_DRIVE(); } @@ -64,21 +65,30 @@ static uint32_t swdptap_seq_in(int ticks) uint32_t index = 1; uint32_t ret = 0; int len = ticks; + register volatile int32_t cnt; swdptap_turnaround(SWDIO_STATUS_FLOAT); - while (len--) { - int res; - res = gpio_get(SWDIO_PORT, SWDIO_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - if (res) - ret |= index; - index <<= 1; - gpio_clear(SWCLK_PORT, SWCLK_PIN); + if (swd_delay_cnt) { + while (len--) { + int res; + res = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + ret |= (res) ? index : 0; + index <<= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + } + } else { + volatile int res; + while (len--) { + res = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + ret |= (res) ? index : 0; + 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); @@ -92,26 +102,35 @@ static bool swdptap_seq_in_parity(uint32_t *ret, int ticks) uint32_t res = 0; bool bit; int len = ticks; + register volatile int32_t cnt; swdptap_turnaround(SWDIO_STATUS_FLOAT); - while (len--) { - bit = gpio_get(SWDIO_PORT, SWDIO_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - if (bit) - res |= index; - index <<= 1; - gpio_clear(SWCLK_PORT, SWCLK_PIN); + if (swd_delay_cnt) { + while (len--) { + bit = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + res |= (bit) ? index : 0; + index <<= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + } + } else { + while (len--) { + bit = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + res |= (bit) ? index : 0; + index <<= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } } int parity = __builtin_popcount(res); bit = gpio_get(SWDIO_PORT, SWDIO_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN); - if (bit) - parity++; - else - gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + parity += (bit) ? 1 : 0; gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); #ifdef DEBUG_SWD_BITS for (int i = 0; i < len; i++) DEBUG("%d", (res & (1 << i)) ? 1 : 0); @@ -128,14 +147,25 @@ static void swdptap_seq_out(uint32_t MS, int ticks) for (int i = 0; i < ticks; i++) DEBUG("%d", (MS & (1 << i)) ? 1 : 0); #endif + register volatile int32_t cnt; swdptap_turnaround(SWDIO_STATUS_DRIVE); gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); - while (ticks--) { - gpio_set(SWCLK_PORT, SWCLK_PIN); - MS >>= 1; - gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); - gpio_clear(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); + if (swd_delay_cnt) { + while (ticks--) { + gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + MS >>= 1; + gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); + gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + } + } else { + while (ticks--) { + gpio_set(SWCLK_PORT, SWCLK_PIN); + MS >>= 1; + gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); + gpio_clear(SWCLK_PORT, SWCLK_PIN); + } } } @@ -146,20 +176,32 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks) for (int i = 0; i < ticks; i++) DEBUG("%d", (MS & (1 << i)) ? 1 : 0); #endif + register volatile int32_t cnt; swdptap_turnaround(SWDIO_STATUS_DRIVE); gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); MS >>= 1; - while (ticks--) { - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); - MS >>= 1; - gpio_clear(SWCLK_PORT, SWCLK_PIN); + if (swd_delay_cnt) { + while (ticks--) { + gpio_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); + MS >>= 1; + gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); + } + } else { + while (ticks--) { + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1); + 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_set(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); gpio_clear(SWCLK_PORT, SWCLK_PIN); + for(cnt = swd_delay_cnt; --cnt > 0;); } swd_proc_t swd_proc; diff --git a/src/platforms/hosted/bmp_remote.c b/src/platforms/hosted/bmp_remote.c index b6d97f18..66d1b92a 100644 --- a/src/platforms/hosted/bmp_remote.c +++ b/src/platforms/hosted/bmp_remote.c @@ -128,6 +128,40 @@ bool remote_srst_get_val(void) return (construct[1] == '1'); } +void remote_max_frequency_set(uint32_t freq) +{ + uint8_t construct[REMOTE_MAX_MSG_SIZE]; + int s; + s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_FREQ_SET_STR, + freq); + platform_buffer_write(construct, s); + + s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); + + if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + DEBUG_WARN("Update Firmware to allow to set max SWJ frequency\n"); + } +} + +uint32_t remote_max_frequency_get(void) +{ + uint8_t construct[REMOTE_MAX_MSG_SIZE]; + int s; + + s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,"%s", + REMOTE_FREQ_GET_STR); + platform_buffer_write(construct, s); + + s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); + + if ((!s) || (construct[0] == REMOTE_RESP_ERR)) + return FREQ_FIXED; + + uint32_t freq[1]; + unhexify(freq, (const char*)&construct[1], 4); + return freq[0]; +} + const char *remote_target_voltage(void) { static uint8_t construct[REMOTE_MAX_MSG_SIZE]; diff --git a/src/platforms/hosted/bmp_remote.h b/src/platforms/hosted/bmp_remote.h index 5d135a38..c61cb026 100644 --- a/src/platforms/hosted/bmp_remote.h +++ b/src/platforms/hosted/bmp_remote.h @@ -37,6 +37,8 @@ const char *remote_target_voltage(void); void remote_target_set_power(bool power); void remote_srst_set_val(bool assert); bool remote_srst_get_val(void); +void remote_max_frequency_set(uint32_t freq); +uint32_t remote_max_frequency_get(void); const char *platform_target_voltage(void); void remote_adiv5_dp_defaults(ADIv5_DP_t *dp); void remote_add_jtag_dev(int i, const jtag_dev_t *jtag_dev); diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 8df0dbe5..8ee10169 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -109,6 +109,8 @@ void platform_init(int argc, char **argv) default: exit(-1); } + if (cl_opts.opt_max_swj_frequency) + platform_max_frequency_set(cl_opts.opt_max_swj_frequency); int ret = -1; if (cl_opts.opt_mode != BMP_MODE_DEBUG) { ret = cl_execute(&cl_opts); @@ -318,6 +320,32 @@ bool platform_srst_get_val(void) return false; } +void platform_max_frequency_set(uint32_t freq) +{ + if (!freq) + return; + switch (info.bmp_type) { + case BMP_TYPE_BMP: + remote_max_frequency_set(freq); + break; + default: + DEBUG_WARN("Setting max SWJ frequency not yet implemented\n"); + break; + } +} + +uint32_t platform_max_frequency_get(void) +{ + switch (info.bmp_type) { + case BMP_TYPE_BMP: + return remote_max_frequency_get(); + default: + DEBUG_WARN("Reading max SWJ frequency not yet implemented\n"); + break; + } + return false; +} + void platform_buffer_flush(void) { switch (info.bmp_type) { diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 5a78063c..b415336c 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -37,6 +37,8 @@ volatile platform_timeout * volatile head_timeout; uint8_t running_status; static volatile uint32_t time_ms; +uint32_t swd_delay_cnt = 0; + void sys_tick_handler(void) { trace_tick(); @@ -140,3 +142,12 @@ void platform_request_boot(void) { } +void platform_max_frequency_set(uint32_t freq) +{ + (void)freq; +} + +uint32_t platform_max_frequency_get(void) +{ + return 0; +} diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 7ed96367..d86fcede 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -25,6 +25,7 @@ #define PLATFORM_IDENT "(Launchpad ICDI) " extern uint8_t running_status; +extern uint32_t swd_delay_cnt; #define TMS_PORT GPIOA_BASE #define TMS_PIN GPIO3 diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 6283d561..664d7eb8 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -138,6 +138,7 @@ static void cl_help(char **argv) DEBUG_WARN("Run mode related options:\n"); DEBUG_WARN("\tDefault mode is to start the debug server at :2000\n"); DEBUG_WARN("\t-j\t\t: Use JTAG. SWD is default.\n"); + DEBUG_WARN("\t-f\t\t: Set minimum high and low times of SWJ waveform.\n"); DEBUG_WARN("\t-C\t\t: Connect under reset\n"); DEBUG_WARN("\t-t\t\t: Scan SWD or JTAG and display information about \n" "\t\t\t connected devices\n"); @@ -166,7 +167,8 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_target_dev = 1; opt->opt_flash_size = 16 * 1024 *1024; opt->opt_flash_start = 0xffffffff; - while((c = getopt(argc, argv, "eEhHv:d:s:I:c:CnltVtTa:S:jpP:rR")) != -1) { + opt->opt_max_swj_frequency = 4000000; + while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:CnltVtTa:S:jpP:rR")) != -1) { switch(c) { case 'c': if (optarg) @@ -200,6 +202,21 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) if (optarg) opt->opt_device = optarg; break; + case 'f': + if (optarg) { + char *p; + uint32_t frequency = strtol(optarg, &p, 10); + switch(*p) { + case 'k': + frequency *= 1000; + break; + case 'M': + frequency *= 1000*1000; + break; + } + opt->opt_max_swj_frequency = frequency; + } + break; case 's': if (optarg) opt->opt_serial = optarg; @@ -273,6 +290,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) DEBUG_WARN("Ignoring filename in reset/test mode\n"); opt->opt_flash_file = NULL; } + DEBUG_WARN("opt freq %" PRIu32 "\n", opt->opt_max_swj_frequency); } static void display_target(int i, target *t, void *context) diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index 6cff3b81..81aedc66 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -54,6 +54,7 @@ typedef struct BMP_CL_OPTIONS_s { int opt_debuglevel; int opt_target_dev; uint32_t opt_flash_start; + uint32_t opt_max_swj_frequency; size_t opt_flash_size; }BMP_CL_OPTIONS_t; diff --git a/src/platforms/stm32/timing_stm32.c b/src/platforms/stm32/timing_stm32.c index ca10de3f..dbf5cc3a 100644 --- a/src/platforms/stm32/timing_stm32.c +++ b/src/platforms/stm32/timing_stm32.c @@ -25,6 +25,7 @@ uint8_t running_status; static volatile uint32_t time_ms; +uint32_t swd_delay_cnt = 0; void platform_timing_init(void) { @@ -60,3 +61,29 @@ uint32_t platform_time_ms(void) return time_ms; } +/* Assume some USED_SWD_CYCLES per clock + * and CYCLES_PER_CNT Cycles per delay loop cnt with 2 delay loops per clock + */ + +/* Values for STM32F103 at 72 MHz */ +#define USED_SWD_CYCLES 22 +#define CYCLES_PER_CNT 10 +void platform_max_frequency_set(uint32_t freq) +{ + int divisor = rcc_ahb_frequency - USED_SWD_CYCLES * freq; + if (divisor < 0) { + swd_delay_cnt = 0; + return; + } + divisor /= 2; + swd_delay_cnt = divisor/(CYCLES_PER_CNT * freq); + if ((swd_delay_cnt * (CYCLES_PER_CNT * freq)) < (unsigned int)divisor) + swd_delay_cnt++; +} + +uint32_t platform_max_frequency_get(void) +{ + uint32_t ret = rcc_ahb_frequency; + ret /= USED_SWD_CYCLES + CYCLES_PER_CNT * swd_delay_cnt; + return ret; +} diff --git a/src/platforms/stm32/timing_stm32.h b/src/platforms/stm32/timing_stm32.h index 76909019..9e5db18a 100644 --- a/src/platforms/stm32/timing_stm32.h +++ b/src/platforms/stm32/timing_stm32.h @@ -19,6 +19,7 @@ #ifndef __TIMING_STM32_H #define __TIMING_STM32_H +extern uint32_t swd_delay_cnt; extern uint8_t running_status; void platform_timing_init(void); diff --git a/src/remote.c b/src/remote.c index 10fc65ef..f24f8768 100644 --- a/src/remote.c +++ b/src/remote.c @@ -269,6 +269,7 @@ void remotePacketProcessGEN(uint8_t i, char *packet) { (void)i; + uint32_t freq; switch (packet[1]) { case REMOTE_VOLTAGE: _respondS(REMOTE_RESP_OK,platform_target_voltage()); @@ -282,6 +283,14 @@ void remotePacketProcessGEN(uint8_t i, char *packet) case REMOTE_SRST_GET: _respond(REMOTE_RESP_OK,platform_srst_get_val()); break; + case REMOTE_FREQ_SET: + platform_max_frequency_set( remotehston(8, packet + 2)); + _respond(REMOTE_RESP_OK, 0); + break; + case REMOTE_FREQ_GET: + freq = platform_max_frequency_get(); + _respond_buf(REMOTE_RESP_OK, (uint8_t*)&freq, 4); + break; case REMOTE_PWR_SET: #ifdef PLATFORM_HAS_POWER_SWITCH diff --git a/src/remote.h b/src/remote.h index 94eee009..65f3bb95 100644 --- a/src/remote.h +++ b/src/remote.h @@ -66,6 +66,8 @@ #define REMOTE_TDITDO_TMS 'D' #define REMOTE_TDITDO_NOTMS 'd' #define REMOTE_IN_PAR 'I' +#define REMOTE_FREQ_SET 'F' +#define REMOTE_FREQ_GET 'f' #define REMOTE_IN 'i' #define REMOTE_NEXT 'N' #define REMOTE_OUT_PAR 'O' @@ -106,6 +108,8 @@ #define REMOTE_VOLTAGE_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_VOLTAGE, REMOTE_EOM, 0 } #define REMOTE_SRST_SET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_SRST_SET, '%', 'c', REMOTE_EOM, 0 } #define REMOTE_SRST_GET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_SRST_GET, REMOTE_EOM, 0 } +#define REMOTE_FREQ_SET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_FREQ_SET, '%', '0', '8', 'x', REMOTE_EOM, 0 } +#define REMOTE_FREQ_GET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_FREQ_GET, REMOTE_EOM, 0 } #define REMOTE_PWR_SET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_PWR_SET, '%', 'c', REMOTE_EOM, 0 } #define REMOTE_PWR_GET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_PWR_GET, REMOTE_EOM, 0 }