diff --git a/doc/tutorial.md b/doc/tutorial.md index 929aa3250..ad64a8db8 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -19,6 +19,17 @@ The size may be followed by an optional "k" or "m" to multiply the given value b When flashing a file, a checksum is calculated for the binary file, both in md5 and the sum algorithm. The latter is also used by the official ST-Link utility tool from STMicroelectronics as described in the document: [`UM0892 - User manual - STM32 ST-LINK utility software description`](https://www.st.com/resource/en/user_manual/cd00262073-stm32-stlink-utility-software-description-stmicroelectronics.pdf). +#### --freq=n[k][m] + +(since v1.6.1) + +You can specify the frequency of SWD/JTAG interface, to override the default 1800KHz configuration. This option accpets decimal only (5K or 1.8M). `Hz` is left out in this option. Valid frequencies are `5K, 15K, 25K, 50K, 100K, 125K, 240K, 480K, 950K, 1200K(1.2M), 1800K(1.8M), 4000K(4M)` + +#### --opt + +(since v1.6.1, optional; enabled by default from v1.0.0 to v1.6.0) + +You can enable the optimization to skip flashing empty (0x00 or 0xff) bytes at the end of binary file. May cause some garbage data left after a flash. ## Solutions to common problems ### a) STLINK/v1 driver: Issue with Kernel Extension (kext) (macOS 10.11 and later only) diff --git a/include/stlink.h b/include/stlink.h index 74c366d1c..b8080fd5e 100644 --- a/include/stlink.h +++ b/include/stlink.h @@ -151,7 +151,7 @@ typedef struct flash_loader { // transport layer verboseness: 0 for no debug info, 10 for lots int verbose; - int opt; + int opt; // set by main() in tools/flash.c, empty tail bytes drop optimization uint32_t core_id; // set by stlink_core_id(), result from STLINK_DEBUGREADCOREID uint32_t chip_id; // set by stlink_load_device_params(), used to identify flash and sram int core_stat; // set by stlink_status(), values STLINK_CORE_xxxxx @@ -159,6 +159,8 @@ typedef struct flash_loader { char serial[STLINK_SERIAL_MAX_SIZE]; int serial_size; + int freq; // set by stlink_open_usb(), values: STLINK_SWDCLK_xxx_DIVISOR + enum stlink_flash_type flash_type; // stlink_chipid_params.flash_type, set by stlink_load_device_params(), values: STLINK_FLASH_TYPE_xxx bool has_dual_bank; diff --git a/include/stlink/tools/flash.h b/include/stlink/tools/flash.h index 8c3f7d766..a912a14aa 100644 --- a/include/stlink/tools/flash.h +++ b/include/stlink/tools/flash.h @@ -25,10 +25,11 @@ struct flash_opts enum flash_area area; uint32_t val; size_t flash_size; /* --flash=n[k][m] */ - int opt; + int opt; /* enable empty tail data drop optimization */ + int freq; /* --freq=n[k][m] frequency of JTAG/SWD */ }; -#define FLASH_OPTS_INITIALIZER {0, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define FLASH_OPTS_INITIALIZER {0, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} int flash_get_opts(struct flash_opts* o, int ac, char** av); diff --git a/src/st-util/gdb-server.c b/src/st-util/gdb-server.c index a3839cfc8..20954821b 100644 --- a/src/st-util/gdb-server.c +++ b/src/st-util/gdb-server.c @@ -87,9 +87,9 @@ static void cleanup(int signum) { static stlink_t* do_connect(st_state_t *st) { stlink_t *sl = NULL; if (serial_specified) { - sl = stlink_open_usb(st->logging_level, st->reset, serialnumber); + sl = stlink_open_usb(st->logging_level, st->reset, serialnumber, 0); } else { - sl = stlink_open_usb(st->logging_level, st->reset, NULL); + sl = stlink_open_usb(st->logging_level, st->reset, NULL, 0); } return sl; } diff --git a/src/stlink-gui/gui.c b/src/stlink-gui/gui.c index 5d5a422d5..6e9d59b1e 100644 --- a/src/stlink-gui/gui.c +++ b/src/stlink-gui/gui.c @@ -490,7 +490,7 @@ static void connect_button_cb (GtkWidget *widget, gpointer data) { /* try version 1 then version 2 */ gui->sl = stlink_v1_open(0, 1); if (gui->sl == NULL) - gui->sl = stlink_open_usb(0, 1, NULL); + gui->sl = stlink_open_usb(0, 1, NULL, 0); if (gui->sl == NULL) { stlink_gui_set_info_error_message (gui, "Failed to connect to STLink."); return; diff --git a/src/tools/flash.c b/src/tools/flash.c index 841b93c3c..3a83daf8a 100644 --- a/src/tools/flash.c +++ b/src/tools/flash.c @@ -28,9 +28,9 @@ static void cleanup(int signum) { static void usage(void) { - puts("command line: ./st-flash [--debug] [--reset] [--opt] [--serial ] [--format ] [--flash=] {read|write} [addr] [size]"); - puts("command line: ./st-flash [--debug] [--serial ] erase"); - puts("command line: ./st-flash [--debug] [--serial ] reset"); + puts("command line: ./st-flash [--debug] [--reset] [--opt] [--serial ] [--format ] [--flash=] [--freq=] {read|write} [addr] [size]"); + puts("command line: ./st-flash [--debug] [--freq=] [--serial ] erase"); + puts("command line: ./st-flash [--debug] [--freq=] [--serial ] reset"); puts(" , and : Use hex format."); puts(" : Use decimal, octal or hex (prefix 0xXXX) format, optionally followed by k=KB, or m=MB (eg. --flash=128k)"); puts(" : Can be 'binary' (default) or 'ihex', although must be specified for binary format only."); @@ -56,7 +56,7 @@ int main(int ac, char** av) printf("st-flash %s\n", STLINK_VERSION); - sl = stlink_open_usb(o.log_level, 1, (char *)o.serial); + sl = stlink_open_usb(o.log_level, 1, (char *)o.serial, o.freq); if (sl == NULL) { return -1; diff --git a/src/tools/flash_opts.c b/src/tools/flash_opts.c index 044527a8b..a5c9d287f 100644 --- a/src/tools/flash_opts.c +++ b/src/tools/flash_opts.c @@ -149,6 +149,56 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av) { return -1; } + else if (strcmp(av[0], "--freq") == 0 || starts_with(av[0], "--freq=")) { + const char* freq; + if (strcmp(av[0], "--freq") == 0) { + ac--; + av++; + if (ac < 1) return -1; + freq = av[0]; + } + else { + freq = av[0] + strlen("--freq="); + } + if (strcmp(freq, "5K") == 0 || strcmp(freq, "5k") == 0) { + o->freq = 5; + } + else if (strcmp(freq, "15K") == 0 || strcmp(freq, "15k") == 0) { + o->freq = 15; + } + else if (strcmp(freq, "25K") == 0 || strcmp(freq, "25k") == 0) { + o->freq = 25; + } + else if (strcmp(freq, "50K") == 0 || strcmp(freq, "50k") == 0) { + o->freq = 50; + } + else if (strcmp(freq, "100K") == 0 || strcmp(freq, "100k") == 0) { + o->freq = 100; + } + else if (strcmp(freq, "125K") == 0 || strcmp(freq, "125k") == 0) { + o->freq = 125; + } + else if (strcmp(freq, "240K") == 0 || strcmp(freq, "240k") == 0) { + o->freq = 240; + } + else if (strcmp(freq, "480K") == 0 || strcmp(freq, "480k") == 0) { + o->freq = 480; + } + else if (strcmp(freq, "950K") == 0 || strcmp(freq, "950k") == 0) { + o->freq = 950; + } + else if (strcmp(freq, "1200K") == 0 || strcmp(freq, "1200k") == 0 || strcmp(freq, "1.2M") == 0 || strcmp(freq, "1.2m") == 0) { + o->freq = 1200; + } + else if (strcmp(freq, "1800K") == 0 || strcmp(freq, "1800k") == 0 || strcmp(freq, "1.8M") == 0 || strcmp(freq, "1.8m") == 0) { + o->freq = 1800; + } + else if (strcmp(freq, "4000K") == 0 || strcmp(freq, "4000k") == 0 || strcmp(freq, "4M") == 0 || strcmp(freq, "4m") == 0) { + o->freq = 4000; + } + else + return -1; + } else if (strcmp(av[0], "--format") == 0 || starts_with(av[0], "--format=")) { const char * format; if (strcmp(av[0], "--format") == 0) { diff --git a/src/tools/info.c b/src/tools/info.c index 3ebbba8de..45d484270 100644 --- a/src/tools/info.c +++ b/src/tools/info.c @@ -81,7 +81,7 @@ static stlink_t *stlink_open_first(void) stlink_t* sl = NULL; sl = stlink_v1_open(0, 1); if (sl == NULL) - sl = stlink_open_usb(0, 1, NULL); + sl = stlink_open_usb(0, 1, NULL, 0); return sl; } diff --git a/src/usb.c b/src/usb.c index 4e7a2983f..148ad7652 100644 --- a/src/usb.c +++ b/src/usb.c @@ -873,7 +873,7 @@ static stlink_backend_t _stlink_usb_backend = { _stlink_usb_set_swdclk }; -stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[STLINK_SERIAL_MAX_SIZE]) +stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq) { stlink_t* sl = NULL; struct stlink_libusb* slu = NULL; @@ -1041,10 +1041,51 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[ST stlink_exit_dfu_mode(sl); } + + sl->freq = freq; // set the speed before entering the mode // as the chip discovery phase should be done at this speed too // Set the stlink clock speed (default is 1800kHz) - stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); + DLOG("JTAG/SWD freq set to %d\n", freq); + switch (freq) { + case 5: + stlink_set_swdclk(sl, STLINK_SWDCLK_5KHZ_DIVISOR); + break; + case 15: + stlink_set_swdclk(sl, STLINK_SWDCLK_15KHZ_DIVISOR); + break; + case 25: + stlink_set_swdclk(sl, STLINK_SWDCLK_25KHZ_DIVISOR); + break; + case 50: + stlink_set_swdclk(sl, STLINK_SWDCLK_50KHZ_DIVISOR); + break; + case 100: + stlink_set_swdclk(sl, STLINK_SWDCLK_100KHZ_DIVISOR); + break; + case 125: + stlink_set_swdclk(sl, STLINK_SWDCLK_125KHZ_DIVISOR); + break; + case 240: + stlink_set_swdclk(sl, STLINK_SWDCLK_240KHZ_DIVISOR); + break; + case 480: + stlink_set_swdclk(sl, STLINK_SWDCLK_480KHZ_DIVISOR); + break; + case 950: + stlink_set_swdclk(sl, STLINK_SWDCLK_950KHZ_DIVISOR); + break; + case 1200: + stlink_set_swdclk(sl, STLINK_SWDCLK_1P2MHZ_DIVISOR); + break; + case 0: case 1800: + stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); + break; + case 4000: + stlink_set_swdclk(sl, STLINK_SWDCLK_4MHZ_DIVISOR); + break; + } + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); @@ -1147,7 +1188,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { continue; } - stlink_t *sl = stlink_open_usb(0, 1, serial); + stlink_t *sl = stlink_open_usb(0, 1, serial, 0); if (!sl) { ELOG("Failed to open USB device %#06x:%#06x\n", desc.idVendor, desc.idProduct); continue; diff --git a/src/usb.h b/src/usb.h index 968f38ba4..061042e8d 100644 --- a/src/usb.h +++ b/src/usb.h @@ -68,7 +68,7 @@ extern "C" { * @retval NULL Error while opening the stlink * @retval !NULL Stlink found and ready to use */ - stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[STLINK_SERIAL_MAX_SIZE]); + stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[STLINK_SERIAL_MAX_SIZE], int freq); size_t stlink_probe_usb(stlink_t **stdevs[]); void stlink_probe_usb_free(stlink_t **stdevs[], size_t size); diff --git a/tests/flash.c b/tests/flash.c index 96a43a2c3..d47b3564d 100644 --- a/tests/flash.c +++ b/tests/flash.c @@ -66,6 +66,7 @@ static bool execute_test(const struct Test * test) { ret &= (opts.size == test->opts.size); ret &= (opts.reset == test->opts.reset); ret &= (opts.log_level == test->opts.log_level); + ret &= (opts.freq == test->opts.freq); ret &= (opts.format == test->opts.format); } @@ -83,6 +84,7 @@ static struct Test tests[] = { .size = 0x1000, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset write test.bin 0x80000000", 0, @@ -93,6 +95,51 @@ static struct Test tests[] = { .size = 0, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, + .format = FLASH_FORMAT_BINARY } + }, + { "--debug --freq 5k --reset write test.bin 0x80000000", 0, + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 5, + .format = FLASH_FORMAT_BINARY } + }, + { "--debug --freq 15K --reset write test.bin 0x80000000", 0, + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 15, + .format = FLASH_FORMAT_BINARY } + }, + { "--debug --freq=5k --reset write test.bin 0x80000000", 0, + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 5, + .format = FLASH_FORMAT_BINARY } + }, + { "--debug --freq=6k --reset write test.bin 0x80000000", -1, + { .cmd = FLASH_CMD_WRITE, + .serial = { 0 }, + .filename = "test.bin", + .addr = 0x80000000, + .size = 0, + .reset = 1, + .log_level = DEBUG_LOG_LEVEL, + .freq = 6, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset read test.bin 0x80000000 1000", 0, @@ -103,6 +150,7 @@ static struct Test tests[] = { .size = 1000, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset read test.bin 0x80000000 1k", 0, @@ -113,6 +161,7 @@ static struct Test tests[] = { .size = 1024, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset read test.bin 0x80000000 1M", 0, @@ -123,6 +172,7 @@ static struct Test tests[] = { .size = 1048576, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset write test.bin 0x80000000", 0, @@ -133,6 +183,7 @@ static struct Test tests[] = { .size = 0, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "erase", 0, @@ -143,6 +194,7 @@ static struct Test tests[] = { .size = 0, .reset = 0, .log_level = STND_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--debug --reset --format=ihex write test.hex", 0, @@ -153,6 +205,7 @@ static struct Test tests[] = { .size = 0, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_IHEX } }, { "--debug --reset --format=binary write test.hex", -1, FLASH_OPTS_INITIALIZER }, @@ -167,6 +220,7 @@ static struct Test tests[] = { .size = 0, .reset = 0, .log_level = STND_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, { "--serial=A1020304 erase", 0, @@ -177,6 +231,7 @@ static struct Test tests[] = { .size = 0, .reset = 0, .log_level = STND_LOG_LEVEL, + .freq = 0, .format = FLASH_FORMAT_BINARY } }, }; diff --git a/tests/usb.c b/tests/usb.c index d4098834d..5165ea563 100644 --- a/tests/usb.c +++ b/tests/usb.c @@ -9,7 +9,7 @@ int main(int ac, char** av) { stlink_t* sl; struct stlink_reg regs; - sl = stlink_open_usb(10, 1, NULL); + sl = stlink_open_usb(10, 1, NULL, 0); if (sl != NULL) { printf("-- version\n"); stlink_version(sl);