You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
(50) |
Sep
|
Oct
|
Nov
|
Dec
|
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-29 05:37:11
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 291d1511aab3eee6a181510e1b1ff9282d47e69c (commit) from 70babcc00b5f495e4d0dbac9bad88d78592d2779 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 291d1511aab3eee6a181510e1b1ff9282d47e69c Author: Antonio Borneo <bor...@gm...> Date: Fri Aug 23 15:12:57 2019 +0200 openocd: fix minor inconsistencies after renaming "adapter" command Replace in the code any reference to the deprecated commands. Change-Id: I75d28064017d664990b4024967900f32e196230a Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5282 Tested-by: jenkins Reviewed-by: Marc Schink <de...@za...> Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/jtag/core.c b/src/jtag/core.c index 111b122d9..24d645a49 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1519,9 +1519,9 @@ int adapter_init(struct command_context *cmd_ctx) return ERROR_OK; if (!adapter_driver) { - /* nothing was previously specified by "interface" command */ + /* nothing was previously specified by "adapter driver" command */ LOG_ERROR("Debug Adapter has to be specified, " - "see \"interface\" command"); + "see \"adapter driver\" command"); return ERROR_JTAG_INVALID_INTERFACE; } @@ -1538,7 +1538,7 @@ int adapter_init(struct command_context *cmd_ctx) if (CLOCK_MODE_UNSELECTED == clock_mode) { LOG_ERROR("An adapter speed is not selected in the init script." - " Insert a call to adapter_khz or jtag_rclk to proceed."); + " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed."); return ERROR_JTAG_INIT_FAILED; } diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index c0728214c..3d2693c0a 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -1628,10 +1628,10 @@ static int cmsis_dap_execute_queue(void) static int cmsis_dap_speed(int speed) { if (speed > DAP_MAX_CLOCK) - LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed); + LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed); if (speed == 0) { - LOG_ERROR("RTCK not supported. Set nonzero adapter_khz."); + LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\"."); return ERROR_JTAG_NOT_IMPLEMENTED; } diff --git a/src/svf/svf.c b/src/svf/svf.c index 759ba5263..5d87c8944 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -990,7 +990,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) /* TODO: set jtag speed to */ if (svf_para.frequency > 0) { command_run_linef(cmd_ctx, - "adapter_khz %d", + "adapter speed %d", (int)svf_para.frequency / 1000); LOG_DEBUG("\tfrequency = %f", svf_para.frequency); } ----------------------------------------------------------------------- Summary of changes: src/jtag/core.c | 6 +++--- src/jtag/drivers/cmsis_dap_usb.c | 4 ++-- src/svf/svf.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-29 05:36:15
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 70babcc00b5f495e4d0dbac9bad88d78592d2779 (commit) from 5280eb618a8cab4639f1eca567472db7e5024d13 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 70babcc00b5f495e4d0dbac9bad88d78592d2779 Author: Oleksij Rempel <li...@re...> Date: Wed Aug 14 13:17:51 2019 +0200 move ftdi_location deprecation helper to proper place Change-Id: I927d4e918acbf321aea1dd7a8de95fbaa8fbbbf0 Signed-off-by: Oleksij Rempel <li...@re...> Reviewed-on: http://openocd.zylin.com/5278 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 440d8ea74..2ac857158 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -211,4 +211,9 @@ proc interface_list args { eval adapter list $args } +proc ftdi_location args { + echo "DEPRECATED! use 'adapter usb location' not 'ftdi_location'" + eval adapter usb location $args +} + # END MIGRATION AIDS diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 4d4426f98..cf844e1f6 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -221,9 +221,3 @@ proc cortex_a8 args { echo "DEPRECATED! use 'cortex_a' not 'cortex_a8'" eval cortex_a $args } - -# deprecated ftdi cmds -proc ftdi_location args { - echo "DEPRECATED! use 'adapter usb location' not 'ftdi_location'" - eval adapter usb location $args -} ----------------------------------------------------------------------- Summary of changes: src/jtag/startup.tcl | 5 +++++ src/target/startup.tcl | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-29 05:34:22
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 5280eb618a8cab4639f1eca567472db7e5024d13 (commit) from e7e681ac2b66b9eb585b7dfb8eed6c5bd2efefa9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5280eb618a8cab4639f1eca567472db7e5024d13 Author: Oleksij Rempel <o.r...@pe...> Date: Mon Nov 19 12:56:48 2018 +0100 jtag: adapter: rework adapter related commands currently we have different types of same command group: - starting with adapter_* - starting with interface* - without adapter or interface prefix. Since interface name is already used, we can only use "adapter" command group by keeping old commands as well. Change-Id: Id0a1cb63a2ea6860c67ae1e7a3a06a37ddf464f4 Signed-off-by: Oleksij Rempel <o.r...@pe...> Reviewed-on: http://openocd.zylin.com/4774 Reviewed-by: Marc Schink <de...@za...> Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/doc/openocd.texi b/doc/openocd.texi index cb1c5b791..b203656fc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -1574,7 +1574,7 @@ solution just avoids using that instruction with JTAG debuggers. If both the chip and the board support adaptive clocking, use the @command{jtag_rclk} command, in case your board is used with JTAG adapter which -also supports it. Otherwise use @command{adapter_khz}. +also supports it. Otherwise use @command{adapter speed}. Set the slow rate at the beginning of the reset sequence, and the faster rate as soon as the clocks are at full speed. @@ -1614,12 +1614,12 @@ proc init_board @{@} @{ reset_config trst_and_srst trst_pulls_srst $_TARGETNAME configure -event reset-start @{ - adapter_khz 100 + adapter speed 100 @} $_TARGETNAME configure -event reset-init @{ enable_fast_clock - adapter_khz 10000 + adapter speed 10000 @} @} @end example @@ -2344,22 +2344,22 @@ interface jlink Most adapters need a bit more configuration than that. -@section Interface Configuration +@section Adapter Configuration -The interface command tells OpenOCD what type of debug adapter you are +The @command{adapter driver} command tells OpenOCD what type of debug adapter you are using. Depending on the type of adapter, you may need to use one or more additional commands to further identify or configure the adapter. -@deffn {Config Command} {interface} name -Use the interface driver @var{name} to connect to the +@deffn {Config Command} {adapter driver} name +Use the adapter driver @var{name} to connect to the target. @end deffn -@deffn Command {interface_list} +@deffn Command {adapter list} List the debug adapter drivers that have been built into the running copy of OpenOCD. @end deffn -@deffn Command {interface transports} transport_name+ +@deffn Command {adapter transports} transport_name+ Specifies the transports supported by this debug adapter. The adapter driver builds-in similar knowledge; use this only when external configuration (such as jumpering) changes what @@ -2368,7 +2368,7 @@ the hardware can support. -@deffn Command {adapter_name} +@deffn Command {adapter name} Returns the name of the debug adapter driver being used. @end deffn @@ -2993,7 +2993,7 @@ you may encounter a problem. @deffn Command {parport_toggling_time} [nanoseconds] Displays how many nanoseconds the hardware needs to toggle TCK; the parport driver uses this value to obey the -@command{adapter_khz} configuration. +@command{adapter speed} configuration. When the optional @var{nanoseconds} parameter is given, that setting is changed before displaying the current value. @@ -3004,7 +3004,7 @@ To measure the toggling time with a logic analyzer or a digital storage oscilloscope, follow the procedure below: @example > parport_toggling_time 1000 -> adapter_khz 500 +> adapter speed 500 @end example This sets the maximum JTAG clock speed of the hardware, but the actual speed probably deviates from the requested 500 kHz. @@ -3015,14 +3015,15 @@ Update the setting to match your measurement: @example > parport_toggling_time <measured nanoseconds> @end example -Now the clock speed will be a better match for @command{adapter_khz rate} -commands given in OpenOCD scripts and event handlers. +Now the clock speed will be a better match for @command{adapter speed} +command given in OpenOCD scripts and event handlers. You can do something similar with many digital multimeters, but note that you'll probably need to run the clock continuously for several seconds before it decides what clock rate to show. Adjust the toggling time up or down until the measured clock rate is a good -match for the adapter_khz rate you specified; be conservative. +match with the rate you specified in the @command{adapter speed} command; +be conservative. @end quotation @end deffn @@ -3329,10 +3330,10 @@ However, it introduces delays to synchronize clocks; so it may not be the fastest solution. @b{NOTE:} Script writers should consider using @command{jtag_rclk} -instead of @command{adapter_khz}, but only for (ARM) cores and boards +instead of @command{adapter speed}, but only for (ARM) cores and boards which support adaptive clocking. -@deffn {Command} adapter_khz max_speed_kHz +@deffn {Command} adapter speed max_speed_kHz A non-zero speed is in KHZ. Hence: 3000 is 3mhz. JTAG interfaces usually support a limited number of speeds. The speed actually used won't be faster @@ -3462,7 +3463,7 @@ stops issuing the reset. For example, there may be chip or board requirements that all reset pulses last for at least a certain amount of time; and reset buttons commonly have hardware debouncing. -Use the @command{adapter_nsrst_delay} and @command{jtag_ntrst_delay} +Use the @command{adapter srst delay} and @command{jtag_ntrst_delay} commands to say when extra delays are needed. @item @emph{Drive type} ... Reset lines often have a pullup @@ -3502,13 +3503,13 @@ needing to cope with both architecture and board specific constraints. @section Commands for Handling Resets -@deffn {Command} adapter_nsrst_assert_width milliseconds +@deffn {Command} adapter srst pulse_width milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nSRST (active-low system reset) before allowing it to be deasserted. @end deffn -@deffn {Command} adapter_nsrst_delay milliseconds +@deffn {Command} adapter srst delay milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nSRST (active-low system reset) before starting new JTAG operations. When a board has a reset button connected to SRST line it will @@ -4889,7 +4890,7 @@ the target clocks are fully set up.) before @command{reset-assert-pre} is called. This is the most robust place to use @command{jtag_rclk} -or @command{adapter_khz} to switch to a low JTAG clock rate, +or @command{adapter speed} to switch to a low JTAG clock rate, when reset disables PLLs needed to use a fast clock. @item @b{resume-start} @* Before any target is resumed @@ -10736,7 +10737,7 @@ To set the JTAG frequency use the command: @example # Example: 1.234MHz -adapter_khz 1234 +adapter speed 1234 @end example diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index e2782a777..af75917a3 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -66,7 +66,7 @@ static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv) return JIM_OK; } -COMMAND_HANDLER(interface_transport_command) +COMMAND_HANDLER(adapter_transports_command) { char **transports; int retval; @@ -85,12 +85,12 @@ COMMAND_HANDLER(interface_transport_command) return retval; } -COMMAND_HANDLER(handle_interface_list_command) +COMMAND_HANDLER(handle_adapter_list_command) { - if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0) + if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; - command_print(CMD, "The following debug interfaces are available:"); + command_print(CMD, "The following debug adapters are available:"); for (unsigned i = 0; NULL != adapter_drivers[i]; i++) { const char *name = adapter_drivers[i]->name; command_print(CMD, "%u: %s", i + 1, name); @@ -99,7 +99,7 @@ COMMAND_HANDLER(handle_interface_list_command) return ERROR_OK; } -COMMAND_HANDLER(handle_interface_command) +COMMAND_HANDLER(handle_adapter_driver_command) { int retval; @@ -134,7 +134,7 @@ COMMAND_HANDLER(handle_interface_command) */ LOG_ERROR("The specified debug interface was not found (%s)", CMD_ARGV[0]); - CALL_COMMAND_HANDLER(handle_interface_list_command); + CALL_COMMAND_HANDLER(handle_adapter_list_command); return ERROR_JTAG_INVALID_INTERFACE; } @@ -355,7 +355,7 @@ next: return ERROR_OK; } -COMMAND_HANDLER(handle_adapter_nsrst_delay_command) +COMMAND_HANDLER(handle_adapter_srst_delay_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -365,11 +365,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_delay_command) jtag_set_nsrst_delay(delay); } - command_print(CMD, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay()); + command_print(CMD, "adapter srst delay: %u", jtag_get_nsrst_delay()); return ERROR_OK; } -COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command) +COMMAND_HANDLER(handle_adapter_srst_pulse_width_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -379,11 +379,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command) jtag_set_nsrst_assert_width(width); } - command_print(CMD, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width()); + command_print(CMD, "adapter srst pulse_width: %u", jtag_get_nsrst_assert_width()); return ERROR_OK; } -COMMAND_HANDLER(handle_adapter_khz_command) +COMMAND_HANDLER(handle_adapter_speed_command) { if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -524,92 +524,103 @@ static const struct command_registration adapter_usb_command_handlers[] = { }; #endif /* MINIDRIVER */ -static const struct command_registration adapter_command_handlers[] = { -#ifndef HAVE_JTAG_MINIDRIVER_H +static const struct command_registration adapter_srst_command_handlers[] = { { - .name = "usb", + .name = "delay", + .handler = handle_adapter_srst_delay_command, .mode = COMMAND_ANY, - .help = "usb adapter command group", - .usage = "", - .chain = adapter_usb_command_handlers, - }, -#endif /* MINIDRIVER */ - { - .name = "assert", - .handler = handle_adapter_reset_de_assert, - .mode = COMMAND_EXEC, - .help = "Controls SRST and TRST lines.", - .usage = "|deassert [srst|trst [assert|deassert srst|trst]]", + .help = "delay after deasserting SRST in ms", + .usage = "[milliseconds]", }, { - .name = "deassert", - .handler = handle_adapter_reset_de_assert, - .mode = COMMAND_EXEC, - .help = "Controls SRST and TRST lines.", - .usage = "|assert [srst|trst [deassert|assert srst|trst]]", + .name = "pulse_width", + .handler = handle_adapter_srst_pulse_width_command, + .mode = COMMAND_ANY, + .help = "SRST assertion pulse width in ms", + .usage = "[milliseconds]", }, COMMAND_REGISTRATION_DONE }; -static const struct command_registration interface_command_handlers[] = { +static const struct command_registration adapter_command_handlers[] = { { - .name = "adapter", - .mode = COMMAND_ANY, - .help = "adapter command group", - .usage = "", - .chain = adapter_command_handlers, + .name = "driver", + .handler = handle_adapter_driver_command, + .mode = COMMAND_CONFIG, + .help = "Select a debug adapter driver", + .usage = "driver_name", }, { - .name = "adapter_khz", - .handler = handle_adapter_khz_command, + .name = "speed", + .handler = handle_adapter_speed_command, .mode = COMMAND_ANY, .help = "With an argument, change to the specified maximum " "jtag speed. For JTAG, 0 KHz signifies adaptive " - " clocking. " + "clocking. " "With or without argument, display current setting.", .usage = "[khz]", }, { - .name = "adapter_name", + .name = "list", + .handler = handle_adapter_list_command, + .mode = COMMAND_ANY, + .help = "List all built-in debug adapter drivers", + .usage = "", + }, + { + .name = "name", .mode = COMMAND_ANY, .jim_handler = jim_adapter_name, .help = "Returns the name of the currently " "selected adapter (driver)", }, { - .name = "adapter_nsrst_delay", - .handler = handle_adapter_nsrst_delay_command, + .name = "srst", .mode = COMMAND_ANY, - .help = "delay after deasserting SRST in ms", - .usage = "[milliseconds]", + .help = "srst adapter command group", + .usage = "", + .chain = adapter_srst_command_handlers, }, { - .name = "adapter_nsrst_assert_width", - .handler = handle_adapter_nsrst_assert_width_command, + .name = "transports", + .handler = adapter_transports_command, + .mode = COMMAND_CONFIG, + .help = "Declare transports the adapter supports.", + .usage = "transport ... ", + }, +#ifndef HAVE_JTAG_MINIDRIVER_H + { + .name = "usb", .mode = COMMAND_ANY, - .help = "delay after asserting SRST in ms", - .usage = "[milliseconds]", + .help = "usb adapter command group", + .usage = "", + .chain = adapter_usb_command_handlers, }, +#endif /* MINIDRIVER */ { - .name = "interface", - .handler = handle_interface_command, - .mode = COMMAND_CONFIG, - .help = "Select a debug adapter interface (driver)", - .usage = "driver_name", + .name = "assert", + .handler = handle_adapter_reset_de_assert, + .mode = COMMAND_EXEC, + .help = "Controls SRST and TRST lines.", + .usage = "|deassert [srst|trst [assert|deassert srst|trst]]", }, { - .name = "interface_transports", - .handler = interface_transport_command, - .mode = COMMAND_CONFIG, - .help = "Declare transports the interface supports.", - .usage = "transport ... ", + .name = "deassert", + .handler = handle_adapter_reset_de_assert, + .mode = COMMAND_EXEC, + .help = "Controls SRST and TRST lines.", + .usage = "|assert [srst|trst [deassert|assert srst|trst]]", }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration interface_command_handlers[] = { { - .name = "interface_list", - .handler = handle_interface_list_command, + .name = "adapter", .mode = COMMAND_ANY, - .help = "List all built-in debug adapter interfaces (drivers)", + .help = "adapter command group", .usage = "", + .chain = adapter_command_handlers, }, { .name = "reset_config", diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 355152136..440d8ea74 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -120,18 +120,18 @@ proc jtag_ntrst_assert_width args { # FIXME phase these aids out after about April 2011 # proc jtag_khz args { - echo "DEPRECATED! use 'adapter_khz' not 'jtag_khz'" - eval adapter_khz $args + echo "DEPRECATED! use 'adapter speed' not 'jtag_khz'" + eval adapter speed $args } proc jtag_nsrst_delay args { - echo "DEPRECATED! use 'adapter_nsrst_delay' not 'jtag_nsrst_delay'" - eval adapter_nsrst_delay $args + echo "DEPRECATED! use 'adapter srst delay' not 'jtag_nsrst_delay'" + eval adapter srst delay $args } proc jtag_nsrst_assert_width args { - echo "DEPRECATED! use 'adapter_nsrst_assert_width' not 'jtag_nsrst_assert_width'" - eval adapter_nsrst_assert_width $args + echo "DEPRECATED! use 'adapter srst pulse_width' not 'jtag_nsrst_assert_width'" + eval adapter srst pulse_width $args } proc jtag_reset args { @@ -176,4 +176,39 @@ proc stlink args { eval hla $args } +proc adapter_khz args { + echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'" + eval adapter speed $args +} + +proc adapter_name args { + echo "DEPRECATED! use 'adapter name' not 'adapter_name'" + eval adapter name $args +} + +proc adapter_nsrst_delay args { + echo "DEPRECATED! use 'adapter srst delay' not 'adapter_nsrst_delay'" + eval adapter srst delay $args +} + +proc adapter_nsrst_assert_width args { + echo "DEPRECATED! use 'adapter srst pulse_width' not 'adapter_nsrst_assert_width'" + eval adapter srst pulse_width $args +} + +proc interface args { + echo "DEPRECATED! use 'adapter driver' not 'interface'" + eval adapter driver $args +} + +proc interface_transports args { + echo "DEPRECATED! use 'adapter transports' not 'interface_transports'" + eval adapter transports $args +} + +proc interface_list args { + echo "DEPRECATED! use 'adapter list' not 'interface_list'" + eval adapter list $args +} + # END MIGRATION AIDS ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 45 ++++++++--------- src/jtag/adapter.c | 133 ++++++++++++++++++++++++++++----------------------- src/jtag/startup.tcl | 47 +++++++++++++++--- 3 files changed, 136 insertions(+), 89 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-27 17:04:22
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via e7e681ac2b66b9eb585b7dfb8eed6c5bd2efefa9 (commit) from c2cb4e40b80783a56d991e1e970a9fde5887551a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e7e681ac2b66b9eb585b7dfb8eed6c5bd2efefa9 Author: Tomas Vanek <va...@fb...> Date: Sat Dec 14 18:55:01 2019 +0100 flash/nor/stm32l4x: fix minor errors in flash write/async algo Fix comment of tested errors in asm src. List all relevant errors in FLASH_ERROR mask: FLASH_PROGERR was missing and any trial to re-program already programmed double word ended up in the error bit held uncleared and flash write permanetly repeating the error message until reset. Lock the bank also after unsuccesfull write_block run. Set async target algo block size to size of double word. Remove warning in case of write_block success. In case of error use LOG_ERROR instead of warning. Change-Id: Ibf6d5e306a4c2eaa43de67d636b4902c737f02f3 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5360 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> diff --git a/contrib/loaders/flash/stm32/stm32l4x.S b/contrib/loaders/flash/stm32/stm32l4x.S index 9c49016df..e0ce3cb34 100644 --- a/contrib/loaders/flash/stm32/stm32l4x.S +++ b/contrib/loaders/flash/stm32/stm32l4x.S @@ -71,7 +71,7 @@ busy: ldr r6, [r4, #STM32_FLASH_SR_OFFSET] tst r6, #0x10000 /* BSY (bit16) == 1 => operation in progress */ bne busy /* wait more... */ - tst r6, #0xfa /* PGSERR | PGPERR | PGAERR | WRPERR | PROGERR*/ + tst r6, #0xfa /* PGSERR | SIZERR | PGAERR | WRPERR | PROGERR | OPERR */ bne error /* fail... */ cmp r5, r1 /* wrap rp at end of buffer */ diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 1b54193c2..c8055cd9c 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -106,7 +106,7 @@ #define FLASH_PROGERR (1 << 3) /* Programming error */ #define FLASH_OPERR (1 << 1) /* Operation error */ #define FLASH_EOP (1 << 0) /* End of operation */ -#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGSERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR) +#define FLASH_ERROR (FLASH_PGSERR | FLASH_SIZERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_PROGERR | FLASH_OPERR) /* register unlock keys */ #define KEY1 0x45670123 @@ -577,7 +577,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last return ret; } -/* Count is in halfwords */ +/* Count is in double-words */ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { @@ -630,15 +630,15 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (double word-64bit) */ - init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* flash base */ + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* flash regs base */ buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); - buf_set_u32(reg_params[3].value, 0, 32, count / 4); + buf_set_u32(reg_params[3].value, 0, 32, count); buf_set_u32(reg_params[4].value, 0, 32, stm32l4_info->part_info->flash_regs_base); - retval = target_run_flash_async_algorithm(target, buffer, count, 2, + retval = target_run_flash_async_algorithm(target, buffer, count, 8, 0, NULL, 5, reg_params, source->address, source->size, @@ -676,7 +676,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - int retval; + int retval, retval2; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -692,14 +692,15 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) return retval; - retval = stm32l4_write_block(bank, buffer, offset, count / 2); + retval = stm32l4_write_block(bank, buffer, offset, count / 8); + + retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); + if (retval != ERROR_OK) { - LOG_WARNING("block write failed"); + LOG_ERROR("block write failed"); return retval; } - - LOG_WARNING("block write succeeded"); - return stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); + return retval2; } static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) ----------------------------------------------------------------------- Summary of changes: contrib/loaders/flash/stm32/stm32l4x.S | 2 +- src/flash/nor/stm32l4x.c | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-27 17:00:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via c2cb4e40b80783a56d991e1e970a9fde5887551a (commit) from 634e09f4e7da02a3813ac98b77bc2a4f047debbc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c2cb4e40b80783a56d991e1e970a9fde5887551a Author: Tomas Vanek <va...@fb...> Date: Sat Dec 14 16:08:32 2019 +0100 flash/nor/stm32l4x: use flash infrastructure to align write The original code paded the write chunk with random bytes by overrunning the buffer. An user can easily regard the random bytes to be a programming error. Change-Id: Ib0f47b5bc406bc6a7c32f3d929bf324a17c7c1e1 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5359 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3d1537756..1b54193c2 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -278,6 +278,10 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command) return ERROR_FAIL; /* Checkme: What better error to use?*/ bank->driver_priv = stm32l4_info; + /* The flash write must be aligned to a double word (8-bytes) boundary. + * Ask the flash infrastructure to ensure required alignment */ + bank->write_start_alignment = bank->write_end_alignment = 8; + stm32l4_info->probed = 0; return ERROR_OK; @@ -679,30 +683,15 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, return ERROR_TARGET_NOT_HALTED; } - if (offset & 0x7) { - LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", - offset); - return ERROR_FLASH_DST_BREAKS_ALIGNMENT; - } - - if (count & 0x7) { - LOG_WARNING("Padding %d bytes to keep 8-byte write size", - count & 7); - count = (count + 7) & ~7; - /* This pads the write chunk with random bytes by overrunning the - * write buffer. Padding with the erased pattern 0xff is purely - * cosmetical, as 8-byte flash words are ECC secured and the first - * write will program the ECC bits. A second write would need - * to reprogramm these ECC bits. - * But this can only be done after erase! - */ - } + /* The flash write must be aligned to a double word (8-bytes) boundary. + * The flash infrastructure ensures it, do just a security check */ + assert(offset % 8 == 0); + assert(count % 8 == 0); retval = stm32l4_unlock_reg(bank); if (retval != ERROR_OK) return retval; - /* Only full double words (8-byte) can be programmed*/ retval = stm32l4_write_block(bank, buffer, offset, count / 2); if (retval != ERROR_OK) { LOG_WARNING("block write failed"); ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-27 17:00:16
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 634e09f4e7da02a3813ac98b77bc2a4f047debbc (commit) from dc95dd036fd1ec8333472da752035fa3b0ebc369 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 634e09f4e7da02a3813ac98b77bc2a4f047debbc Author: Marc Schink <de...@za...> Date: Thu Dec 12 13:30:57 2019 +0100 tcl/board: Add config for STM32WB Nucleo board Change-Id: Ic29802306c706bcf3e261c60facd01d101c9e1ce Signed-off-by: Marc Schink <de...@za...> Reviewed-on: http://openocd.zylin.com/5358 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Ilya Kharin <ak...@gm...> diff --git a/tcl/board/st_nucleo_wb55.cfg b/tcl/board/st_nucleo_wb55.cfg new file mode 100644 index 000000000..5b5b8f779 --- /dev/null +++ b/tcl/board/st_nucleo_wb55.cfg @@ -0,0 +1,11 @@ +# +# Configuration for STM32WB55 Nucleo board (STM32WB55RGV6) +# + +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32wbx.cfg] + +reset_config srst_only ----------------------------------------------------------------------- Summary of changes: tcl/board/st_nucleo_wb55.cfg | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tcl/board/st_nucleo_wb55.cfg hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-27 09:19:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via dc95dd036fd1ec8333472da752035fa3b0ebc369 (commit) from ddbd8dcf9115cfd863e07bc1a7e5eb94f6b4372f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit dc95dd036fd1ec8333472da752035fa3b0ebc369 Author: Tomas Vanek <va...@fb...> Date: Mon Dec 16 13:08:01 2019 +0100 target/arm_cti: fix regression from Tcl_return_values series Since commit 7f260f5009a774f2d66b5f3037f8f595c6881d4d native OpenOCD command handlers should not directly use Jim_SetResult functions. The Tcl result of a native command is built as concatenation of command_print() strings and Jim_SetResult() is called after return of the command handler. Replace "wrong number of args" error messages (now not delivered to user) by simply return ERROR_COMMAND_SYNTAX_ERROR Change-Id: I40c1374a13859cefbdef68e0f1c13ab93538bd50 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5363 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index d415eb3a8..1662c7e16 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -261,14 +261,11 @@ COMMAND_HANDLER(handle_cti_dump) COMMAND_HANDLER(handle_cti_enable) { struct arm_cti_object *obj = CMD_DATA; - Jim_Interp *interp = CMD_CTX->interp; struct arm_cti *cti = &obj->cti; bool on_off; - if (CMD_ARGC != 1) { - Jim_SetResultString(interp, "wrong number of args", -1); - return ERROR_FAIL; - } + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off); @@ -278,14 +275,11 @@ COMMAND_HANDLER(handle_cti_enable) COMMAND_HANDLER(handle_cti_testmode) { struct arm_cti_object *obj = CMD_DATA; - Jim_Interp *interp = CMD_CTX->interp; struct arm_cti *cti = &obj->cti; bool on_off; - if (CMD_ARGC != 1) { - Jim_SetResultString(interp, "wrong number of args", -1); - return ERROR_FAIL; - } + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off); @@ -295,15 +289,12 @@ COMMAND_HANDLER(handle_cti_testmode) COMMAND_HANDLER(handle_cti_write) { struct arm_cti_object *obj = CMD_DATA; - Jim_Interp *interp = CMD_CTX->interp; struct arm_cti *cti = &obj->cti; int offset; uint32_t value; - if (CMD_ARGC != 2) { - Jim_SetResultString(interp, "Wrong number of args", -1); - return ERROR_FAIL; - } + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; offset = cti_find_reg_offset(CMD_ARGV[0]); if (offset < 0) @@ -317,16 +308,13 @@ COMMAND_HANDLER(handle_cti_write) COMMAND_HANDLER(handle_cti_read) { struct arm_cti_object *obj = CMD_DATA; - Jim_Interp *interp = CMD_CTX->interp; struct arm_cti *cti = &obj->cti; int offset; int retval; uint32_t value; - if (CMD_ARGC != 1) { - Jim_SetResultString(interp, "Wrong number of args", -1); - return ERROR_FAIL; - } + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; offset = cti_find_reg_offset(CMD_ARGV[0]); if (offset < 0) ----------------------------------------------------------------------- Summary of changes: src/target/arm_cti.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-27 09:17:30
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via ddbd8dcf9115cfd863e07bc1a7e5eb94f6b4372f (commit) from 60aaf14837d39393edff0df76e426232e72988f5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ddbd8dcf9115cfd863e07bc1a7e5eb94f6b4372f Author: Marek Vasut <mar...@gm...> Date: Fri Jan 10 04:24:59 2020 +0100 flash/nor/nrf5: Fix build error on OSX The chip->hwid is uint32_t , fix the print format. This was detected by TravisCI on OSX, where this triggers a build error. Change-Id: I776a7bb50e396c8fccc24500dec4750190da7982 Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5401 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Ilya Kharin <ak...@gm...> diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index d923468fd..8422589b8 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -609,7 +609,7 @@ static int nrf5_info(struct flash_bank *bank, char *buf, int buf_size) variant, &variant[2]); } else { - res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%04" PRIx16 ")", + res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%08" PRIx32 ")", chip->hwid); } if (res <= 0) ----------------------------------------------------------------------- Summary of changes: src/flash/nor/nrf5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-22 12:50:44
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 60aaf14837d39393edff0df76e426232e72988f5 (commit) from 8b7265700136d6035d2769531a6202295f7113a6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 60aaf14837d39393edff0df76e426232e72988f5 Author: Antonio Borneo <bor...@gm...> Date: Fri Jan 17 16:44:00 2020 +0100 jtag: drivers: xlnx-pcie-xvc: fix build after merge Commit [1] was submitted in gerrit well before the conflicting commit [2] get merged in master branch. While it was fine committing in master branch [1] alone, it should not be committed "as is" after [2]. Unfortunately gerrit did not complained committing [1] after [2]. The result is that master branch does not build anymore when the driver xlnx-pcie-xvc is enabled at configure time by the optional flag --enable-xlnx-pcie-xvc. Apply to the driver the required changes as in [2]. While there, remove the duplicated struct xlnx_pcie_xvc_transports and the struct field already implicitly initialized to zero. [1] ff6d0704ecd6 ("jtag: drivers: xlnx-pcie-xvc: Add support for Xilinx XVC/PCIe") [2] efd1d642220a ("adapter: switch from struct jtag_interface to adapter_driver") Change-Id: I5498479b802a231afbee1b845ae9775e1da7c728 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5402 Reviewed-by: Moritz Fischer <mo...@go...> Tested-by: jenkins Reviewed-by: Andreas Fritiofson <and...@gm...> diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index fabf0f39f..48b03ec83 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -466,16 +466,17 @@ static const struct command_registration xlnx_pcie_xvc_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const char * const xlnx_pcie_xvc_transports[] = { "jtag", NULL }; +static struct jtag_interface xlnx_pcie_xvc_interface = { + .execute_queue = &xlnx_pcie_xvc_execute_queue, +}; -struct jtag_interface xlnx_pcie_xvc_interface = { +struct adapter_driver xlnx_pcie_xvc_adapter_driver = { .name = "xlnx_pcie_xvc", + .transports = jtag_only, .commands = xlnx_pcie_xvc_command_handlers, - .transports = xlnx_pcie_xvc_transports, - .execute_queue = &xlnx_pcie_xvc_execute_queue, - .speed = NULL, - .speed_div = NULL, - .khz = NULL, + .init = &xlnx_pcie_xvc_init, .quit = &xlnx_pcie_xvc_quit, + + .jtag_ops = &xlnx_pcie_xvc_interface, }; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 356d89ecd..00b3bb502 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -118,7 +118,7 @@ extern struct adapter_driver opendous_adapter_driver; extern struct adapter_driver sysfsgpio_adapter_driver; #endif #if BUILD_XLNX_PCIE_XVC == 1 -extern struct jtag_interface xlnx_pcie_xvc_interface; +extern struct adapter_driver xlnx_pcie_xvc_adapter_driver; #endif #if BUILD_AICE == 1 extern struct adapter_driver aice_adapter_driver; @@ -229,7 +229,7 @@ struct adapter_driver *adapter_drivers[] = { &sysfsgpio_adapter_driver, #endif #if BUILD_XLNX_PCIE_XVC == 1 - &xlnx_pcie_xvc_interface, + &xlnx_pcie_xvc_adapter_driver, #endif #if BUILD_AICE == 1 &aice_adapter_driver, ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/xlnx-pcie-xvc.c | 15 ++++++++------- src/jtag/interfaces.c | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-22 05:51:04
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 8b7265700136d6035d2769531a6202295f7113a6 (commit) from d612baacaa3fef549c446053089867d7b134ccfd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8b7265700136d6035d2769531a6202295f7113a6 Author: Marek Vasut <mar...@gm...> Date: Tue Apr 2 16:44:18 2019 +0200 flash/nor/sh_qspi: Add SH QSPI driver Add driver for the SH QSPI controller. This SPI controller is often connected to the boot SPI NOR flash on R-Car Gen2 platforms. Add the following two lines to board TCL file to bind the driver on R-Car Gen2 SoC and make SRAM work area available: flash bank flash0 sh_qspi 0xe6b10000 0 0 0 ${_TARGETNAME}0 cs0 ${_TARGETNAME}0 configure -work-area-phys 0xe6300000 -work-area-virt 0xe6300000 -work-area-size 0x10000 -work-area-backup 0 To install mainline U-Boot on the board, use the following procedure: proc update_uboot {} { # SPL flash erase_sector 0 0x0 0x0 flash write_bank 0 /u-boot/spl/u-boot-spl.bin 0x0 # U-Boot flash erase_sector 0 0x5 0x6 flash write_bank 0 /u-boot/u-boot.img 0x140000 } Change-Id: Ief22f61e93bcabae37f6e371156dece6c4be3459 Signed-off-by: Marek Vasut <mar...@gm...> --- V2: - Add Makefile and linker script for the SH QSPI IO algorithm - Include the algorithm code instead of hard-coding it Reviewed-on: http://openocd.zylin.com/5143 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/contrib/loaders/flash/sh_qspi/Makefile b/contrib/loaders/flash/sh_qspi/Makefile new file mode 100644 index 000000000..2bfbad1b0 --- /dev/null +++ b/contrib/loaders/flash/sh_qspi/Makefile @@ -0,0 +1,37 @@ +CROSS_COMPILE=arm-linux-gnueabihf- +BIN2C = ../../../../src/helper/bin2char.sh + +TGT = sh_qspi +ASRC += sh_qspi.S +LDS = sh_qspi.ld + +OBJS += $(ASRC:.S=.o) + +CC=$(CROSS_COMPILE)gcc +OBJCOPY=$(CROSS_COMPILE)objcopy +OBJDUMP=$(CROSS_COMPILE)objdump +LD=$(CROSS_COMPILE)ld +NM=$(CROSS_COMPILE)nm +SIZE=$(CROSS_COMPILE)size + +CFLAGS=-Os -Wall -nostartfiles -marm -nostdinc -ffreestanding -mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access -ffunction-sections -fdata-sections -fno-common -msoft-float -pipe -march=armv7-a -mtune=generic-armv7-a +LDFLAGS=-T$(LDS) -nostdlib -Map=$(TGT).map + +all: $(TGT).inc + +%.o: %.S + $(CC) $(CFLAGS) -c $^ -o $@ + +$(TGT).elf: $(OBJS) + $(LD) $(LDFLAGS) $^ -o $@ + +$(TGT).bin: $(TGT).elf + $(OBJCOPY) $< -O binary $@ + $(NM) -n $(TGT).elf > $(TGT).sym + $(SIZE) $(TGT).elf + +$(TGT).inc: $(TGT).bin + $(BIN2C) < $< > $@ + +clean: + rm -rf *.elf *.hex *.map *.o *.disasm *.sym diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.S b/contrib/loaders/flash/sh_qspi/sh_qspi.S new file mode 100644 index 000000000..78eb1e818 --- /dev/null +++ b/contrib/loaders/flash/sh_qspi/sh_qspi.S @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * SH QSPI (Quad SPI) driver + * Copyright (C) 2019 Marek Vasut <mar...@gm...> + */ + +#define BIT(n) (1UL << (n)) +/* SH QSPI register bit masks <REG>_<BIT> */ +#define SPCR_MSTR 0x08 +#define SPCR_SPE 0x40 +#define SPSR_SPRFF 0x80 +#define SPSR_SPTEF 0x20 +#define SPPCR_IO3FV 0x04 +#define SPPCR_IO2FV 0x02 +#define SPPCR_IO1FV 0x01 +#define SPBDCR_RXBC0 BIT(0) +#define SPCMD_SCKDEN BIT(15) +#define SPCMD_SLNDEN BIT(14) +#define SPCMD_SPNDEN BIT(13) +#define SPCMD_SSLKP BIT(7) +#define SPCMD_BRDV0 BIT(2) +#define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \ + SPCMD_SPNDEN | SPCMD_SSLKP | \ + SPCMD_BRDV0 +#define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \ + SPCMD_BRDV0 +#define SPBFCR_TXRST BIT(7) +#define SPBFCR_RXRST BIT(6) +#define SPBFCR_TXTRG 0x30 +#define SPBFCR_RXTRG 0x07 + +/* SH QSPI register set */ +#define SH_QSPI_SPCR 0x00 +#define SH_QSPI_SSLP 0x01 +#define SH_QSPI_SPPCR 0x02 +#define SH_QSPI_SPSR 0x03 +#define SH_QSPI_SPDR 0x04 +#define SH_QSPI_SPSCR 0x08 +#define SH_QSPI_SPSSR 0x09 +#define SH_QSPI_SPBR 0x0a +#define SH_QSPI_SPDCR 0x0b +#define SH_QSPI_SPCKD 0x0c +#define SH_QSPI_SSLND 0x0d +#define SH_QSPI_SPND 0x0e +#define SH_QSPI_DUMMY0 0x0f +#define SH_QSPI_SPCMD0 0x10 +#define SH_QSPI_SPCMD1 0x12 +#define SH_QSPI_SPCMD2 0x14 +#define SH_QSPI_SPCMD3 0x16 +#define SH_QSPI_SPBFCR 0x18 +#define SH_QSPI_DUMMY1 0x19 +#define SH_QSPI_SPBDCR 0x1a +#define SH_QSPI_SPBMUL0 0x1c +#define SH_QSPI_SPBMUL1 0x20 +#define SH_QSPI_SPBMUL2 0x24 +#define SH_QSPI_SPBMUL3 0x28 + +.syntax unified +.arm +.text + +.macro wait_for_spsr, spsrbit + 1: ldrb r12, [r0, #SH_QSPI_SPSR] + tst r12, \spsrbit + beq 1b +.endm + +.macro sh_qspi_xfer + bl sh_qspi_cs_activate + str r6, [r0, SH_QSPI_SPBMUL0] + bl sh_qspi_xfer_common + bl sh_qspi_cs_deactivate +.endm + +.macro sh_qspi_write_enable + ldr r4, =SPIFLASH_WRITE_ENABLE + adr r5, _start + add r4, r5 + mov r5, #0x0 + mov r6, #0x1 + sh_qspi_xfer +.endm + +.macro sh_qspi_wait_till_ready + 1: ldr r4, =SPIFLASH_READ_STATUS + adr r5, _start + add r4, r5 + mov r5, #0x0 + mov r6, #0x2 + sh_qspi_xfer + and r13, #0x1 + cmp r13, #0x1 + beq 1b +.endm + +/* + * r0: controller base address + * r1: data buffer base address + * r2: BIT(31) -- page program (not read) + * BIT(30) -- 4-byte address (not 3-byte) + * BIT(29) -- 512-byte page (not 256-byte) + * BIT(27:20) -- SF command + * BIT(19:0) -- amount of data to read/write + * r3: SF target address + * + * r7: data size + * r8: page size + * + * r14: lr, link register + * r15: pc, program counter + * + * Clobber: r4, r5, r6, r7, r8 + */ + +.global _start +_start: + bic r7, r2, #0xff000000 + bic r7, r7, #0x00f00000 + + and r8, r2, #(1 << 31) + cmp r8, #(1 << 31) + beq do_page_program + +/* fast read */ + + bl sh_qspi_cs_activate + + bl sh_qspi_setup_command + add r8, r6, r7 + str r8, [r0, SH_QSPI_SPBMUL0] + bl sh_qspi_xfer_common + + mov r4, #0x0 + mov r5, r1 + mov r6, r7 + bl sh_qspi_xfer_common + + bl sh_qspi_cs_deactivate + + b end + +do_page_program: + + mov r8, #0x100 + tst r2, (1 << 29) + movne r8, #0x200 + +do_pp_next_page: + /* Check if less then page bytes left. */ + cmp r7, r8 + movlt r8, r7 + + sh_qspi_write_enable + + bl sh_qspi_cs_activate + + bl sh_qspi_setup_command + str r6, [r0, SH_QSPI_SPBMUL0] + bl sh_qspi_xfer_common + + mov r4, r1 + mov r5, #0x0 + mov r6, r8 + + bl sh_qspi_xfer_common + + bl sh_qspi_cs_deactivate + + sh_qspi_wait_till_ready + + add r1, r8 + add r3, r8 + sub r7, r8 + cmp r7, #0 + + bne do_pp_next_page + +end: + bkpt #0 + +sh_qspi_cs_activate: + /* Set master mode only */ + mov r12, #SPCR_MSTR + strb r12, [r0, SH_QSPI_SPCR] + + /* Set command */ + mov r12, #SPCMD_INIT1 + strh r12, [r0, SH_QSPI_SPCMD0] + + /* Reset transfer and receive Buffer */ + ldrb r12, [r0, SH_QSPI_SPSCR] + orr r12, #(SPBFCR_TXRST | SPBFCR_RXRST) + strb r12, [r0, SH_QSPI_SPBFCR] + + /* Clear transfer and receive Buffer control bit */ + ldrb r12, [r0, SH_QSPI_SPBFCR] + bic r12, #(SPBFCR_TXRST | SPBFCR_RXRST) + strb r12, [r0, SH_QSPI_SPBFCR] + + /* Set sequence control method. Use sequence0 only */ + mov r12, #0x00 + strb r12, [r0, SH_QSPI_SPSCR] + + /* Enable SPI function */ + ldrb r12, [r0, SH_QSPI_SPCR] + orr r12, #SPCR_SPE + strb r12, [r0, SH_QSPI_SPCR] + + mov pc, lr + +sh_qspi_cs_deactivate: + /* Disable SPI function */ + ldrb r12, [r0, SH_QSPI_SPCR] + bic r12, #SPCR_SPE + strb r12, [r0, SH_QSPI_SPCR] + + mov pc, lr + +/* + * r0, controller base address + * r4, tx buffer + * r5, rx buffer + * r6, xfer len, non-zero + * + * Upon exit, r13 contains the last byte in SPDR + * + * Clobber: r11, r12, r13 + */ +sh_qspi_xfer_common: +prepcopy: + ldr r13, [r0, #SH_QSPI_SPBFCR] + orr r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG) + mov r11, #32 + cmp r6, #32 + + biclt r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG) + movlt r11, #1 + +copy: + str r13, [r0, #SH_QSPI_SPBFCR] + + wait_for_spsr SPSR_SPTEF + + mov r12, r11 + mov r13, #0 + cmp r4, #0 + beq 3f + +2: ldrb r13, [r4], #1 + strb r13, [r0, #SH_QSPI_SPDR] + subs r12, #1 + bne 2b + b 4f + +3: strb r13, [r0, #SH_QSPI_SPDR] + subs r12, #1 + bne 3b + +4: wait_for_spsr SPSR_SPRFF + + mov r12, r11 + cmp r5, #0 + beq 6f + +5: ldrb r13, [r0, #SH_QSPI_SPDR] + strb r13, [r5], #1 + subs r12, #1 + bne 5b + b 7f + +6: ldrb r13, [r0, #SH_QSPI_SPDR] + subs r12, #1 + bne 6b + +7: subs r6, r11 + bne prepcopy + + mov pc, lr + +sh_qspi_setup_command: + ldr r4, =SPIFLASH_SCRATCH_DATA + adr r5, _start + add r4, r5 + and r12, r2, #0x0ff00000 + lsr r12, #20 + strb r12, [r4] + mov r12, r3 + strb r12, [r4, #4] + lsr r12, #8 + strb r12, [r4, #3] + lsr r12, #8 + strb r12, [r4, #2] + lsr r12, #8 + strb r12, [r4, #1] + lsr r12, #8 + mov r5, #0x0 + mov r6, #0x4 + tst r2, (1 << 30) + movne r6, #0x5 + + mov pc, lr + +SPIFLASH_READ_STATUS: .byte 0x05 /* Read Status Register */ +SPIFLASH_WRITE_ENABLE: .byte 0x06 /* Write Enable */ +SPIFLASH_NOOP: .byte 0x00 +SPIFLASH_SCRATCH_DATA: .byte 0x00, 0x0, 0x0, 0x0, 0x0 diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.inc b/contrib/loaders/flash/sh_qspi/sh_qspi.inc new file mode 100644 index 000000000..ca913923f --- /dev/null +++ b/contrib/loaders/flash/sh_qspi/sh_qspi.inc @@ -0,0 +1,37 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0xff,0x74,0xc2,0xe3,0x0f,0x76,0xc7,0xe3,0x02,0x81,0x02,0xe2,0x02,0x01,0x58,0xe3, +0x0a,0x00,0x00,0x0a,0x32,0x00,0x00,0xeb,0x6c,0x00,0x00,0xeb,0x07,0x80,0x86,0xe0, +0x1c,0x80,0x80,0xe5,0x42,0x00,0x00,0xeb,0x00,0x40,0xa0,0xe3,0x01,0x50,0xa0,0xe1, +0x07,0x60,0xa0,0xe1,0x3e,0x00,0x00,0xeb,0x39,0x00,0x00,0xeb,0x27,0x00,0x00,0xea, +0x01,0x8c,0xa0,0xe3,0x02,0x02,0x12,0xe3,0x02,0x8c,0xa0,0x13,0x08,0x00,0x57,0xe1, +0x07,0x80,0xa0,0xb1,0xcc,0x41,0x9f,0xe5,0x60,0x50,0x4f,0xe2,0x05,0x40,0x84,0xe0, +0x00,0x50,0xa0,0xe3,0x01,0x60,0xa0,0xe3,0x1d,0x00,0x00,0xeb,0x1c,0x60,0x80,0xe5, +0x2f,0x00,0x00,0xeb,0x2a,0x00,0x00,0xeb,0x19,0x00,0x00,0xeb,0x53,0x00,0x00,0xeb, +0x1c,0x60,0x80,0xe5,0x2a,0x00,0x00,0xeb,0x01,0x40,0xa0,0xe1,0x00,0x50,0xa0,0xe3, +0x08,0x60,0xa0,0xe1,0x26,0x00,0x00,0xeb,0x21,0x00,0x00,0xeb,0x88,0x41,0x9f,0xe5, +0xa8,0x50,0x4f,0xe2,0x05,0x40,0x84,0xe0,0x00,0x50,0xa0,0xe3,0x02,0x60,0xa0,0xe3, +0x0b,0x00,0x00,0xeb,0x1c,0x60,0x80,0xe5,0x1d,0x00,0x00,0xeb,0x18,0x00,0x00,0xeb, +0x01,0xd0,0x0d,0xe2,0x01,0x00,0x5d,0xe3,0xf3,0xff,0xff,0x0a,0x08,0x10,0x81,0xe0, +0x08,0x30,0x83,0xe0,0x08,0x70,0x47,0xe0,0x00,0x00,0x57,0xe3,0xda,0xff,0xff,0x1a, +0x70,0x00,0x20,0xe1,0x08,0xc0,0xa0,0xe3,0x00,0xc0,0xc0,0xe5,0x84,0xc0,0x0e,0xe3, +0xb0,0xc1,0xc0,0xe1,0x08,0xc0,0xd0,0xe5,0xc0,0xc0,0x8c,0xe3,0x18,0xc0,0xc0,0xe5, +0x18,0xc0,0xd0,0xe5,0xc0,0xc0,0xcc,0xe3,0x18,0xc0,0xc0,0xe5,0x00,0xc0,0xa0,0xe3, +0x08,0xc0,0xc0,0xe5,0x00,0xc0,0xd0,0xe5,0x40,0xc0,0x8c,0xe3,0x00,0xc0,0xc0,0xe5, +0x0e,0xf0,0xa0,0xe1,0x00,0xc0,0xd0,0xe5,0x40,0xc0,0xcc,0xe3,0x00,0xc0,0xc0,0xe5, +0x0e,0xf0,0xa0,0xe1,0x18,0xd0,0x90,0xe5,0x37,0xd0,0x8d,0xe3,0x20,0xb0,0xa0,0xe3, +0x20,0x00,0x56,0xe3,0x37,0xd0,0xcd,0xb3,0x01,0xb0,0xa0,0xb3,0x18,0xd0,0x80,0xe5, +0x03,0xc0,0xd0,0xe5,0x20,0x00,0x1c,0xe3,0xfc,0xff,0xff,0x0a,0x0b,0xc0,0xa0,0xe1, +0x00,0xd0,0xa0,0xe3,0x00,0x00,0x54,0xe3,0x04,0x00,0x00,0x0a,0x01,0xd0,0xd4,0xe4, +0x04,0xd0,0xc0,0xe5,0x01,0xc0,0x5c,0xe2,0xfb,0xff,0xff,0x1a,0x02,0x00,0x00,0xea, +0x04,0xd0,0xc0,0xe5,0x01,0xc0,0x5c,0xe2,0xfc,0xff,0xff,0x1a,0x03,0xc0,0xd0,0xe5, +0x80,0x00,0x1c,0xe3,0xfc,0xff,0xff,0x0a,0x0b,0xc0,0xa0,0xe1,0x00,0x00,0x55,0xe3, +0x04,0x00,0x00,0x0a,0x04,0xd0,0xd0,0xe5,0x01,0xd0,0xc5,0xe4,0x01,0xc0,0x5c,0xe2, +0xfb,0xff,0xff,0x1a,0x02,0x00,0x00,0xea,0x04,0xd0,0xd0,0xe5,0x01,0xc0,0x5c,0xe2, +0xfc,0xff,0xff,0x1a,0x0b,0x60,0x56,0xe0,0xd9,0xff,0xff,0x1a,0x0e,0xf0,0xa0,0xe1, +0x58,0x40,0x9f,0xe5,0x77,0x5f,0x4f,0xe2,0x05,0x40,0x84,0xe0,0xff,0xc6,0x02,0xe2, +0x2c,0xca,0xa0,0xe1,0x00,0xc0,0xc4,0xe5,0x03,0xc0,0xa0,0xe1,0x04,0xc0,0xc4,0xe5, +0x2c,0xc4,0xa0,0xe1,0x03,0xc0,0xc4,0xe5,0x2c,0xc4,0xa0,0xe1,0x02,0xc0,0xc4,0xe5, +0x2c,0xc4,0xa0,0xe1,0x01,0xc0,0xc4,0xe5,0x2c,0xc4,0xa0,0xe1,0x00,0x50,0xa0,0xe3, +0x04,0x60,0xa0,0xe3,0x01,0x01,0x12,0xe3,0x05,0x60,0xa0,0x13,0x0e,0xf0,0xa0,0xe1, +0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x02,0x00,0x00,0x20,0x02,0x00,0x00, +0x23,0x02,0x00,0x00, diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.ld b/contrib/loaders/flash/sh_qspi/sh_qspi.ld new file mode 100644 index 000000000..2683c520b --- /dev/null +++ b/contrib/loaders/flash/sh_qspi/sh_qspi.ld @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x0; + . = ALIGN(4); + .text : { + sh_qspi.o (.text*) + *(.text*) + } +} diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 34f91ce1e..12bafa2c5 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -51,6 +51,7 @@ NOR_DRIVERS = \ %D%/psoc4.c \ %D%/psoc5lp.c \ %D%/psoc6.c \ + %D%/sh_qspi.c \ %D%/sim3x.c \ %D%/spi.c \ %D%/stmsmi.c \ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 551f389de..fb43a438d 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -66,6 +66,7 @@ extern const struct flash_driver psoc5lp_flash; extern const struct flash_driver psoc5lp_eeprom_flash; extern const struct flash_driver psoc5lp_nvl_flash; extern const struct flash_driver psoc6_flash; +extern const struct flash_driver sh_qspi_flash; extern const struct flash_driver sim3x_flash; extern const struct flash_driver stellaris_flash; extern const struct flash_driver stm32f1x_flash; @@ -136,6 +137,7 @@ static const struct flash_driver * const flash_drivers[] = { &psoc5lp_eeprom_flash, &psoc5lp_nvl_flash, &psoc6_flash, + &sh_qspi_flash, &sim3x_flash, &stellaris_flash, &stm32f1x_flash, diff --git a/src/flash/nor/sh_qspi.c b/src/flash/nor/sh_qspi.c new file mode 100644 index 000000000..931b0b176 --- /dev/null +++ b/src/flash/nor/sh_qspi.c @@ -0,0 +1,912 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SH QSPI (Quad SPI) driver + * Copyright (C) 2019 Marek Vasut <mar...@gm...> + * + * Based on U-Boot SH QSPI driver + * Copyright (C) 2013 Renesas Electronics Corporation + * Copyright (C) 2013 Nobuhiro Iwamatsu <nob...@re...> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "spi.h" +#include <helper/binarybuffer.h> +#include <helper/bits.h> +#include <helper/time_support.h> +#include <helper/types.h> +#include <jtag/jtag.h> +#include <target/algorithm.h> +#include <target/arm.h> +#include <target/arm_opcodes.h> +#include <target/target.h> + +/* SH QSPI register bit masks <REG>_<BIT> */ +#define SPCR_MSTR 0x08 +#define SPCR_SPE 0x40 +#define SPSR_SPRFF 0x80 +#define SPSR_SPTEF 0x20 +#define SPPCR_IO3FV 0x04 +#define SPPCR_IO2FV 0x02 +#define SPPCR_IO1FV 0x01 +#define SPBDCR_RXBC0 BIT(0) +#define SPCMD_SCKDEN BIT(15) +#define SPCMD_SLNDEN BIT(14) +#define SPCMD_SPNDEN BIT(13) +#define SPCMD_SSLKP BIT(7) +#define SPCMD_BRDV0 BIT(2) +#define SPCMD_INIT1 (SPCMD_SCKDEN | SPCMD_SLNDEN | \ + SPCMD_SPNDEN | SPCMD_SSLKP | \ + SPCMD_BRDV0) +#define SPCMD_INIT2 (SPCMD_SPNDEN | SPCMD_SSLKP | \ + SPCMD_BRDV0) +#define SPBFCR_TXRST BIT(7) +#define SPBFCR_RXRST BIT(6) +#define SPBFCR_TXTRG 0x30 +#define SPBFCR_RXTRG 0x07 + +/* SH QSPI register set */ +#define SH_QSPI_SPCR 0x00 +#define SH_QSPI_SSLP 0x01 +#define SH_QSPI_SPPCR 0x02 +#define SH_QSPI_SPSR 0x03 +#define SH_QSPI_SPDR 0x04 +#define SH_QSPI_SPSCR 0x08 +#define SH_QSPI_SPSSR 0x09 +#define SH_QSPI_SPBR 0x0a +#define SH_QSPI_SPDCR 0x0b +#define SH_QSPI_SPCKD 0x0c +#define SH_QSPI_SSLND 0x0d +#define SH_QSPI_SPND 0x0e +#define SH_QSPI_DUMMY0 0x0f +#define SH_QSPI_SPCMD0 0x10 +#define SH_QSPI_SPCMD1 0x12 +#define SH_QSPI_SPCMD2 0x14 +#define SH_QSPI_SPCMD3 0x16 +#define SH_QSPI_SPBFCR 0x18 +#define SH_QSPI_DUMMY1 0x19 +#define SH_QSPI_SPBDCR 0x1a +#define SH_QSPI_SPBMUL0 0x1c +#define SH_QSPI_SPBMUL1 0x20 +#define SH_QSPI_SPBMUL2 0x24 +#define SH_QSPI_SPBMUL3 0x28 + +struct sh_qspi_flash_bank { + const struct flash_device *dev; + uint32_t io_base; + int probed; + struct working_area *io_algorithm; + struct working_area *source; + unsigned int buffer_size; +}; + +struct sh_qspi_target { + char *name; + uint32_t tap_idcode; + uint32_t io_base; +}; + +static const struct sh_qspi_target target_devices[] = { + /* name, tap_idcode, io_base */ + { "SH QSPI", 0x4ba00477, 0xe6b10000 }, + { NULL, 0, 0 } +}; + +static int sh_qspi_init(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + uint8_t val; + int ret; + + /* QSPI initialize */ + /* Set master mode only */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR); + if (ret != ERROR_OK) + return ret; + + /* Set SSL signal level */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SSLP, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Set MOSI signal value when transfer is in idle state */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPPCR, + SPPCR_IO3FV | SPPCR_IO2FV); + if (ret != ERROR_OK) + return ret; + + /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBR, 0x01); + if (ret != ERROR_OK) + return ret; + + /* Disable Dummy Data Transmission */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPDCR, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Set clock delay value */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPCKD, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Set SSL negation delay value */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SSLND, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Set next-access delay value */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPND, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Set equence command */ + ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0, + SPCMD_INIT2); + if (ret != ERROR_OK) + return ret; + + /* Reset transfer and receive Buffer */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val); + if (ret != ERROR_OK) + return ret; + + val |= SPBFCR_TXRST | SPBFCR_RXRST; + + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val); + if (ret != ERROR_OK) + return ret; + + /* Clear transfer and receive Buffer control bit */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val); + if (ret != ERROR_OK) + return ret; + + val &= ~(SPBFCR_TXRST | SPBFCR_RXRST); + + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val); + if (ret != ERROR_OK) + return ret; + + /* Set equence control method. Use equence0 only */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Enable SPI function */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val); + if (ret != ERROR_OK) + return ret; + + val |= SPCR_SPE; + + return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val); +} + +static int sh_qspi_cs_activate(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + uint8_t val; + int ret; + + /* Set master mode only */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR); + if (ret != ERROR_OK) + return ret; + + /* Set command */ + ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0, + SPCMD_INIT1); + if (ret != ERROR_OK) + return ret; + + /* Reset transfer and receive Buffer */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val); + if (ret != ERROR_OK) + return ret; + + val |= SPBFCR_TXRST | SPBFCR_RXRST; + + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val); + if (ret != ERROR_OK) + return ret; + + /* Clear transfer and receive Buffer control bit */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val); + if (ret != ERROR_OK) + return ret; + + val &= ~(SPBFCR_TXRST | SPBFCR_RXRST); + + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val); + if (ret != ERROR_OK) + return ret; + + /* Set equence control method. Use equence0 only */ + ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00); + if (ret != ERROR_OK) + return ret; + + /* Enable SPI function */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val); + if (ret != ERROR_OK) + return ret; + + val |= SPCR_SPE; + + return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val); +} + +static int sh_qspi_cs_deactivate(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + uint8_t val; + int ret; + + /* Disable SPI Function */ + ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val); + if (ret != ERROR_OK) + return ret; + + val &= ~SPCR_SPE; + + return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val); +} + +static int sh_qspi_wait_for_bit(struct flash_bank *bank, uint8_t reg, + uint32_t mask, bool set, + unsigned long timeout) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + long long endtime; + uint8_t val; + int ret; + + endtime = timeval_ms() + timeout; + do { + ret = target_read_u8(target, info->io_base + reg, &val); + if (ret != ERROR_OK) + return ret; + + if (!set) + val = ~val; + + if ((val & mask) == mask) + return ERROR_OK; + + alive_sleep(1); + } while (timeval_ms() < endtime); + + LOG_ERROR("timeout"); + return ERROR_TIMEOUT_REACHED; +} + +static int sh_qspi_xfer_common(struct flash_bank *bank, + const uint8_t *dout, unsigned int outlen, + uint8_t *din, unsigned int inlen, + bool xfer_start, bool xfer_end) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + uint8_t tdata, rdata; + uint8_t val; + unsigned int nbyte = outlen + inlen; + int ret = 0; + + if (xfer_start) { + ret = sh_qspi_cs_activate(bank); + if (ret != ERROR_OK) + return ret; + + ret = target_write_u32(target, info->io_base + SH_QSPI_SPBMUL0, + nbyte); + if (ret != ERROR_OK) + return ret; + + ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, + &val); + if (ret != ERROR_OK) + return ret; + + val &= ~(SPBFCR_TXTRG | SPBFCR_RXTRG); + + ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, + val); + if (ret != ERROR_OK) + return ret; + } + + while (nbyte > 0) { + ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPTEF, + true, 1000); + if (ret != ERROR_OK) + return ret; + + tdata = outlen ? *dout++ : 0; + ret = target_write_u8(target, info->io_base + SH_QSPI_SPDR, + tdata); + if (ret != ERROR_OK) + return ret; + + ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPRFF, + true, 1000); + if (ret != ERROR_OK) + return ret; + + ret = target_read_u8(target, info->io_base + SH_QSPI_SPDR, + &rdata); + if (ret != ERROR_OK) + return ret; + if (!outlen && inlen) { + *din++ = rdata; + inlen--; + } + + if (outlen) + outlen--; + + nbyte--; + } + + if (xfer_end) + return sh_qspi_cs_deactivate(bank); + else + return ERROR_OK; +} + +/* Send "write enable" command to SPI flash chip. */ +static int sh_qspi_write_enable(struct flash_bank *bank) +{ + uint8_t dout = SPIFLASH_WRITE_ENABLE; + + return sh_qspi_xfer_common(bank, &dout, 1, NULL, 0, 1, 1); +} + +/* Read the status register of the external SPI flash chip. */ +static int read_status_reg(struct flash_bank *bank, uint32_t *status) +{ + uint8_t dout = SPIFLASH_READ_STATUS; + uint8_t din; + int ret; + + ret = sh_qspi_xfer_common(bank, &dout, 1, &din, 1, 1, 1); + if (ret != ERROR_OK) + return ret; + + *status = din & 0xff; + + return ERROR_OK; +} + +/* check for WIP (write in progress) bit in status register */ +/* timeout in ms */ +static int wait_till_ready(struct flash_bank *bank, int timeout) +{ + long long endtime; + uint32_t status; + int ret; + + endtime = timeval_ms() + timeout; + do { + /* read flash status register */ + ret = read_status_reg(bank, &status); + if (ret != ERROR_OK) + return ret; + + if ((status & SPIFLASH_BSY_BIT) == 0) + return ERROR_OK; + alive_sleep(1); + } while (timeval_ms() < endtime); + + LOG_ERROR("timeout"); + return ERROR_TIMEOUT_REACHED; +} + +static int sh_qspi_erase_sector(struct flash_bank *bank, int sector) +{ + struct sh_qspi_flash_bank *info = bank->driver_priv; + bool addr4b = info->dev->size_in_bytes > (1UL << 24); + uint32_t address = (sector * info->dev->sectorsize) << + (addr4b ? 0 : 8); + uint8_t dout[5] = { + info->dev->erase_cmd, + (address >> 24) & 0xff, (address >> 16) & 0xff, + (address >> 8) & 0xff, (address >> 0) & 0xff + }; + unsigned int doutlen = addr4b ? 5 : 4; + int ret; + + /* Write Enable */ + ret = sh_qspi_write_enable(bank); + if (ret != ERROR_OK) + return ret; + + /* Erase */ + ret = sh_qspi_xfer_common(bank, dout, doutlen, NULL, 0, 1, 1); + if (ret != ERROR_OK) + return ret; + + /* Poll status register */ + return wait_till_ready(bank, 3000); +} + +static int sh_qspi_erase(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + int retval = ERROR_OK; + int sector; + + LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { + LOG_ERROR("Flash sector invalid"); + return ERROR_FLASH_SECTOR_INVALID; + } + + if (!info->probed) { + LOG_ERROR("Flash bank not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + if (info->dev->erase_cmd == 0x00) + return ERROR_FLASH_OPER_UNSUPPORTED; + + for (sector = first; sector <= last; sector++) { + if (bank->sectors[sector].is_protected) { + LOG_ERROR("Flash sector %d protected", sector); + return ERROR_FAIL; + } + } + + for (sector = first; sector <= last; sector++) { + retval = sh_qspi_erase_sector(bank, sector); + if (retval != ERROR_OK) + break; + keep_alive(); + } + + return retval; +} + +static int sh_qspi_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + struct reg_param reg_params[4]; + struct arm_algorithm arm_algo; + uint32_t io_base = (uint32_t)(info->io_base); + uint32_t src_base = (uint32_t)(info->source->address); + uint32_t chunk; + bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24)); + int ret = ERROR_OK; + int sector; + + LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, + __func__, offset, count); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) { + LOG_WARNING("Write pasts end of flash. Extra data discarded."); + count = bank->size - offset; + } + + if (offset & 0xff) { + LOG_ERROR("sh_qspi_write_page: unaligned write address: %08x", + offset); + return ERROR_FAIL; + } + + /* Check sector protection */ + for (sector = 0; sector < bank->num_sectors; sector++) { + /* Start offset in or before this sector? */ + /* End offset in or behind this sector? */ + struct flash_sector *bs = &bank->sectors[sector]; + + if ((offset < (bs->offset + bs->size)) && + ((offset + count - 1) >= bs->offset) && + bs->is_protected) { + LOG_ERROR("Flash sector %d protected", sector); + return ERROR_FAIL; + } + } + + LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, + __func__, offset, count); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) { + LOG_WARNING("Reads past end of flash. Extra data discarded."); + count = bank->size - offset; + } + + arm_algo.common_magic = ARM_COMMON_MAGIC; + arm_algo.core_mode = ARM_MODE_SVC; + arm_algo.core_state = ARM_STATE_ARM; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + + while (count > 0) { + chunk = (count > info->buffer_size) ? + info->buffer_size : count; + + target_write_buffer(target, info->source->address, + chunk, buffer); + + buf_set_u32(reg_params[0].value, 0, 32, io_base); + buf_set_u32(reg_params[1].value, 0, 32, src_base); + buf_set_u32(reg_params[2].value, 0, 32, + (1 << 31) | (addr4b << 30) | + (info->dev->pprog_cmd << 20) | chunk); + buf_set_u32(reg_params[3].value, 0, 32, offset); + + ret = target_run_algorithm(target, 0, NULL, 4, reg_params, + info->io_algorithm->address, + 0, 10000, &arm_algo); + if (ret != ERROR_OK) { + LOG_ERROR("error executing SH QSPI flash IO algorithm"); + ret = ERROR_FLASH_OPERATION_FAILED; + break; + } + + buffer += chunk; + offset += chunk; + count -= chunk; + } + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + + return ret; +} + +static int sh_qspi_read(struct flash_bank *bank, uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + struct reg_param reg_params[4]; + struct arm_algorithm arm_algo; + uint32_t io_base = (uint32_t)(info->io_base); + uint32_t src_base = (uint32_t)(info->source->address); + uint32_t chunk; + bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24)); + int ret = ERROR_OK; + + LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, + __func__, offset, count); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) { + LOG_WARNING("Reads past end of flash. Extra data discarded."); + count = bank->size - offset; + } + + arm_algo.common_magic = ARM_COMMON_MAGIC; + arm_algo.core_mode = ARM_MODE_SVC; + arm_algo.core_state = ARM_STATE_ARM; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + + while (count > 0) { + chunk = (count > info->buffer_size) ? + info->buffer_size : count; + + buf_set_u32(reg_params[0].value, 0, 32, io_base); + buf_set_u32(reg_params[1].value, 0, 32, src_base); + buf_set_u32(reg_params[2].value, 0, 32, + (addr4b << 30) | (info->dev->read_cmd << 20) | + chunk); + buf_set_u32(reg_params[3].value, 0, 32, offset); + + ret = target_run_algorithm(target, 0, NULL, 4, reg_params, + info->io_algorithm->address, + 0, 10000, &arm_algo); + if (ret != ERROR_OK) { + LOG_ERROR("error executing SH QSPI flash IO algorithm"); + ret = ERROR_FLASH_OPERATION_FAILED; + break; + } + + target_read_buffer(target, info->source->address, + chunk, buffer); + + buffer += chunk; + offset += chunk; + count -= chunk; + } + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + + return ERROR_OK; +} + +/* Return ID of flash device */ +static int read_flash_id(struct flash_bank *bank, uint32_t *id) +{ + struct target *target = bank->target; + uint8_t dout = SPIFLASH_READ_ID; + uint8_t din[3] = { 0, 0, 0 }; + int ret; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + ret = sh_qspi_xfer_common(bank, &dout, 1, din, 3, 1, 1); + if (ret != ERROR_OK) + return ret; + + *id = (din[0] << 0) | (din[1] << 8) | (din[2] << 16); + + if (*id == 0xffffff) { + LOG_ERROR("No SPI flash found"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int sh_qspi_protect(struct flash_bank *bank, int set, + int first, int last) +{ + int sector; + + for (sector = first; sector <= last; sector++) + bank->sectors[sector].is_protected = set; + + return ERROR_OK; +} + +static int sh_qspi_upload_helper(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + + /* see contrib/loaders/flash/sh_qspi.s for src */ + static const uint8_t sh_qspi_io_code[] = { +#include "../../../contrib/loaders/flash/sh_qspi/sh_qspi.inc" + }; + int ret; + + if (info->source) + target_free_working_area(target, info->source); + if (info->io_algorithm) + target_free_working_area(target, info->io_algorithm); + + /* flash write code */ + if (target_alloc_working_area(target, sizeof(sh_qspi_io_code), + &info->io_algorithm) != ERROR_OK) { + LOG_WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + target_write_buffer(target, info->io_algorithm->address, + sizeof(sh_qspi_io_code), sh_qspi_io_code); + + /* + * Try to allocate as big work area buffer as possible, start + * with 32 kiB and count down. If there is less than 256 Bytes + * of work area available, abort. + */ + info->buffer_size = 32768; + while (true) { + ret = target_alloc_working_area_try(target, info->buffer_size, + &info->source); + if (ret == ERROR_OK) + return ret; + + info->buffer_size /= 2; + if (info->buffer_size <= 256) { + target_free_working_area(target, info->io_algorithm); + + LOG_WARNING("no large enough working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } + + return ERROR_OK; +} + +static int sh_qspi_probe(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct sh_qspi_flash_bank *info = bank->driver_priv; + struct flash_sector *sectors; + uint32_t id = 0; /* silence uninitialized warning */ + uint32_t sectorsize; + const struct sh_qspi_target *target_device; + int ret; + + if (info->probed) + free(bank->sectors); + + info->probed = 0; + + for (target_device = target_devices; target_device->name; + ++target_device) + if (target_device->tap_idcode == target->tap->idcode) + break; + if (!target_device->name) { + LOG_ERROR("Device ID 0x%" PRIx32 " is not known", + target->tap->idcode); + return ERROR_FAIL; + } + + info->io_base = target_device->io_base; + + LOG_DEBUG("Found device %s at address " TARGET_ADDR_FMT, + target_device->name, bank->base); + + ret = sh_qspi_upload_helper(bank); + if (ret != ERROR_OK) + return ret; + + ret = sh_qspi_init(bank); + if (ret != ERROR_OK) + return ret; + + ret = read_flash_id(bank, &id); + if (ret != ERROR_OK) + return ret; + + info->dev = NULL; + for (const struct flash_device *p = flash_devices; p->name; p++) + if (p->device_id == id) { + info->dev = p; + break; + } + + if (!info->dev) { + LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); + return ERROR_FAIL; + } + + LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", + info->dev->name, info->dev->device_id); + + /* Set correct size value */ + bank->size = info->dev->size_in_bytes; + if (bank->size <= (1UL << 16)) + LOG_WARNING("device needs 2-byte addresses - not implemented"); + + /* if no sectors, treat whole bank as single sector */ + sectorsize = info->dev->sectorsize ? + info->dev->sectorsize : + info->dev->size_in_bytes; + + /* create and fill sectors array */ + bank->num_sectors = info->dev->size_in_bytes / sectorsize; + sectors = calloc(1, sizeof(*sectors) * bank->num_sectors); + if (!sectors) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + for (int sector = 0; sector < bank->num_sectors; sector++) { + sectors[sector].offset = sector * sectorsize; + sectors[sector].size = sectorsize; + sectors[sector].is_erased = 0; + sectors[sector].is_protected = 0; + } + + bank->sectors = sectors; + info->probed = 1; + return ERROR_OK; +} + +static int sh_qspi_auto_probe(struct flash_bank *bank) +{ + struct sh_qspi_flash_bank *info = bank->driver_priv; + + if (info->probed) + return ERROR_OK; + + return sh_qspi_probe(bank); +} + +static int sh_qspi_flash_blank_check(struct flash_bank *bank) +{ + /* Not implemented */ + return ERROR_OK; +} + +static int sh_qspi_protect_check(struct flash_bank *bank) +{ + /* Not implemented */ + return ERROR_OK; +} + +static int sh_qspi_get_info(struct flash_bank *bank, char *buf, int buf_size) +{ + struct sh_qspi_flash_bank *info = bank->driver_priv; + + if (!info->probed) { + snprintf(buf, buf_size, + "\nSH QSPI flash bank not probed yet\n"); + return ERROR_OK; + } + + snprintf(buf, buf_size, "\nSH QSPI flash information:\n" + " Device \'%s\' (ID 0x%08" PRIx32 ")\n", + info->dev->name, info->dev->device_id); + + return ERROR_OK; +} + +FLASH_BANK_COMMAND_HANDLER(sh_qspi_flash_bank_command) +{ + struct sh_qspi_flash_bank *info; + + LOG_DEBUG("%s", __func__); + + if (CMD_ARGC < 6 || CMD_ARGC > 7) + return ERROR_COMMAND_SYNTAX_ERROR; + + if ((CMD_ARGC == 7) && strcmp(CMD_ARGV[6], "cs0")) { + LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + info = calloc(1, sizeof(struct sh_qspi_flash_bank)); + if (!info) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + bank->driver_priv = info; + + return ERROR_OK; +} + +const struct flash_driver sh_qspi_flash = { + .name = "sh_qspi", + .flash_bank_command = sh_qspi_flash_bank_command, + .erase = sh_qspi_erase, + .protect = sh_qspi_protect, + .write = sh_qspi_write, + .read = sh_qspi_read, + .probe = sh_qspi_probe, + .auto_probe = sh_qspi_auto_probe, + .erase_check = sh_qspi_flash_blank_check, + .protect_check = sh_qspi_protect_check, + .info = sh_qspi_get_info, + .free_driver_priv = default_flash_free_driver_priv, +}; ----------------------------------------------------------------------- Summary of changes: contrib/loaders/flash/sh_qspi/Makefile | 37 ++ contrib/loaders/flash/sh_qspi/sh_qspi.S | 306 ++++++++++ contrib/loaders/flash/sh_qspi/sh_qspi.inc | 37 ++ contrib/loaders/flash/sh_qspi/sh_qspi.ld | 13 + src/flash/nor/Makefile.am | 1 + src/flash/nor/drivers.c | 2 + src/flash/nor/sh_qspi.c | 912 ++++++++++++++++++++++++++++++ 7 files changed, 1308 insertions(+) create mode 100644 contrib/loaders/flash/sh_qspi/Makefile create mode 100644 contrib/loaders/flash/sh_qspi/sh_qspi.S create mode 100644 contrib/loaders/flash/sh_qspi/sh_qspi.inc create mode 100644 contrib/loaders/flash/sh_qspi/sh_qspi.ld create mode 100644 src/flash/nor/sh_qspi.c hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-22 05:34:21
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via d612baacaa3fef549c446053089867d7b134ccfd (commit) from f98099507f509db9a18c70365490a6b9f67108db (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d612baacaa3fef549c446053089867d7b134ccfd Author: Oleksij Rempel <o.r...@pe...> Date: Thu Jul 5 13:42:14 2018 +0200 jtag_libusb_bulk_read|write: return error code instead of size A USB bulk write/read operation may fail with different errors: LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates transferred) LIBUSB_ERROR_PIPE if the endpoint halted LIBUSB_ERROR_OVERFLOW if the device offered more data, see Packets and overflows LIBUSB_ERROR_NO_DEVICE if the device has been disconnected another LIBUSB_ERROR code on other failures Current OpenOCD code is using the transfer size based error detection. Which may not always work. For example for LIBUSB_ERROR_OVERFLOW as libusb documentation says: "Problems may occur if the device attempts to send more data than can fit in the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but other behaviour is largely undefined: actual_length may or may not be accurate, the chunk of data that can fit in the buffer (before overflow) may or may not have been transferred." This patch is refactoring code to use actual error return value for error detection instead of size. Change-Id: Iec0798438ca7b5c76e2e2912af21d9aa76ee0217 Signed-off-by: Oleksij Rempel <o.r...@pe...> Reviewed-on: http://openocd.zylin.com/4590 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 324ec7c32..9e4741342 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -349,41 +349,53 @@ static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id, /* calls the given usb_bulk_* function, allowing for the data to * trickle in with some timeouts */ static int usb_bulk_with_retries( - int (*f)(jtag_libusb_device_handle *, int, char *, int, int), + int (*f)(jtag_libusb_device_handle *, int, char *, int, int, int *), jtag_libusb_device_handle *dev, int ep, - char *bytes, int size, int timeout) + char *bytes, int size, int timeout, int *transferred) { int tries = 3, count = 0; while (tries && (count < size)) { - int result = f(dev, ep, bytes + count, size - count, timeout); - if (result > 0) + int result, ret; + + ret = f(dev, ep, bytes + count, size - count, timeout, &result); + if (ERROR_OK == ret) count += result; - else if ((-ETIMEDOUT != result) || !--tries) - return result; + else if ((ERROR_TIMEOUT_REACHED != ret) || !--tries) + return ret; } - return count; + + *transferred = count; + return ERROR_OK; } static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep, - char *buff, int size, int timeout) + char *buff, int size, int timeout, int *transferred) { + /* usb_bulk_write() takes const char *buff */ - return jtag_libusb_bulk_write(dev, ep, buff, size, timeout); + jtag_libusb_bulk_write(dev, ep, buff, size, timeout, transferred); + + return 0; } static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { - return usb_bulk_with_retries(&wrap_usb_bulk_write, - dev, ep, bytes, size, timeout); + int tr = 0; + + usb_bulk_with_retries(&wrap_usb_bulk_write, + dev, ep, bytes, size, timeout, &tr); + return tr; } static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { - return usb_bulk_with_retries(&jtag_libusb_bulk_read, - dev, ep, bytes, size, timeout); + int tr = 0; + usb_bulk_with_retries(&jtag_libusb_bulk_read, + dev, ep, bytes, size, timeout, &tr); + return tr; } /* Write data from out_buffer to USB. */ diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 1ef0c57ea..c20367fc0 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -132,11 +132,11 @@ static int ft232r_send_recv(void) bytes_to_write = rxfifo_free; if (bytes_to_write) { - int n = jtag_libusb_bulk_write(adapter, IN_EP, - (char *) ft232r_output + total_written, - bytes_to_write, 1000); + int n; - if (n == 0) { + if (jtag_libusb_bulk_write(adapter, IN_EP, + (char *) ft232r_output + total_written, + bytes_to_write, 1000, &n) != ERROR_OK) { LOG_ERROR("usb bulk write failed"); return ERROR_JTAG_DEVICE_ERROR; } @@ -147,12 +147,10 @@ static int ft232r_send_recv(void) /* Read */ uint8_t reply[64]; + int n; - int n = jtag_libusb_bulk_read(adapter, OUT_EP, - (char *) reply, - sizeof(reply), 1000); - - if (n == 0) { + if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply, + sizeof(reply), 1000, &n) != ERROR_OK) { LOG_ERROR("usb bulk read failed"); return ERROR_JTAG_DEVICE_ERROR; } diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index 489441111..7b339aa0b 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -731,14 +731,14 @@ static int kitprog_swd_run_queue(void) } } - ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle, - BULK_EP_OUT, (char *)buffer, write_count, 0); - if (ret > 0) { - queued_retval = ERROR_OK; - } else { + if (jtag_libusb_bulk_write(kitprog_handle->usb_handle, + BULK_EP_OUT, (char *)buffer, + write_count, 0, &ret)) { LOG_ERROR("Bulk write failed"); queued_retval = ERROR_FAIL; break; + } else { + queued_retval = ERROR_OK; } /* KitProg firmware does not send a zero length packet @@ -754,18 +754,17 @@ static int kitprog_swd_run_queue(void) if (read_count % 64 == 0) read_count_workaround = read_count; - ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle, + if (jtag_libusb_bulk_read(kitprog_handle->usb_handle, BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer, - read_count_workaround, 1000); - if (ret > 0) { + read_count_workaround, 1000, &ret)) { + LOG_ERROR("Bulk read failed"); + queued_retval = ERROR_FAIL; + break; + } else { /* Handle garbage data by offsetting the initial read index */ if ((unsigned int)ret > read_count) read_index = ret - read_count; queued_retval = ERROR_OK; - } else { - LOG_ERROR("Bulk read failed"); - queued_retval = ERROR_FAIL; - break; } for (int i = 0; i < pending_transfer_count; i++) { diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c index 14a8b61cc..0e7858911 100644 --- a/src/jtag/drivers/libusb0_common.c +++ b/src/jtag/drivers/libusb0_common.c @@ -23,6 +23,18 @@ #include "log.h" #include "libusb0_common.h" +static int jtag_libusb_error(int err) +{ + switch (err) { + case 0: + return ERROR_OK; + case -ETIMEDOUT: + return ERROR_TIMEOUT_REACHED; + default: + return ERROR_FAIL; + } +} + static bool jtag_libusb_match(struct jtag_libusb_device *dev, const uint16_t vids[], const uint16_t pids[]) { @@ -130,15 +142,37 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request } int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes, - int size, int timeout) + int size, int timeout, int *transferred) { - return usb_bulk_write(dev, ep, bytes, size, timeout); + int ret; + + *transferred = 0; + + ret = usb_bulk_write(dev, ep, bytes, size, timeout); + + if (ret < 0) { + LOG_ERROR("usb_bulk_write error: %i", ret); + return jtag_libusb_error(ret); + } + + return ERROR_OK; } int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes, - int size, int timeout) + int size, int timeout, int *transferred) { - return usb_bulk_read(dev, ep, bytes, size, timeout); + int ret; + + *transferred = 0; + + ret = usb_bulk_read(dev, ep, bytes, size, timeout); + + if (ret < 0) { + LOG_ERROR("usb_bulk_read error: %i", ret); + return jtag_libusb_error(ret); + } + + return ERROR_OK; } int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h index 676f43acd..6f632c462 100644 --- a/src/jtag/drivers/libusb0_common.h +++ b/src/jtag/drivers/libusb0_common.h @@ -60,9 +60,9 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout); int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep, - char *bytes, int size, int timeout); + char *bytes, int size, int timeout, int *transferred); int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, - char *bytes, int size, int timeout); + char *bytes, int size, int timeout, int *transferred); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index d96ac7692..0d4bcbab6 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -33,6 +33,31 @@ static struct libusb_context *jtag_libusb_context; /**< Libusb context **/ static libusb_device **devs; /**< The usb device list **/ +static int jtag_libusb_error(int err) +{ + switch (err) { + case LIBUSB_SUCCESS: + return ERROR_OK; + case LIBUSB_ERROR_TIMEOUT: + return ERROR_TIMEOUT_REACHED; + case LIBUSB_ERROR_IO: + case LIBUSB_ERROR_INVALID_PARAM: + case LIBUSB_ERROR_ACCESS: + case LIBUSB_ERROR_NO_DEVICE: + case LIBUSB_ERROR_NOT_FOUND: + case LIBUSB_ERROR_BUSY: + case LIBUSB_ERROR_OVERFLOW: + case LIBUSB_ERROR_PIPE: + case LIBUSB_ERROR_INTERRUPTED: + case LIBUSB_ERROR_NO_MEM: + case LIBUSB_ERROR_NOT_SUPPORTED: + case LIBUSB_ERROR_OTHER: + return ERROR_FAIL; + default: + return ERROR_FAIL; + } +} + static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc, const uint16_t vids[], const uint16_t pids[]) { @@ -179,23 +204,37 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request } int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes, - int size, int timeout) + int size, int timeout, int *transferred) { - int transferred = 0; + int ret; - libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, - &transferred, timeout); - return transferred; + *transferred = 0; + + ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, + transferred, timeout); + if (ret != LIBUSB_SUCCESS) { + LOG_ERROR("libusb_bulk_write error: %s", libusb_error_name(ret)); + return jtag_libusb_error(ret); + } + + return ERROR_OK; } int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes, - int size, int timeout) + int size, int timeout, int *transferred) { - int transferred = 0; + int ret; - libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, - &transferred, timeout); - return transferred; + *transferred = 0; + + ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size, + transferred, timeout); + if (ret != LIBUSB_SUCCESS) { + LOG_ERROR("libusb_bulk_read error: %s", libusb_error_name(ret)); + return jtag_libusb_error(ret); + } + + return ERROR_OK; } int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h index 7c73d29a4..34be691f5 100644 --- a/src/jtag/drivers/libusb1_common.h +++ b/src/jtag/drivers/libusb1_common.h @@ -53,9 +53,9 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType, uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout); int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep, - char *bytes, int size, int timeout); + char *bytes, int size, int timeout, int *transferred); int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, - char *bytes, int size, int timeout); + char *bytes, int size, int timeout, int *transferred); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); /** diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 539f475bd..d5c279b08 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -770,8 +770,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length) LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT); } else { - result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \ - (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT); + jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \ + (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result); } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB write end: %d bytes", result); @@ -797,8 +797,8 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag) LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT); } else { - result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT, - (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT); + jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT, + (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result); } #ifdef _DEBUG_USB_COMMS_ LOG_DEBUG("USB read end: %d bytes", result); diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 24960a8d9..c42b620bb 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -256,10 +256,9 @@ static int openjtag_buf_write_cy7c65215( return ERROR_JTAG_DEVICE_ERROR; } - ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size, - CY7C65215_USB_TIMEOUT); - if (ret < 0) { - LOG_ERROR("bulk write failed, error %d", ret); + if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size, + CY7C65215_USB_TIMEOUT, &ret)) { + LOG_ERROR("bulk write failed, error"); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written = ret; @@ -324,10 +323,9 @@ static int openjtag_buf_read_cy7c65215( return ERROR_JTAG_DEVICE_ERROR; } - ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty, - CY7C65215_USB_TIMEOUT); - if (ret < 0) { - LOG_ERROR("bulk read failed, error %d", ret); + if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty, + CY7C65215_USB_TIMEOUT, &ret)) { + LOG_ERROR("bulk read failed, error"); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read = ret; diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index ed89a7946..9a570b098 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -144,10 +144,12 @@ static struct osbdm osbdm_context; static int osbdm_send_and_recv(struct osbdm *osbdm) { /* Send request */ - int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE, - (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT); + int count, ret; - if (count != osbdm->count) { + ret = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE, + (char *)osbdm->buffer, osbdm->count, + OSBDM_USB_TIMEOUT, &count); + if (ret || count != osbdm->count) { LOG_ERROR("OSBDM communication error: can't write"); return ERROR_FAIL; } @@ -156,13 +158,12 @@ static int osbdm_send_and_recv(struct osbdm *osbdm) uint8_t cmd_saved = osbdm->buffer[0]; /* Reading answer */ - osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ, - (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT); - + ret = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ, + (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, + OSBDM_USB_TIMEOUT, &osbdm->count); /* Now perform basic checks for data sent by BDM device */ - - if (osbdm->count < 0) { + if (ret) { LOG_ERROR("OSBDM communication error: can't read"); return ERROR_FAIL; } diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 5c904d4ff..8e4493ed8 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -531,14 +531,16 @@ static int jtag_libusb_bulk_transfer_n( static int stlink_usb_xfer_v1_get_status(void *handle) { struct stlink_usb_handle_s *h = handle; + int tr, ret; assert(handle != NULL); /* read status */ memset(h->cmdbuf, 0, STLINK_SG_SIZE); - if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, - 13, STLINK_READ_TIMEOUT) != 13) + ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13, + STLINK_READ_TIMEOUT, &tr); + if (ret || tr != 13) return ERROR_FAIL; uint32_t t1; @@ -602,23 +604,26 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size) { struct stlink_usb_handle_s *h = handle; + int tr, ret; assert(handle != NULL); - if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, cmdsize, - STLINK_WRITE_TIMEOUT) != cmdsize) { + ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, + cmdsize, STLINK_WRITE_TIMEOUT, &tr); + if (ret || tr != cmdsize) return ERROR_FAIL; - } if (h->direction == h->tx_ep && size) { - if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf, - size, STLINK_WRITE_TIMEOUT) != size) { + ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf, + size, STLINK_WRITE_TIMEOUT, &tr); + if (ret || tr != size) { LOG_DEBUG("bulk write failed"); return ERROR_FAIL; } } else if (h->direction == h->rx_ep && size) { - if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf, - size, STLINK_READ_TIMEOUT) != size) { + ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf, + size, STLINK_READ_TIMEOUT, &tr); + if (ret || tr != size) { LOG_DEBUG("bulk read failed"); return ERROR_FAIL; } @@ -840,13 +845,15 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size) { struct stlink_usb_handle_s *h = handle; + int tr, ret; assert(handle != NULL); assert(h->version.flags & STLINK_F_HAS_TRACE); - if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, - size, STLINK_READ_TIMEOUT) != size) { + ret = jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size, + STLINK_READ_TIMEOUT, &tr); + if (ret || tr != size) { LOG_ERROR("bulk trace read failed"); return ERROR_FAIL; } diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index d99173369..fb1e4440a 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -42,25 +42,34 @@ static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read) { - *bytes_read = jtag_libusb_bulk_read(low->libusb_dev, + int ret, tmp = 0; + + ret = jtag_libusb_bulk_read(low->libusb_dev, USBBLASTER_EPIN | \ LIBUSB_ENDPOINT_IN, (char *)buf, size, - 100); - return ERROR_OK; + 100, &tmp); + *bytes_read = tmp; + + return ret; } static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written) { - *bytes_written = jtag_libusb_bulk_write(low->libusb_dev, + int ret, tmp = 0; + + ret = jtag_libusb_bulk_write(low->libusb_dev, USBBLASTER_EPOUT | \ LIBUSB_ENDPOINT_OUT, (char *)buf, size, - 100); - return ERROR_OK; + 100, &tmp); + *bytes_written = tmp; + + return ret; + } static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev, ----------------------------------------------------------------------- Summary of changes: src/jtag/aice/aice_usb.c | 38 +++++++++----- src/jtag/drivers/ft232r.c | 16 +++--- src/jtag/drivers/kitprog.c | 23 ++++----- src/jtag/drivers/libusb0_common.c | 42 +++++++++++++-- src/jtag/drivers/libusb0_common.h | 4 +- src/jtag/drivers/libusb1_common.c | 59 ++++++++++++++++++---- src/jtag/drivers/libusb1_common.h | 4 +- src/jtag/drivers/opendous.c | 8 +-- src/jtag/drivers/openjtag.c | 14 +++-- src/jtag/drivers/osbdm.c | 17 ++++--- src/jtag/drivers/stlink_usb.c | 29 +++++++---- .../drivers/usb_blaster/ublast2_access_libusb.c | 21 +++++--- 12 files changed, 186 insertions(+), 89 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-20 06:29:35
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via f98099507f509db9a18c70365490a6b9f67108db (commit) from ff6d0704ecd66343e3dab2059c89fa392e2214be (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f98099507f509db9a18c70365490a6b9f67108db Author: Jiri Kastner <cz1...@gm...> Date: Wed Aug 1 15:17:43 2018 +0200 mips_ejtag: there is no DCR.MIPS64 bit available revisions (2.60, 3.10, 5.06 and 6.10) of MD00047 (EJTAG specification), have only in IMPCODE MIPS32/MIPS64 bit/flag. Change-Id: If9191b6ced760c59bb7551bb041cd72b0a060bb1 Signed-off-by: Jiri Kastner <cz1...@gm...> Reviewed-on: http://openocd.zylin.com/4628 Reviewed-by: Oleksij Rempel <li...@re...> Tested-by: jenkins diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 0b8122e1c..6d35e211d 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -349,7 +349,7 @@ static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) EJTAG_IMP_HAS(EJTAG_IMP_ASID6) ? " ASID_6" : "", EJTAG_IMP_HAS(EJTAG_IMP_MIPS16) ? " MIPS16" : "", EJTAG_IMP_HAS(EJTAG_IMP_NODMA) ? " noDMA" : " DMA", - EJTAG_IMP_HAS(EJTAG_DCR_MIPS64) ? " MIPS64" : " MIPS32"); + EJTAG_IMP_HAS(EJTAG_IMP_MIPS64) ? " MIPS64" : " MIPS32"); switch (ejtag_info->ejtag_version) { case EJTAG_VERSION_20: diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index cfba0ab56..ace3d281e 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -130,7 +130,7 @@ /* v2.0 - 1:4 Number of Break Channels. */ #define EJTAG_V20_IMP_BCHANNELS_MASK 0xf #define EJTAG_V20_IMP_BCHANNELS_SHIFT 1 -#define EJTAG_DCR_MIPS64 (1 << 0) +#define EJTAG_IMP_MIPS64 (1 << 0) /* Debug Control Register DCR */ #define EJTAG_DCR 0xFF300000 ----------------------------------------------------------------------- Summary of changes: src/target/mips_ejtag.c | 2 +- src/target/mips_ejtag.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-17 05:22:09
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via ff6d0704ecd66343e3dab2059c89fa392e2214be (commit) from f22883e8c131b31b9b1bcc762b3f7317789147fb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ff6d0704ecd66343e3dab2059c89fa392e2214be Author: Moritz Fischer <mo...@go...> Date: Thu Oct 3 20:25:26 2019 -0700 jtag: drivers: xlnx-pcie-xvc: Add support for Xilinx XVC/PCIe Add support for Xilinx Virtual Cable over PCIe JTAG controller. It is commonly used in Xilinx based PCI Express designs with JTAG IP in the FPGA fabric. Access to the JTAG registers happens via the PCI Express extended configuration space. This can be used to debug soft-cores instantiated in the FPGA fabric. The clang static checker doesn't find any new problems with this change. Change-Id: Ib12ede0d1f26dacfda808d5e05b947b640c5bde7 Signed-off-by: Moritz Fischer <mo...@go...> Reviewed-on: http://openocd.zylin.com/5314 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Marex Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/configure.ac b/configure.ac index b84e3e8f8..e86d33f88 100644 --- a/configure.ac +++ b/configure.ac @@ -142,6 +142,9 @@ m4_define([LIBFTDI_ADAPTERS], m4_define([LIBJAYLINK_ADAPTERS], [[[jlink], [SEGGER J-Link Programmer], [JLINK]]]) +m4_define([PCIE_ADAPTERS], + [[[xlnx_pcie_xvc], [Xilinx XVC/PCIe], [XLNX_PCIE_XVC]]]) + AC_ARG_ENABLE([doxygen-html], AS_HELP_STRING([--disable-doxygen-html], @@ -315,12 +318,20 @@ AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) +AC_ARG_ENABLE([xlnx_pcie_xvc], + AS_HELP_STRING([--enable-xlnx-pcie-xvc], [Enable building support for Xilinx XVC/PCIe.]), + [build_xlnx_pcie_xvc=$enableval], [build_xlnx_pcie_xvc=no]) + AS_CASE([$host_os], [linux*], [], [ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_MSG_ERROR([sysfsgpio is only available on linux]) ]) + + AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [ + AC_MSG_ERROR([xlnx_pcie_xvc is only available on linux]) + ]) ]) AC_ARG_ENABLE([minidriver_dummy], @@ -580,6 +591,13 @@ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) ]) +AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [ + build_xlnx_pcie_xvc=yes + AC_DEFINE([BUILD_XLNX_PCIE_XVC], [1], [1 if you want the Xilinx XVC/PCIe driver.]) +], [ + AC_DEFINE([BUILD_XLNX_PCIE_XVC], [0], [0 if you don't want Xilinx XVC/PCIe driver.]) +]) + AS_IF([test "x$build_target64" = "xyes"], [ AC_DEFINE([BUILD_TARGET64], [1], [1 if you want 64-bit addresses.]) ], [ @@ -699,6 +717,7 @@ AM_CONDITIONAL([OOCD_TRACE], [test "x$build_oocd_trace" = "xyes"]) AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"]) AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) +AM_CONDITIONAL([XLNX_PCIE_XVC], [test "x$build_xlnx_pcie_xvc" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB0], [test "x$use_libusb0" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) @@ -778,7 +797,7 @@ echo OpenOCD configuration summary echo -------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, - LIBJAYLINK_ADAPTERS], + LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], [auto], [ diff --git a/doc/openocd.texi b/doc/openocd.texi index c526a632a..cb1c5b791 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -617,6 +617,9 @@ produced, PDF schematics are easily found and it is easy to make. @* A JTAG driver acting as a client for the JTAG VPI server interface. @* Link: @url{http://github.com/fjullien/jtag_vpi} +@item @b{xlnx_pcie_xvc} +@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG interface. + @end itemize @node About Jim-Tcl @@ -3127,6 +3130,25 @@ opendous-jtag is a freely programmable USB adapter. This is the Keil ULINK v1 JTAG debugger. @end deffn +@deffn {Interface Driver} {xlnx_pcie_xvc} +This driver supports the Xilinx Virtual Cable (XVC) over PCI Express. +It is commonly found in Xilinx based PCI Express designs. It allows debugging +fabric based JTAG devices such as Cortex-M1/M3 microcontrollers. Access to this is +exposed via extended capability registers in the PCI Express configuration space. + +For more information see Xilinx PG245 (Section on From_PCIE_to_JTAG mode). + +@deffn {Config Command} {xlnx_pcie_xvc_config} device +Specifies the PCI Express device via parameter @var{device} to use. + +The correct value for @var{device} can be obtained by looking at the output +of lscpi -D (first column) for the corresponding device. + +The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1". + +@end deffn +@end deffn + @deffn {Interface Driver} {ZY1000} This is the Zylin ZY1000 JTAG debugger. @end deffn diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 572cd2441..7fbcd584f 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -145,6 +145,9 @@ endif if SYSFSGPIO DRIVERFILES += %D%/sysfsgpio.c endif +if XLNX_PCIE_XVC +DRIVERFILES += %D%/xlnx-pcie-xvc.c +endif if BCM2835GPIO DRIVERFILES += %D%/bcm2835gpio.c endif diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c new file mode 100644 index 000000000..fabf0f39f --- /dev/null +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -0,0 +1,481 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2019 Google, LLC. + * Author: Moritz Fischer <mo...@go...> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdlib.h> +#include <math.h> +#include <unistd.h> +#include <linux/pci.h> + +#include <jtag/interface.h> +#include <jtag/swd.h> +#include <jtag/commands.h> +#include <helper/replacements.h> +#include <helper/bits.h> + +#define PCIE_EXT_CAP_LST 0x100 + +#define XLNX_XVC_EXT_CAP 0x00 +#define XLNX_XVC_VSEC_HDR 0x04 +#define XLNX_XVC_LEN_REG 0x0C +#define XLNX_XVC_TMS_REG 0x10 +#define XLNX_XVC_TDx_REG 0x14 + +#define XLNX_XVC_CAP_SIZE 0x20 +#define XLNX_XVC_VSEC_ID 0x8 +#define XLNX_XVC_MAX_BITS 0x20 + +struct xlnx_pcie_xvc { + int fd; + unsigned offset; + char *device; +}; + +static struct xlnx_pcie_xvc xlnx_pcie_xvc_state; +static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state; + +static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val) +{ + uint32_t res; + int err; + + /* Note: This should be ok endianess-wise because by going + * through sysfs the kernel does the conversion in the config + * space accessor functions + */ + err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res), + xlnx_pcie_xvc->offset + offset); + if (err != sizeof(res)) { + LOG_ERROR("Failed to read offset %x", offset); + return ERROR_JTAG_DEVICE_ERROR; + } + + if (val) + *val = res; + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val) +{ + int err; + + /* Note: This should be ok endianess-wise because by going + * through sysfs the kernel does the conversion in the config + * space accessor functions + */ + err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val), + xlnx_pcie_xvc->offset + offset); + if (err != sizeof(val)) { + LOG_ERROR("Failed to write offset: %x with value: %x", + offset, val); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi, + uint32_t *tdo) +{ + int err; + + err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits); + if (err != ERROR_OK) + return err; + + err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms); + if (err != ERROR_OK) + return err; + + err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDx_REG, tdi); + if (err != ERROR_OK) + return err; + + err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDx_REG, tdo); + if (err != ERROR_OK) + return err; + + if (tdo) + LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: %x", + num_bits, tms, tdi, *tdo); + else + LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: <null>", + num_bits, tms, tdi); + return ERROR_OK; +} + +int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd) +{ + int tms = tap_get_state() == TAP_RESET ? 1 : 0; + size_t left = cmd->cmd.stableclocks->num_cycles; + size_t write; + int err; + + LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + + while (left) { + write = MIN(XLNX_XVC_MAX_BITS, left); + err = xlnx_pcie_xvc_transact(write, tms, 0, NULL); + if (err != ERROR_OK) + return err; + left -= write; + }; + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_execute_statemove(size_t skip) +{ + uint8_t tms_scan = tap_get_tms_path(tap_get_state(), + tap_get_end_state()); + int tms_count = tap_get_tms_path_len(tap_get_state(), + tap_get_end_state()); + int err; + + LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip, + tap_state_name(tap_get_state()), + tap_state_name(tap_get_end_state())); + + + err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL); + if (err != ERROR_OK) + return err; + + tap_set_state(tap_get_end_state()); + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) +{ + int err = ERROR_OK; + + LOG_DEBUG("runtest %i cycles, end in %i", + cmd->cmd.runtest->num_cycles, + cmd->cmd.runtest->end_state); + + tap_state_t tmp_state = tap_get_end_state(); + + if (tap_get_state() != TAP_IDLE) { + tap_set_end_state(TAP_IDLE); + err = xlnx_pcie_xvc_execute_statemove(0); + if (err != ERROR_OK) + return err; + }; + + size_t left = cmd->cmd.runtest->num_cycles; + size_t write; + + while (left) { + write = MIN(XLNX_XVC_MAX_BITS, left); + err = xlnx_pcie_xvc_transact(write, 0, 0, NULL); + if (err != ERROR_OK) + return err; + left -= write; + }; + + tap_set_end_state(tmp_state); + if (tap_get_state() != tap_get_end_state()) + err = xlnx_pcie_xvc_execute_statemove(0); + + return err; +} + +static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) +{ + size_t num_states = cmd->cmd.pathmove->num_states; + tap_state_t *path = cmd->cmd.pathmove->path; + int err = ERROR_OK; + size_t i; + + LOG_DEBUG("pathmove: %i states, end in %i", + cmd->cmd.pathmove->num_states, + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + + for (i = 0; i < num_states; i++) { + if (path[i] == tap_state_transition(tap_get_state(), false)) { + err = xlnx_pcie_xvc_transact(1, 1, 0, NULL); + } else if (path[i] == tap_state_transition(tap_get_state(), true)) { + err = xlnx_pcie_xvc_transact(1, 0, 0, NULL); + } else { + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.", + tap_state_name(tap_get_state()), + tap_state_name(path[i])); + err = ERROR_JTAG_QUEUE_FAILED; + } + if (err != ERROR_OK) + return err; + tap_set_state(path[i]); + } + + tap_set_end_state(tap_get_state()); + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd) +{ + enum scan_type type = jtag_scan_type(cmd->cmd.scan); + tap_state_t saved_end_state = cmd->cmd.scan->end_state; + bool ir_scan = cmd->cmd.scan->ir_scan; + uint32_t tdi, tms, tdo; + uint8_t *buf, *rd_ptr; + int err, scan_size; + size_t write; + size_t left; + + scan_size = jtag_build_buffer(cmd->cmd.scan, &buf); + rd_ptr = buf; + LOG_DEBUG("%s scan type %d %d bits; starts in %s end in %s", + (cmd->cmd.scan->ir_scan) ? "IR" : "DR", type, scan_size, + tap_state_name(tap_get_state()), + tap_state_name(cmd->cmd.scan->end_state)); + + /* If we're in TAP_DR_SHIFT state but need to do a IR_SCAN or + * vice-versa, do a statemove to corresponding other state, then restore + * end state + */ + if (ir_scan && tap_get_state() != TAP_IRSHIFT) { + tap_set_end_state(TAP_IRSHIFT); + err = xlnx_pcie_xvc_execute_statemove(0); + if (err != ERROR_OK) + goto out_err; + tap_set_end_state(saved_end_state); + } else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) { + tap_set_end_state(TAP_DRSHIFT); + err = xlnx_pcie_xvc_execute_statemove(0); + if (err != ERROR_OK) + goto out_err; + tap_set_end_state(saved_end_state); + } + + left = scan_size; + while (left) { + write = MIN(XLNX_XVC_MAX_BITS, left); + /* the last TMS should be a 1, to leave the state */ + tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0; + tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0; + err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ? + &tdo : NULL); + if (err != ERROR_OK) + goto out_err; + left -= write; + if (type != SCAN_OUT) + buf_set_u32(rd_ptr, 0, write, tdo); + rd_ptr += sizeof(uint32_t); + }; + + err = jtag_read_buffer(buf, cmd->cmd.scan); + if (buf) + free(buf); + + if (tap_get_state() != tap_get_end_state()) + err = xlnx_pcie_xvc_execute_statemove(1); + + return err; + +out_err: + if (buf) + free(buf); + return err; +} + +static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd) +{ + LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst, + cmd->cmd.reset->srst); +} + +static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd) +{ + LOG_DEBUG("sleep %" PRIi32 "", cmd->cmd.sleep->us); + usleep(cmd->cmd.sleep->us); +} + +static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd) +{ + const size_t num_bits = cmd->cmd.tms->num_bits; + const uint8_t *bits = cmd->cmd.tms->bits; + size_t left, write; + uint32_t tms; + int err; + + LOG_DEBUG("execute tms %zu", num_bits); + + left = num_bits; + while (left) { + write = MIN(XLNX_XVC_MAX_BITS, left); + tms = buf_get_u32(bits, 0, write); + err = xlnx_pcie_xvc_transact(write, tms, 0, NULL); + if (err != ERROR_OK) + return err; + left -= write; + bits += 4; + }; + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd) +{ + LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type); + switch (cmd->type) { + case JTAG_STABLECLOCKS: + return xlnx_pcie_xvc_execute_stableclocks(cmd); + case JTAG_RUNTEST: + return xlnx_pcie_xvc_execute_runtest(cmd); + case JTAG_TLR_RESET: + tap_set_end_state(cmd->cmd.statemove->end_state); + return xlnx_pcie_xvc_execute_statemove(0); + case JTAG_PATHMOVE: + return xlnx_pcie_xvc_execute_pathmove(cmd); + case JTAG_SCAN: + return xlnx_pcie_xvc_execute_scan(cmd); + case JTAG_RESET: + xlnx_pcie_xvc_execute_reset(cmd); + break; + case JTAG_SLEEP: + xlnx_pcie_xvc_execute_sleep(cmd); + break; + case JTAG_TMS: + return xlnx_pcie_xvc_execute_tms(cmd); + default: + LOG_ERROR("BUG: Unknown JTAG command type encountered."); + return ERROR_JTAG_QUEUE_FAILED; + } + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; + int ret; + + while (cmd) { + ret = xlnx_pcie_xvc_execute_command(cmd); + + if (ret != ERROR_OK) + return ret; + + cmd = cmd->next; + } + + return ERROR_OK; +} + + +static int xlnx_pcie_xvc_init(void) +{ + char filename[PATH_MAX]; + uint32_t cap, vh; + int err; + + snprintf(filename, PATH_MAX, "/sys/bus/pci/devices/%s/config", + xlnx_pcie_xvc->device); + xlnx_pcie_xvc->fd = open(filename, O_RDWR | O_SYNC); + if (xlnx_pcie_xvc->fd < 0) { + LOG_ERROR("Failed to open device: %s", filename); + return ERROR_JTAG_INIT_FAILED; + } + + LOG_INFO("Scanning PCIe device %s's for Xilinx XVC/PCIe ...", + xlnx_pcie_xvc->device); + /* Parse the PCIe extended capability list and try to find + * vendor specific header */ + xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST; + while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) && + xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) { + err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap); + if (err != ERROR_OK) + return err; + LOG_DEBUG("Checking capability at 0x%x; id=0x%04x version=0x%x next=0x%x", + xlnx_pcie_xvc->offset, + PCI_EXT_CAP_ID(cap), + PCI_EXT_CAP_VER(cap), + PCI_EXT_CAP_NEXT(cap)); + if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) { + err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh); + if (err != ERROR_OK) + return err; + LOG_DEBUG("Checking possible match at 0x%x; id: 0x%x; rev: 0x%x; length: 0x%x", + xlnx_pcie_xvc->offset, + PCI_VNDR_HEADER_ID(vh), + PCI_VNDR_HEADER_REV(vh), + PCI_VNDR_HEADER_LEN(vh)); + if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) && + (PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE)) + break; + } + xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap); + } + if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) || + xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) { + close(xlnx_pcie_xvc->fd); + return ERROR_JTAG_INIT_FAILED; + } + + LOG_INFO("Found Xilinx XVC/PCIe capability at offset: 0x%x", xlnx_pcie_xvc->offset); + + return ERROR_OK; +} + +static int xlnx_pcie_xvc_quit(void) +{ + int err; + + err = close(xlnx_pcie_xvc->fd); + if (err) + return err; + + return ERROR_OK; +} + +COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command) +{ + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* we can't really free this in a safe manner, so at least + * limit the memory we're leaking by freeing the old one first + * before allocating a new one ... + */ + if (xlnx_pcie_xvc->device) + free(xlnx_pcie_xvc->device); + + xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]); + return ERROR_OK; +} + +static const struct command_registration xlnx_pcie_xvc_command_handlers[] = { + { + .name = "xlnx_pcie_xvc_config", + .handler = xlnx_pcie_xvc_handle_config_command, + .mode = COMMAND_CONFIG, + .help = "Configure XVC/PCIe JTAG adapter", + .usage = "device", + }, + COMMAND_REGISTRATION_DONE +}; + +static const char * const xlnx_pcie_xvc_transports[] = { "jtag", NULL }; + +struct jtag_interface xlnx_pcie_xvc_interface = { + .name = "xlnx_pcie_xvc", + .commands = xlnx_pcie_xvc_command_handlers, + .transports = xlnx_pcie_xvc_transports, + .execute_queue = &xlnx_pcie_xvc_execute_queue, + .speed = NULL, + .speed_div = NULL, + .khz = NULL, + .init = &xlnx_pcie_xvc_init, + .quit = &xlnx_pcie_xvc_quit, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 17d45415a..356d89ecd 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -117,6 +117,9 @@ extern struct adapter_driver opendous_adapter_driver; #if BUILD_SYSFSGPIO == 1 extern struct adapter_driver sysfsgpio_adapter_driver; #endif +#if BUILD_XLNX_PCIE_XVC == 1 +extern struct jtag_interface xlnx_pcie_xvc_interface; +#endif #if BUILD_AICE == 1 extern struct adapter_driver aice_adapter_driver; #endif @@ -225,6 +228,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_SYSFSGPIO == 1 &sysfsgpio_adapter_driver, #endif +#if BUILD_XLNX_PCIE_XVC == 1 + &xlnx_pcie_xvc_interface, +#endif #if BUILD_AICE == 1 &aice_adapter_driver, #endif ----------------------------------------------------------------------- Summary of changes: configure.ac | 21 +- doc/openocd.texi | 22 ++ src/jtag/drivers/Makefile.am | 3 + src/jtag/drivers/xlnx-pcie-xvc.c | 481 +++++++++++++++++++++++++++++++++++++++ src/jtag/interfaces.c | 6 + 5 files changed, 532 insertions(+), 1 deletion(-) create mode 100644 src/jtag/drivers/xlnx-pcie-xvc.c hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 12:27:03
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via f22883e8c131b31b9b1bcc762b3f7317789147fb (commit) via 76de1c8de104496f26a1cd084b755008349fa064 (commit) via 3192717ae910d387476b3a7980c325ceb0d2f733 (commit) from 515a30f7200d69a41610984bee6dc4d967056ad4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f22883e8c131b31b9b1bcc762b3f7317789147fb Author: Marek Vasut <mar...@gm...> Date: Sun Jan 5 22:34:42 2020 +0100 flash/nor: Rename flash_address() to cfi_flash_address() This is a preparatory change, align the function name with the rest of the API, no functional change. Change-Id: I6a810d2a54edcd13ad9a87d24a7334802c41623b Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5391 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 19c63f8eb..bcb1f575f 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -112,7 +112,7 @@ static void cfi_fixup(struct flash_bank *bank, const struct cfi_fixup *fixups) } } -static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32_t offset) +static inline uint32_t cfi_flash_address(struct flash_bank *bank, int sector, uint32_t offset) { struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -193,7 +193,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui uint8_t data[CFI_MAX_BUS_WIDTH]; int retval; - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset), 1, data); if (retval != ERROR_OK) return retval; @@ -217,7 +217,7 @@ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint int i; int retval; - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset), 1, data); if (retval != ERROR_OK) return retval; @@ -246,13 +246,13 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 2; i++) { - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset + i), 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset), 2, data); if (retval != ERROR_OK) return retval; @@ -275,13 +275,13 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 4; i++) { - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset + i), 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { - retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, sector, offset), 4, data); if (retval != ERROR_OK) return retval; @@ -303,11 +303,11 @@ static int cfi_reset(struct flash_bank *bank) struct cfi_flash_bank *cfi_info = bank->driver_priv; int retval = ERROR_OK; - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -315,7 +315,7 @@ static int cfi_reset(struct flash_bank *bank) (cfi_info->device_id == 0x227E || cfi_info->device_id == 0x7E)) { /* Numonix M29W128G is cmd 0xFF intolerant - causes internal undefined state * so we send an extra 0xF0 reset to fix the bug */ - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x00)); if (retval != ERROR_OK) return retval; } @@ -325,7 +325,7 @@ static int cfi_reset(struct flash_bank *bank) static void cfi_intel_clear_status_register(struct flash_bank *bank) { - cfi_send_command(bank, 0x50, flash_address(bank, 0, 0x0)); + cfi_send_command(bank, 0x50, cfi_flash_address(bank, 0, 0x0)); } static int cfi_intel_wait_status_busy(struct flash_bank *bank, int timeout, uint8_t *val) @@ -554,7 +554,7 @@ static int cfi_read_spansion_pri_ext(struct flash_bank *bank) pri_ext->_reversed_geometry = 0; if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) { - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not read spansion bank information"); @@ -661,7 +661,7 @@ static int cfi_read_atmel_pri_ext(struct flash_bank *bank) if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I')) { - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; LOG_ERROR("Could not read atmel bank information"); @@ -889,11 +889,11 @@ static int cfi_intel_erase(struct flash_bank *bank, int first, int last) cfi_intel_clear_status_register(bank); for (i = first; i <= last; i++) { - retval = cfi_send_command(bank, 0x20, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x20, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0xd0, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; @@ -905,7 +905,7 @@ static int cfi_intel_erase(struct flash_bank *bank, int first, int last) if (status == 0x80) bank->sectors[i].is_erased = 1; else { - retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -915,7 +915,7 @@ static int cfi_intel_erase(struct flash_bank *bank, int first, int last) } } - return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + return cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); } static int cfi_spansion_unlock_seq(struct flash_bank *bank) @@ -924,11 +924,11 @@ static int cfi_spansion_unlock_seq(struct flash_bank *bank) struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; - retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1)); + retval = cfi_send_command(bank, 0xaa, cfi_flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2)); + retval = cfi_send_command(bank, 0x55, cfi_flash_address(bank, 0, pri_ext->_unlock2)); if (retval != ERROR_OK) return retval; @@ -947,7 +947,7 @@ static int cfi_spansion_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x80, flash_address(bank, 0, pri_ext->_unlock1)); + retval = cfi_send_command(bank, 0x80, cfi_flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; @@ -955,14 +955,14 @@ static int cfi_spansion_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x30, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x30, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->block_erase_timeout) == ERROR_OK) bank->sectors[i].is_erased = 1; else { - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -972,7 +972,7 @@ static int cfi_spansion_erase(struct flash_bank *bank, int first, int last) } } - return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + return cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); } static int cfi_erase(struct flash_bank *bank, int first, int last) @@ -1025,16 +1025,16 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la cfi_intel_clear_status_register(bank); for (i = first; i <= last; i++) { - retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x60, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; if (set) { - retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x01, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; bank->sectors[i].is_protected = 1; } else { - retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0xd0, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; bank->sectors[i].is_protected = 0; @@ -1051,7 +1051,7 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la } else { uint8_t block_status; /* read block lock bit, to verify status */ - retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55)); + retval = cfi_send_command(bank, 0x90, cfi_flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; retval = cfi_get_u8(bank, i, 0x2, &block_status); @@ -1062,7 +1062,7 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la LOG_ERROR( "couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status); - retval = cfi_send_command(bank, 0x70, flash_address(bank, 0, 0x55)); + retval = cfi_send_command(bank, 0x70, cfi_flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; uint8_t status; @@ -1099,11 +1099,11 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la if (bank->sectors[i].is_protected == 1) { cfi_intel_clear_status_register(bank); - retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x60, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0)); + retval = cfi_send_command(bank, 0x01, cfi_flash_address(bank, i, 0x0)); if (retval != ERROR_OK) return retval; @@ -1115,7 +1115,7 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la } } - return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + return cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); } static int cfi_protect(struct flash_bank *bank, int set, int first, int last) @@ -1587,9 +1587,9 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0)); buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80)); - buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1)); + buf_set_u32(reg_params[6].value, 0, 32, cfi_flash_address(bank, 0, pri_ext->_unlock1)); buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa); - buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2)); + buf_set_u32(reg_params[8].value, 0, 32, cfi_flash_address(bank, 0, pri_ext->_unlock2)); buf_set_u32(reg_params[9].value, 0, 32, 0x55555555); retval = target_run_algorithm(target, 0, NULL, 10, reg_params, @@ -1966,9 +1966,9 @@ static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buff buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width); buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0)); buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80)); - buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1)); + buf_set_u32(reg_params[6].value, 0, 32, cfi_flash_address(bank, 0, pri_ext->_unlock1)); buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa); - buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2)); + buf_set_u32(reg_params[8].value, 0, 32, cfi_flash_address(bank, 0, pri_ext->_unlock2)); buf_set_u32(reg_params[9].value, 0, 32, 0x55555555); retval = target_run_algorithm(target, 0, NULL, 10, reg_params, @@ -2025,7 +2025,7 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t if (retval != ERROR_OK) return retval; if (status != 0x80) { - retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2079,7 +2079,7 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, if (retval != ERROR_OK) return retval; if (status != 0x80) { - retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2110,7 +2110,7 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, return retval; if (status != 0x80) { - retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2132,7 +2132,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0xa0, flash_address(bank, 0, pri_ext->_unlock1)); + retval = cfi_send_command(bank, 0xa0, cfi_flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; @@ -2141,7 +2141,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->word_write_timeout) != ERROR_OK) { - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2207,7 +2207,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word return retval; if (cfi_spansion_wait_status_busy(bank, cfi_info->buf_write_timeout) != ERROR_OK) { - retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2563,7 +2563,7 @@ static int cfi_query_string(struct flash_bank *bank, int address) struct cfi_flash_bank *cfi_info = bank->driver_priv; int retval; - retval = cfi_send_command(bank, 0x98, flash_address(bank, 0, address)); + retval = cfi_send_command(bank, 0x98, cfi_flash_address(bank, 0, address)); if (retval != ERROR_OK) return retval; @@ -2628,21 +2628,21 @@ static int cfi_probe(struct flash_bank *bank) } /* switch to read identifier codes mode ("AUTOSELECT") */ - retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, unlock1)); + retval = cfi_send_command(bank, 0xaa, cfi_flash_address(bank, 0, unlock1)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, unlock2)); + retval = cfi_send_command(bank, 0x55, cfi_flash_address(bank, 0, unlock2)); if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, unlock1)); + retval = cfi_send_command(bank, 0x90, cfi_flash_address(bank, 0, unlock1)); if (retval != ERROR_OK) return retval; - retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x00), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, 0, 0x00), 1, value_buf0); if (retval != ERROR_OK) return retval; - retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x01), + retval = cfi_target_read_memory(bank, cfi_flash_address(bank, 0, 0x01), 1, value_buf1); if (retval != ERROR_OK) return retval; @@ -2946,7 +2946,7 @@ static int cfi_intel_protect_check(struct flash_bank *bank) if (!(pri_ext->blk_status_reg_mask & 0x1)) return ERROR_FLASH_OPERATION_FAILED; - retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55)); + retval = cfi_send_command(bank, 0x90, cfi_flash_address(bank, 0, 0x55)); if (retval != ERROR_OK) return retval; @@ -2962,7 +2962,7 @@ static int cfi_intel_protect_check(struct flash_bank *bank) bank->sectors[i].is_protected = 0; } - return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); + return cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0)); } static int cfi_spansion_protect_check(struct flash_bank *bank) @@ -2976,7 +2976,7 @@ static int cfi_spansion_protect_check(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, pri_ext->_unlock1)); + retval = cfi_send_command(bank, 0x90, cfi_flash_address(bank, 0, pri_ext->_unlock1)); if (retval != ERROR_OK) return retval; @@ -2992,7 +2992,7 @@ static int cfi_spansion_protect_check(struct flash_bank *bank) bank->sectors[i].is_protected = 0; } - return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); + return cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0)); } static int cfi_protect_check(struct flash_bank *bank) commit 76de1c8de104496f26a1cd084b755008349fa064 Author: Marek Vasut <mar...@gm...> Date: Sun Jan 5 22:33:29 2020 +0100 flash/nor: Rename get_cfi_info() to cfi_get_info() This is a preparatory change, align the function name with the rest of the API, no functional change. Change-Id: Ib967520f027b03eb1792b36ede52335df8e23941 Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5390 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 0437930b2..19c63f8eb 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -3023,7 +3023,7 @@ static int cfi_protect_check(struct flash_bank *bank) return ERROR_OK; } -static int get_cfi_info(struct flash_bank *bank, char *buf, int buf_size) +static int cfi_get_info(struct flash_bank *bank, char *buf, int buf_size) { int printed; struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -3134,6 +3134,6 @@ const struct flash_driver cfi_flash = { /* FIXME: access flash at bus_width size */ .erase_check = default_flash_blank_check, .protect_check = cfi_protect_check, - .info = get_cfi_info, + .info = cfi_get_info, .free_driver_priv = default_flash_free_driver_priv, }; commit 3192717ae910d387476b3a7980c325ceb0d2f733 Author: Marek Vasut <mar...@gm...> Date: Sat Apr 13 22:44:45 2019 +0200 flash/nor: Allow CFI memory read/write functions be overriden Add possibility to supply custom CFI memory accessors via cfi_info and override the default memory-mapped ones. Change-Id: I1b6bc1db69fc33e8cdef96c41742c40e6d8917e9 Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5147 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 14f9b1130..0437930b2 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -134,15 +134,25 @@ static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32 static int cfi_target_write_memory(struct flash_bank *bank, target_addr_t addr, uint32_t count, const uint8_t *buffer) { - return target_write_memory(bank->target, addr, bank->bus_width, - count, buffer); + struct cfi_flash_bank *cfi_info = bank->driver_priv; + if (cfi_info->write_mem) { + return cfi_info->write_mem(bank, addr, count, buffer); + } else { + return target_write_memory(bank->target, addr, bank->bus_width, + count, buffer); + } } static int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr, uint32_t count, uint8_t *buffer) { - return target_read_memory(bank->target, addr, bank->bus_width, - count, buffer); + struct cfi_flash_bank *cfi_info = bank->driver_priv; + if (cfi_info->read_mem) { + return cfi_info->read_mem(bank, addr, count, buffer); + } else { + return target_read_memory(bank->target, addr, bank->bus_width, + count, buffer); + } } static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) diff --git a/src/flash/nor/cfi.h b/src/flash/nor/cfi.h index ed858a9de..9451faae6 100644 --- a/src/flash/nor/cfi.h +++ b/src/flash/nor/cfi.h @@ -73,6 +73,12 @@ struct cfi_flash_bank { unsigned buf_write_timeout; unsigned block_erase_timeout; unsigned chip_erase_timeout; + + /* memory accessors */ + int (*write_mem)(struct flash_bank *bank, target_addr_t addr, + uint32_t count, const uint8_t *buffer); + int (*read_mem)(struct flash_bank *bank, target_addr_t addr, + uint32_t count, uint8_t *buffer); }; /* Intel primary extended query table ----------------------------------------------------------------------- Summary of changes: src/flash/nor/cfi.c | 124 ++++++++++++++++++++++++++++------------------------ src/flash/nor/cfi.h | 6 +++ 2 files changed, 73 insertions(+), 57 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 12:26:27
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 515a30f7200d69a41610984bee6dc4d967056ad4 (commit) via f83ce0a2ef7fa9c844d4591e4586911c14c44ac8 (commit) from 7fffa3cbc6f85480eaf1498d30c45af5933bd017 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 515a30f7200d69a41610984bee6dc4d967056ad4 Author: Marek Vasut <mar...@gm...> Date: Sun Jan 5 17:26:18 2020 +0100 flash/nor: Drop size argument of cfi_target_{read,write}_memory() The size argument is always set to bank->bus_width and bank pointer is now passed into cfi_target_{read,write}_memory(), so the size can be accessed through the bank pointer inside the function instead of being explicitly passed in. Change-Id: I0abc1cc3bf513281c10cb5de7a21cb0e75cb7676 Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5389 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 3e265dd39..14f9b1130 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -132,17 +132,17 @@ static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32 } static int cfi_target_write_memory(struct flash_bank *bank, target_addr_t addr, - uint32_t size, uint32_t count, - const uint8_t *buffer) + uint32_t count, const uint8_t *buffer) { - return target_write_memory(bank->target, addr, size, count, buffer); + return target_write_memory(bank->target, addr, bank->bus_width, + count, buffer); } static int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr, - uint32_t size, uint32_t count, - uint8_t *buffer) + uint32_t count, uint8_t *buffer) { - return target_read_memory(bank->target, addr, size, count, buffer); + return target_read_memory(bank->target, addr, bank->bus_width, + count, buffer); } static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) @@ -170,7 +170,7 @@ static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t addre uint8_t command[CFI_MAX_BUS_WIDTH]; cfi_command(bank, cmd, command); - return cfi_target_write_memory(bank, address, bank->bus_width, 1, command); + return cfi_target_write_memory(bank, address, 1, command); } /* read unsigned 8-bit value from the bank @@ -184,7 +184,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui int retval; retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), - bank->bus_width, 1, data); + 1, data); if (retval != ERROR_OK) return retval; @@ -208,7 +208,7 @@ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint int retval; retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), - bank->bus_width, 1, data); + 1, data); if (retval != ERROR_OK) return retval; @@ -237,13 +237,13 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u uint8_t i; for (i = 0; i < 2; i++) { retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), - bank->bus_width, 1, &data[i * bank->bus_width]); + 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), - bank->bus_width, 2, data); + 2, data); if (retval != ERROR_OK) return retval; } @@ -266,13 +266,13 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u uint8_t i; for (i = 0; i < 4; i++) { retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), - bank->bus_width, 1, &data[i * bank->bus_width]); + 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), - bank->bus_width, 4, data); + 4, data); if (retval != ERROR_OK) return retval; } @@ -2006,7 +2006,7 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(bank, address, bank->bus_width, 1, word); + retval = cfi_target_write_memory(bank, address, 1, word); if (retval != ERROR_OK) return retval; @@ -2086,7 +2086,7 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(bank, address, bank->bus_width, bufferwsize, word); + retval = cfi_target_write_memory(bank, address, bufferwsize, word); if (retval != ERROR_OK) return retval; @@ -2126,7 +2126,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(bank, address, bank->bus_width, 1, word); + retval = cfi_target_write_memory(bank, address, 1, word); if (retval != ERROR_OK) return retval; @@ -2187,7 +2187,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(bank, address, bank->bus_width, bufferwsize, word); + retval = cfi_target_write_memory(bank, address, bufferwsize, word); if (retval != ERROR_OK) return retval; @@ -2288,7 +2288,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u LOG_INFO("Fixup %d unaligned read head bytes", align); /* read a complete word from flash */ - retval = cfi_target_read_memory(bank, read_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, read_p, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2301,7 +2301,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u align = count / bank->bus_width; if (align) { - retval = cfi_target_read_memory(bank, read_p, bank->bus_width, align, buffer); + retval = cfi_target_read_memory(bank, read_p, align, buffer); if (retval != ERROR_OK) return retval; @@ -2314,7 +2314,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u LOG_INFO("Fixup %" PRIu32 " unaligned read tail bytes", count); /* read a complete word from flash */ - retval = cfi_target_read_memory(bank, read_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, read_p, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2358,7 +2358,7 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of LOG_INFO("Fixup %d unaligned head bytes", align); /* read a complete word from flash */ - retval = cfi_target_read_memory(bank, write_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, write_p, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2478,7 +2478,7 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count); /* read a complete word from flash */ - retval = cfi_target_read_memory(bank, write_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, write_p, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2629,11 +2629,11 @@ static int cfi_probe(struct flash_bank *bank) return retval; retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x00), - bank->bus_width, 1, value_buf0); + 1, value_buf0); if (retval != ERROR_OK) return retval; retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x01), - bank->bus_width, 1, value_buf1); + 1, value_buf1); if (retval != ERROR_OK) return retval; switch (bank->chip_width) { commit f83ce0a2ef7fa9c844d4591e4586911c14c44ac8 Author: Marek Vasut <mar...@gm...> Date: Sun Apr 21 16:28:10 2019 +0200 flash/nor: Pass flash_bank to memory accessors Replace passing in struct target with passing in struct flash_bank, so that the later can contain function pointers to custom per-driver memory accessor functions. Change-Id: Id2573a6d5f1a73ed9c4f73c53592a9a335a11c99 Signed-off-by: Marek Vasut <mar...@gm...> Reviewed-on: http://openocd.zylin.com/5146 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index c22bcdecb..3e265dd39 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -131,18 +131,18 @@ static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32 } } -static int cfi_target_write_memory(struct target *target, target_addr_t addr, +static int cfi_target_write_memory(struct flash_bank *bank, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { - return target_write_memory(target, addr, size, count, buffer); + return target_write_memory(bank->target, addr, size, count, buffer); } -static int cfi_target_read_memory(struct target *target, target_addr_t addr, +static int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { - return target_read_memory(target, addr, size, count, buffer); + return target_read_memory(bank->target, addr, size, count, buffer); } static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) @@ -170,7 +170,7 @@ static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t addre uint8_t command[CFI_MAX_BUS_WIDTH]; cfi_command(bank, cmd, command); - return cfi_target_write_memory(bank->target, address, bank->bus_width, 1, command); + return cfi_target_write_memory(bank, address, bank->bus_width, 1, command); } /* read unsigned 8-bit value from the bank @@ -179,12 +179,11 @@ static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t addre */ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { - struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH]; int retval; - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), bank->bus_width, 1, data); if (retval != ERROR_OK) return retval; @@ -203,13 +202,12 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui */ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { - struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH]; int i; int retval; - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), bank->bus_width, 1, data); if (retval != ERROR_OK) return retval; @@ -231,7 +229,6 @@ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, uint16_t *val) { - struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH * 2]; int retval; @@ -239,13 +236,13 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 2; i++) { - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset + i), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), bank->bus_width, 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), bank->bus_width, 2, data); if (retval != ERROR_OK) return retval; @@ -261,7 +258,6 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, uint32_t *val) { - struct target *target = bank->target; struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH * 4]; int retval; @@ -269,13 +265,13 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u if (cfi_info->x16_as_x8) { uint8_t i; for (i = 0; i < 4; i++) { - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset + i), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset + i), bank->bus_width, 1, &data[i * bank->bus_width]); if (retval != ERROR_OK) return retval; } } else { - retval = cfi_target_read_memory(target, flash_address(bank, sector, offset), + retval = cfi_target_read_memory(bank, flash_address(bank, sector, offset), bank->bus_width, 4, data); if (retval != ERROR_OK) return retval; @@ -2004,14 +2000,13 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; - struct target *target = bank->target; cfi_intel_clear_status_register(bank); retval = cfi_send_command(bank, 0x40, address); if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(target, address, bank->bus_width, 1, word); + retval = cfi_target_write_memory(bank, address, bank->bus_width, 1, word); if (retval != ERROR_OK) return retval; @@ -2038,7 +2033,6 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; - struct target *target = bank->target; /* Calculate buffer size and boundary mask * buffersize is (buffer size per chip) * (number of chips) @@ -2092,7 +2086,7 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(target, address, bank->bus_width, bufferwsize, word); + retval = cfi_target_write_memory(bank, address, bank->bus_width, bufferwsize, word); if (retval != ERROR_OK) return retval; @@ -2123,7 +2117,6 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; - struct target *target = bank->target; retval = cfi_spansion_unlock_seq(bank); if (retval != ERROR_OK) @@ -2133,7 +2126,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(target, address, bank->bus_width, 1, word); + retval = cfi_target_write_memory(bank, address, bank->bus_width, 1, word); if (retval != ERROR_OK) return retval; @@ -2155,7 +2148,6 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word { int retval; struct cfi_flash_bank *cfi_info = bank->driver_priv; - struct target *target = bank->target; /* Calculate buffer size and boundary mask * buffersize is (buffer size per chip) * (number of chips) @@ -2195,7 +2187,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word if (retval != ERROR_OK) return retval; - retval = cfi_target_write_memory(target, address, bank->bus_width, bufferwsize, word); + retval = cfi_target_write_memory(bank, address, bank->bus_width, bufferwsize, word); if (retval != ERROR_OK) return retval; @@ -2268,7 +2260,6 @@ static int cfi_write_words(struct flash_bank *bank, const uint8_t *word, static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; - struct target *target = bank->target; uint32_t address = bank->base + offset; uint32_t read_p; int align; /* number of unaligned bytes */ @@ -2297,7 +2288,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u LOG_INFO("Fixup %d unaligned read head bytes", align); /* read a complete word from flash */ - retval = cfi_target_read_memory(target, read_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, read_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2310,7 +2301,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u align = count / bank->bus_width; if (align) { - retval = cfi_target_read_memory(target, read_p, bank->bus_width, align, buffer); + retval = cfi_target_read_memory(bank, read_p, bank->bus_width, align, buffer); if (retval != ERROR_OK) return retval; @@ -2323,7 +2314,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u LOG_INFO("Fixup %" PRIu32 " unaligned read tail bytes", count); /* read a complete word from flash */ - retval = cfi_target_read_memory(target, read_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, read_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2338,7 +2329,6 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; - struct target *target = bank->target; uint32_t address = bank->base + offset; /* address of first byte to be programmed */ uint32_t write_p; int align; /* number of unaligned bytes */ @@ -2368,7 +2358,7 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of LOG_INFO("Fixup %d unaligned head bytes", align); /* read a complete word from flash */ - retval = cfi_target_read_memory(target, write_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, write_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2488,7 +2478,7 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count); /* read a complete word from flash */ - retval = cfi_target_read_memory(target, write_p, bank->bus_width, 1, current_word); + retval = cfi_target_read_memory(bank, write_p, bank->bus_width, 1, current_word); if (retval != ERROR_OK) return retval; @@ -2638,11 +2628,11 @@ static int cfi_probe(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - retval = cfi_target_read_memory(target, flash_address(bank, 0, 0x00), + retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x00), bank->bus_width, 1, value_buf0); if (retval != ERROR_OK) return retval; - retval = cfi_target_read_memory(target, flash_address(bank, 0, 0x01), + retval = cfi_target_read_memory(bank, flash_address(bank, 0, 0x01), bank->bus_width, 1, value_buf1); if (retval != ERROR_OK) return retval; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/cfi.c | 78 +++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 44 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:47:15
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 7fffa3cbc6f85480eaf1498d30c45af5933bd017 (commit) via af0dda82666e1e4f241fabc0db62212d51413a08 (commit) via fe6bb7eac8c7028236306c562d24a25ef79d0c15 (commit) from 57afa176ce858ad6505a9a962df5d7e978d349bf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7fffa3cbc6f85480eaf1498d30c45af5933bd017 Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:54:29 2019 +0100 target/xscale: remove duplicated command Reported by clang static analyzer. Change-Id: I893af10852af4885507ed62d024008159a80dd56 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5382 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/xscale.c b/src/target/xscale.c index 1a099c946..3ef8922b5 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -3227,7 +3227,6 @@ COMMAND_HANDLER(xscale_handle_vector_catch_command) if (retval != ERROR_OK) return retval; - dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32); if (CMD_ARGC > 0) { if (CMD_ARGC == 1) { if (strcmp(CMD_ARGV[0], "all") == 0) { commit af0dda82666e1e4f241fabc0db62212d51413a08 Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:50:26 2019 +0100 target/etm: add check for calloc error and fix one more clang static analyzer warning. Change-Id: I17f03e318e1cf7617e7f753e7ca960552be547e5 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5381 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/etm.c b/src/target/etm.c index 5751348e7..d1cfe61f6 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -303,6 +303,11 @@ struct reg_cache *etm_build_reg_cache(struct target *target, reg_list = calloc(128, sizeof(struct reg)); arch_info = calloc(128, sizeof(struct etm_reg)); + if (reg_cache == NULL || reg_list == NULL || arch_info == NULL) { + LOG_ERROR("No memory"); + goto fail; + } + /* fill in values for the reg cache */ reg_cache->name = "etm registers"; reg_cache->next = NULL; @@ -498,6 +503,7 @@ static int etm_read_reg_w_check(struct reg *reg, uint8_t *check_value, uint8_t *check_mask) { struct etm_reg *etm_reg = reg->arch_info; + assert(etm_reg); const struct etm_reg_info *r = etm_reg->reg_info; uint8_t reg_addr = r->addr & 0x7f; struct scan_field fields[3]; commit fe6bb7eac8c7028236306c562d24a25ef79d0c15 Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:48:46 2019 +0100 target/semihosting_common: fix minor memory leak Reported by clang static analyzer. Change-Id: Ie663f49d92588c0d8b502cfdd8fc34004b308066 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5380 Reviewed-by: Liviu Ionescu <il...@li...> Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index ce6a79171..a41f8e4c8 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -944,6 +944,8 @@ int semihosting_common(struct target *target) uint8_t *fn1 = malloc(len1+1); uint8_t *fn2 = malloc(len2+1); if (!fn1 || !fn2) { + free(fn1); + free(fn2); semihosting->result = -1; semihosting->sys_errno = ENOMEM; } else { ----------------------------------------------------------------------- Summary of changes: src/target/etm.c | 6 ++++++ src/target/semihosting_common.c | 2 ++ src/target/xscale.c | 1 - 3 files changed, 8 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:46:39
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 57afa176ce858ad6505a9a962df5d7e978d349bf (commit) via b04d9c05f0eadc7161465755c05a1f3c1bd6a85b (commit) via 8bb1998e6afe8488c44828e69b5b0d5092f39545 (commit) from 5dd5cf26bd18ddaacbdbded881cfbefacda71631 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 57afa176ce858ad6505a9a962df5d7e978d349bf Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:48:13 2019 +0100 target/target: fix clang static analyzer warnings Change-Id: I23e6586be60915f21a7179a994a1ec93fb9b2c36 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5379 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/target.c b/src/target/target.c index 1ec2ee2ed..936a5da0d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1682,7 +1682,7 @@ static int target_call_timer_callbacks_check_time(int checktime) * next item; initially, that's a standalone "root of the * list" variable. */ struct target_timer_callback **callback = &target_timer_callbacks; - while (*callback) { + while (callback && *callback) { if ((*callback)->removed) { struct target_timer_callback *p = *callback; *callback = (*callback)->next; commit b04d9c05f0eadc7161465755c05a1f3c1bd6a85b Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:46:46 2019 +0100 target/avr32_jtag: fix error returns Fixed only 2 error returns discovered by clang static analyzer. There are obviously many more missing error tests in avr32_jtag.c These was not fixed to keep this change minimal. Not tested with hw. Change-Id: I6c79f6248db774990ddb42c0dacdb621651ed69e Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5378 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/avr32_jtag.c b/src/target/avr32_jtag.c index 6526810e2..c17fbe7f0 100644 --- a/src/target/avr32_jtag.c +++ b/src/target/avr32_jtag.c @@ -173,19 +173,15 @@ int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info, { avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); avr32_jtag_nexus_set_address(jtag_info, addr, MODE_READ); - avr32_jtag_nexus_read_data(jtag_info, value); - - return ERROR_OK; - + return avr32_jtag_nexus_read_data(jtag_info, value); } + int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info, uint32_t addr, uint32_t value) { avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); avr32_jtag_nexus_set_address(jtag_info, addr, MODE_WRITE); - avr32_jtag_nexus_write_data(jtag_info, value); - - return ERROR_OK; + return avr32_jtag_nexus_write_data(jtag_info, value); } int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave, commit 8bb1998e6afe8488c44828e69b5b0d5092f39545 Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:45:20 2019 +0100 target/arm_dpm: add missing error returns Discoverd by clang static analyzer. Change-Id: I93d5de0a36216e62b170fe8cc870431226a7777f Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5377 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 8b9957033..f5dd22d8b 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -145,6 +145,9 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) retval = dpm->instr_read_data_r0(dpm, ARMV4_5_VMOV(1, 1, 0, ((regnum - ARM_VFP_V3_D0) >> 4), ((regnum - ARM_VFP_V3_D0) & 0xf)), &value_r0); + if (retval != ERROR_OK) + break; + /* read r1 via dcc */ retval = dpm->instr_read_data_dcc(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0), @@ -248,6 +251,9 @@ static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum retval = dpm->instr_write_data_dcc(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), value_r1); + if (retval != ERROR_OK) + break; + /* write value_r0 to r0 via dcc then, * move to double word register from r0:r1: "vmov vm, r0, r1" */ ----------------------------------------------------------------------- Summary of changes: src/target/arm_dpm.c | 6 ++++++ src/target/avr32_jtag.c | 10 +++------- src/target/target.c | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:46:06
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 5dd5cf26bd18ddaacbdbded881cfbefacda71631 (commit) via 98a8b99ef37542dc34e1b247d9946a127d4ab70d (commit) from 35d9bf9917fc9c00a6b8e941a5479e85878ef33c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5dd5cf26bd18ddaacbdbded881cfbefacda71631 Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:43:55 2019 +0100 target/arm946e: add missing error detection Discoverd by clang static analyzer. While on it remove useless type casts from arm946e_read_cp15() parameter. Change-Id: I549e19685b431400243800ee0f7d1bbe6cdb14b4 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5376 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/target/arm946e.c b/src/target/arm946e.c index 112631a7c..4ef167a9d 100644 --- a/src/target/arm946e.c +++ b/src/target/arm946e.c @@ -267,7 +267,11 @@ uint32_t arm946e_invalidate_whole_dcache(struct target *target) /* Read dtag */ uint32_t dtag; - arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag); + retval = arm946e_read_cp15(target, 0x16, &dtag); + if (retval != ERROR_OK) { + LOG_DEBUG("ERROR reading dtag"); + return retval; + } /* Check cache line VALID bit */ if (!(dtag >> 4 & 0x1)) @@ -321,7 +325,7 @@ int arm946e_post_debug_entry(struct target *target) /* See if CACHES are enabled, and save that info * in the context bits, so that arm946e_pre_restore_context() can use them */ - arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg); + arm946e_read_cp15(target, CP15_CTL, &ctr_reg); /* Save control reg in the context */ arm946e->cp15_control_reg = ctr_reg; @@ -362,7 +366,7 @@ void arm946e_pre_restore_context(struct target *target) if (arm946e_preserve_cache) { struct arm946e_common *arm946e = target_to_arm946(target); /* Get the contents of the CTR reg */ - arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg); + arm946e_read_cp15(target, CP15_CTL, &ctr_reg); /** * Read-modify-write CP15 control @@ -410,7 +414,11 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address, } /* Read dtag */ - arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag); + retval = arm946e_read_cp15(target, 0x16, &dtag); + if (retval != ERROR_OK) { + LOG_DEBUG("ERROR reading dtag"); + return retval; + } /* Check cache line VALID bit */ if (!(dtag >> 4 & 0x1)) @@ -463,7 +471,11 @@ uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address, } /* Read itag */ - arm946e_read_cp15(target, 0x17, (uint32_t *) &itag); + retval = arm946e_read_cp15(target, 0x17, &itag); + if (retval != ERROR_OK) { + LOG_DEBUG("ERROR reading itag"); + return retval; + } /* Check cache line VALID bit */ if (!(itag >> 4 & 0x1)) commit 98a8b99ef37542dc34e1b247d9946a127d4ab70d Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:40:07 2019 +0100 server/server: fix clang static analyzer warning Change-Id: I317e189b62540e3688a20d88a95f551280317f14 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5373 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/server/server.c b/src/server/server.c index 9e63f74f4..8e641176a 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -562,7 +562,7 @@ int server_loop(struct command_context *command_context) struct connection *c; for (c = service->connections; c; ) { - if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) { + if ((c->fd >= 0 && FD_ISSET(c->fd, &read_fds)) || c->input_pending) { retval = service->input(c); if (retval != ERROR_OK) { struct connection *next = c->next; ----------------------------------------------------------------------- Summary of changes: src/server/server.c | 2 +- src/target/arm946e.c | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:45:21
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 35d9bf9917fc9c00a6b8e941a5479e85878ef33c (commit) from 251eb035fc72c8fe6348fa21d8c8d8faa9902988 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 35d9bf9917fc9c00a6b8e941a5479e85878ef33c Author: Tomas Vanek <va...@fb...> Date: Fri Dec 20 23:38:42 2019 +0100 xsvf: fix memory leak Discovered by clang static analyzer. Change-Id: I2980586aea5ee43226adb1f4cf72e7ba1dfddd83 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5372 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index e574c6f0e..bec32f21e 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -918,8 +918,10 @@ COMMAND_HANDLER(handle_xsvf_command) struct scan_field field; result = svf_add_statemove(loop_state); - if (result != ERROR_OK) + if (result != ERROR_OK) { + free(dr_in_mask); return result; + } jtag_add_clocks(loop_clocks); jtag_add_sleep(loop_usecs); ----------------------------------------------------------------------- Summary of changes: src/xsvf/xsvf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:42:23
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 251eb035fc72c8fe6348fa21d8c8d8faa9902988 (commit) from a6a642bf72a12c9a1fc4b92de2dc46d12cb3b58e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 251eb035fc72c8fe6348fa21d8c8d8faa9902988 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Jan 6 18:33:42 2020 +0100 flash/nor/stm32l4x: add support of STM32L4P5/L4Q5x devices STM32L4P/Q devices have: - similar flash layout as STM32L4R/S devices - 1024K of flash memory (some parts have 512K only) tested on NUCLEO-L4P5ZG using board/st_nucleo_l4.cfg Change-Id: I77047351bc7dcd7c76d0f31a77be73005104a06f Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5392 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index a373f1168..3d1537756 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -51,12 +51,17 @@ * RM0394 devices have a single bank only. * * RM0432 devices have single and dual bank operating modes. - * The FLASH size is 1Mbyte or 2Mbyte. + * - for STM32L4R/Sxx the FLASH size is 2Mbyte or 1Mbyte. + * - for STM32L4P/Q5x the FLASH size is 1Mbyte or 512Kbyte. * Bank page (sector) size is 4Kbyte (dual mode) or 8Kbyte (single mode). * * Bank mode is controlled by two different bits in option bytes register. - * In 2M FLASH devices bit 22 (DBANK) controls Dual Bank mode. - * In 1M FLASH devices bit 21 (DB1M) controls Dual Bank mode. + * - for STM32L4R/Sxx + * In 2M FLASH devices bit 22 (DBANK) controls Dual Bank mode. + * In 1M FLASH devices bit 21 (DB1M) controls Dual Bank mode. + * - for STM32L4P5/Q5x + * In 1M FLASH devices bit 22 (DBANK) controls Dual Bank mode. + * In 512K FLASH devices bit 21 (DB512K) controls Dual Bank mode. * */ @@ -169,6 +174,10 @@ static const struct stm32l4_rev stm32_470_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" }, }; +static const struct stm32l4_rev stm32_471_revs[] = { + { 0x1000, "1" }, +}; + static const struct stm32l4_rev stm32_495_revs[] = { { 0x2001, "2.1" }, }; @@ -234,6 +243,16 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .flash_regs_base = 0x40022000, .fsize_addr = 0x1FFF75E0, }, + { + .id = 0x471, + .revs = stm32_471_revs, + .num_revs = ARRAY_SIZE(stm32_471_revs), + .device_str = "STM32L4P5/L4Q5x", + .max_flash_size_kb = 1024, + .has_dual_bank = true, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, { .id = 0x495, .revs = stm32_495_revs, @@ -801,17 +820,22 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages; break; case 0x470: + case 0x471: /* STM32L4R/S can be single/dual bank: * if size = 2M check DBANK bit(22) * if size = 1M check DB1M bit(21) + * STM32L4P/Q can be single/dual bank + * if size = 1M check DBANK bit(22) + * if size = 512K check DB512K bit(21) * in single bank configuration the page size is 8K * else (dual bank) the page size is 4K without gap between banks */ page_size = 8192; num_pages = flash_size_in_kb / 8; stm32l4_info->bank1_sectors = num_pages; - if ((flash_size_in_kb == 2048 && (options & BIT(22))) || - (flash_size_in_kb == 1024 && (options & BIT(21)))) { + const bool use_dbank_bit = flash_size_in_kb == part_info->max_flash_size_kb; + if ((use_dbank_bit && (options & BIT(22))) || + (!use_dbank_bit && (options & BIT(21)))) { stm32l4_info->dual_bank_mode = true; page_size = 4096; num_pages = flash_size_in_kb / 4; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:39:41
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via a6a642bf72a12c9a1fc4b92de2dc46d12cb3b58e (commit) from 8536306b6ebcee8249376734d64db40a07916c9d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a6a642bf72a12c9a1fc4b92de2dc46d12cb3b58e Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Jan 6 17:19:31 2020 +0100 flash/nor: add support of STM32WB on top STM32L4 flash driver Change-Id: I9fb6700085d817d35a691f6484193f67939a4e0f Signed-off-by: Laurent LEMELE <lau...@st...> Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/4933 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/doc/openocd.texi b/doc/openocd.texi index b79325276..c526a632a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6869,7 +6869,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn {Flash Driver} stm32l4x -All members of the STM32L4 microcontroller families from STMicroelectronics +All members of the STM32L4 and STM32WB microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @@ -6911,7 +6911,9 @@ is the register offset of the Option byte to read. For example to read the FLASH_OPTR register: @example stm32l4x option_read 0 0x20 -# Option Register: <0x40022020> = 0xffeff8aa +# Option Register (for STM32L4x): <0x40022020> = 0xffeff8aa +# Option Register (for STM32WBx): <0x58004020> = ... +# The correct flash base address will be used automatically @end example The above example will read out the FLASH_OPTR register which contains the RDP diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 9057872ac..a373f1168 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -169,6 +169,10 @@ static const struct stm32l4_rev stm32_470_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" }, }; +static const struct stm32l4_rev stm32_495_revs[] = { + { 0x2001, "2.1" }, +}; + static const struct stm32l4_part_info stm32l4_parts[] = { { .id = 0x415, @@ -230,6 +234,16 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .flash_regs_base = 0x40022000, .fsize_addr = 0x1FFF75E0, }, + { + .id = 0x495, + .revs = stm32_495_revs, + .num_revs = ARRAY_SIZE(stm32_495_revs), + .device_str = "STM32WB5x", + .max_flash_size_kb = 1024, + .has_dual_bank = false, + .flash_regs_base = 0x58004000, + .fsize_addr = 0x1FFF75E0, + }, }; /* flash bank stm32l4x <base> <size> 0 0 <target#> */ @@ -714,7 +728,7 @@ static int stm32l4_probe(struct flash_bank *bank) } if (!stm32l4_info->part_info) { - LOG_WARNING("Cannot identify target as an STM32L4 family device."); + LOG_WARNING("Cannot identify target as an STM32 L4 or WB family device."); return ERROR_FAIL; } @@ -804,6 +818,12 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case 0x495: + /* single bank flash */ + page_size = 4096; + num_pages = flash_size_in_kb / 4; + stm32l4_info->bank1_sectors = num_pages; + break; default: LOG_ERROR("unsupported device"); return ERROR_FAIL; @@ -881,7 +901,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) part_info->device_str, rev_id); return ERROR_OK; } else { - snprintf(buf, buf_size, "Cannot identify target as a STM32L4x device"); + snprintf(buf, buf_size, "Cannot identify target as an STM32 L4 or WB device"); return ERROR_FAIL; } diff --git a/tcl/target/stm32wbx.cfg b/tcl/target/stm32wbx.cfg new file mode 100644 index 000000000..138bcf186 --- /dev/null +++ b/tcl/target/stm32wbx.cfg @@ -0,0 +1,103 @@ +# script for stm32wbx family + +# +# stm32wb devices support both JTAG and SWD transports. +# +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32wbx +} + +set _ENDIAN little + +# Work-area is a space in RAM used for flash programming +# By default use 64kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + set _CPUTAPID 0x6ba00477 + } else { + # SWD IDCODE (single drop, arm) + set _CPUTAPID 0x6ba02477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME + +# Common knowledges tells JTAG speed should be <= F_CPU/6. +# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on +# the safe side. +# +# Note that there is a pretty wide band where things are +# more or less stable, see http://openocd.zylin.com/#/c/3366/ +adapter_khz 500 + +adapter_nsrst_delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +$_TARGETNAME configure -event reset-init { + # CPU comes out of reset with MSI_ON | MSI_RDY | MSI Range 4 MHz. + # Configure system to use MSI 24 MHz clock, compliant with VOS default Range1. + # 2 WS compliant with VOS=Range1 and 24 MHz. + mmw 0x58004000 0x00000102 0 ;# FLASH_ACR |= PRFTBE | 2(Latency) + mmw 0x58000000 0x00000091 0 ;# RCC_CR = MSI_ON | MSI Range 24 MHz + # Boost JTAG frequency + adapter_khz 4000 +} + +$_TARGETNAME configure -event reset-start { + # Reset clock is MSI (4 MHz) + adapter_khz 500 +} + +$_TARGETNAME configure -event examine-end { + # Enable debug during low power modes (uses more power) + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP + mmw 0xE0042004 0x00000007 0 + + # Stop watchdog counters during halt + # DBGMCU_APB1_FZR1 |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0xE004203C 0x00001800 0 +} + +$_TARGETNAME configure -event trace-config { + # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync + # change this value accordingly to configure trace pins + # assignment + mmw 0xE0042004 0x00000020 0 +} ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 6 ++-- src/flash/nor/stm32l4x.c | 24 +++++++++++-- tcl/target/{stm32l4x.cfg => stm32wbx.cfg} | 56 +++++++++++++++---------------- 3 files changed, 54 insertions(+), 32 deletions(-) copy tcl/target/{stm32l4x.cfg => stm32wbx.cfg} (57%) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:37:29
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 8536306b6ebcee8249376734d64db40a07916c9d (commit) from cc85ebc5acb03a51aafad2e3d913a3c894d93407 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8536306b6ebcee8249376734d64db40a07916c9d Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Jan 6 15:47:09 2020 +0100 flash/nor: add support of STM32L41/L42xx tested using STM32L412KB Change-Id: I1e2ae93d8c740db219f0fb579940de7f2fffac15 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/4934 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 6aed7731c..9057872ac 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -161,6 +161,10 @@ static const struct stm32l4_rev stm32_462_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, }; +static const struct stm32l4_rev stm32_464_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32_470_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" }, }; @@ -206,6 +210,16 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .flash_regs_base = 0x40022000, .fsize_addr = 0x1FFF75E0, }, + { + .id = 0x464, + .revs = stm32_464_revs, + .num_revs = ARRAY_SIZE(stm32_464_revs), + .device_str = "STM32L41/L42xx", + .max_flash_size_kb = 128, + .has_dual_bank = false, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, { .id = 0x470, .revs = stm32_470_revs, @@ -766,6 +780,7 @@ static int stm32l4_probe(struct flash_bank *bank) break; case 0x435: case 0x462: + case 0x464: /* single bank flash */ page_size = 2048; num_pages = flash_size_in_kb / 2; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-16 09:35:33
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via cc85ebc5acb03a51aafad2e3d913a3c894d93407 (commit) from ed8fa09cfff93dc29903e33e92d36988a30a9529 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cc85ebc5acb03a51aafad2e3d913a3c894d93407 Author: Tarek BOCHKATI <tar...@gm...> Date: Sun Jan 5 23:19:41 2020 +0100 flash/nor/stm32l4x : add structure containers to hold devices' information This rework is inspired from the 'flash/nor/stm32h7x.c' This rework will ease the support of new devices on top of this driver: for example: STM32WB have different flash base and size addresses Notes: - stm32l4_probe modified in order to charge the correct part_info from the defined stm32l4_parts according to the device id - stm32l4_flash_bank.bank2_start is replaced by .part_info->bank1_sectors - STM32_FLASH_BASE is removed , part_info->flash_regs_base will be used instead based on that flash register addresses are changed to offsets, >> stm32l4_get_flash_reg was modified accordingly - stm32l4_read_option and stm32l4_write_option was modified to accept an offset instead of an absolute address, luckily this is the commands' argument by default - stm32l4_mass_erase modifications : - use MER2 only on top of dual bank devices - wait for BUSY bit before starting the mass erase Change-Id: Ib35bfc3cbadc76bbeaaaba9005b82077b9e1e744 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/4932 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Andreas Bolsch <hyp...@gm...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index f680542c7..6aed7731c 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1,7 +1,10 @@ /*************************************************************************** * Copyright (C) 2015 by Uwe Bonnes * * bo...@el... * - * + * * + * Copyright (C) 2019 by Tarek Bochkati for STMicroelectronics * + * tar...@gm... * + * * * 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 2 of the License, or * @@ -24,6 +27,7 @@ #include <helper/binarybuffer.h> #include <target/algorithm.h> #include <target/armv7m.h> +#include "bits.h" /* STM32L4xxx series for reference. * @@ -60,36 +64,34 @@ #define FLASH_ERASE_TIMEOUT 250 -#define STM32_FLASH_BASE 0x40022000 -#define STM32_FLASH_ACR 0x40022000 -#define STM32_FLASH_KEYR 0x40022008 -#define STM32_FLASH_OPTKEYR 0x4002200c -#define STM32_FLASH_SR 0x40022010 -#define STM32_FLASH_CR 0x40022014 -#define STM32_FLASH_OPTR 0x40022020 -#define STM32_FLASH_WRP1AR 0x4002202c -#define STM32_FLASH_WRP1BR 0x40022030 -#define STM32_FLASH_WRP2AR 0x4002204c -#define STM32_FLASH_WRP2BR 0x40022050 +/* Flash registers offsets */ +#define STM32_FLASH_ACR 0x00 +#define STM32_FLASH_KEYR 0x08 +#define STM32_FLASH_OPTKEYR 0x0c +#define STM32_FLASH_SR 0x10 +#define STM32_FLASH_CR 0x14 +#define STM32_FLASH_OPTR 0x20 +#define STM32_FLASH_WRP1AR 0x2c +#define STM32_FLASH_WRP1BR 0x30 +#define STM32_FLASH_WRP2AR 0x4c +#define STM32_FLASH_WRP2BR 0x50 /* FLASH_CR register bits */ - -#define FLASH_PG (1 << 0) -#define FLASH_PER (1 << 1) -#define FLASH_MER1 (1 << 2) -#define FLASH_PAGE_SHIFT 3 -#define FLASH_CR_BKER (1 << 11) -#define FLASH_MER2 (1 << 15) -#define FLASH_STRT (1 << 16) -#define FLASH_OPTSTRT (1 << 17) -#define FLASH_EOPIE (1 << 24) -#define FLASH_ERRIE (1 << 25) +#define FLASH_PG (1 << 0) +#define FLASH_PER (1 << 1) +#define FLASH_MER1 (1 << 2) +#define FLASH_PAGE_SHIFT 3 +#define FLASH_CR_BKER (1 << 11) +#define FLASH_MER2 (1 << 15) +#define FLASH_STRT (1 << 16) +#define FLASH_OPTSTRT (1 << 17) +#define FLASH_EOPIE (1 << 24) +#define FLASH_ERRIE (1 << 25) #define FLASH_OBLLAUNCH (1 << 27) -#define FLASH_OPTLOCK (1 << 30) -#define FLASH_LOCK (1 << 31) +#define FLASH_OPTLOCK (1 << 30) +#define FLASH_LOCK (1 << 31) /* FLASH_SR register bits */ - #define FLASH_BSY (1 << 16) /* Fast programming not used => related errors not used*/ #define FLASH_PGSERR (1 << 7) /* Programming sequence error */ @@ -99,16 +101,9 @@ #define FLASH_PROGERR (1 << 3) /* Programming error */ #define FLASH_OPERR (1 << 1) /* Operation error */ #define FLASH_EOP (1 << 0) /* End of operation */ - #define FLASH_ERROR (FLASH_PGSERR | FLASH_PGSERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR) -/* STM32_FLASH_OBR bit definitions (reading) */ - -#define OPT_DBANK_LE_1M (1 << 21) /* dual bank for devices up to 1M flash */ -#define OPT_DBANK_GE_2M (1 << 22) /* dual bank for devices with 2M flash */ - /* register unlock keys */ - #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -123,15 +118,107 @@ /* other registers */ #define DBGMCU_IDCODE 0xE0042000 -#define FLASH_SIZE_REG 0x1FFF75E0 + + +struct stm32l4_rev { + const uint16_t rev; + const char *str; +}; + +struct stm32l4_part_info { + uint16_t id; + const char *device_str; + const struct stm32l4_rev *revs; + const size_t num_revs; + const uint16_t max_flash_size_kb; + const bool has_dual_bank; + const uint32_t flash_regs_base; + const uint32_t fsize_addr; +}; struct stm32l4_flash_bank { - uint16_t bank2_start; int probed; + uint32_t idcode; + int bank1_sectors; + bool dual_bank_mode; + int hole_sectors; + const struct stm32l4_part_info *part_info; }; -/* flash bank stm32l4x <base> <size> 0 0 <target#> - */ +static const struct stm32l4_rev stm32_415_revs[] = { + { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } +}; + +static const struct stm32l4_rev stm32_435_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, +}; + +static const struct stm32l4_rev stm32_461_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, +}; + +static const struct stm32l4_rev stm32_462_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, +}; + +static const struct stm32l4_rev stm32_470_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" }, +}; + +static const struct stm32l4_part_info stm32l4_parts[] = { + { + .id = 0x415, + .revs = stm32_415_revs, + .num_revs = ARRAY_SIZE(stm32_415_revs), + .device_str = "STM32L47/L48xx", + .max_flash_size_kb = 1024, + .has_dual_bank = true, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, + { + .id = 0x435, + .revs = stm32_435_revs, + .num_revs = ARRAY_SIZE(stm32_435_revs), + .device_str = "STM32L43/L44xx", + .max_flash_size_kb = 256, + .has_dual_bank = false, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, + { + .id = 0x461, + .revs = stm32_461_revs, + .num_revs = ARRAY_SIZE(stm32_461_revs), + .device_str = "STM32L49/L4Axx", + .max_flash_size_kb = 1024, + .has_dual_bank = true, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, + { + .id = 0x462, + .revs = stm32_462_revs, + .num_revs = ARRAY_SIZE(stm32_462_revs), + .device_str = "STM32L45/L46xx", + .max_flash_size_kb = 512, + .has_dual_bank = false, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, + { + .id = 0x470, + .revs = stm32_470_revs, + .num_revs = ARRAY_SIZE(stm32_470_revs), + .device_str = "STM32L4R/L4Sxx", + .max_flash_size_kb = 2048, + .has_dual_bank = true, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + }, +}; + +/* flash bank stm32l4x <base> <size> 0 0 <target#> */ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command) { struct stm32l4_flash_bank *stm32l4_info; @@ -149,27 +236,30 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command) return ERROR_OK; } -static inline int stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg) +static inline uint32_t stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset) { - return reg; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + return stm32l4_info->part_info->flash_regs_base + reg_offset; } -static inline int stm32l4_get_flash_status(struct flash_bank *bank, uint32_t *status) +static inline int stm32l4_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value) { - struct target *target = bank->target; - return target_read_u32( - target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), status); + return target_read_u32(bank->target, stm32l4_get_flash_reg(bank, reg_offset), value); +} + +static inline int stm32l4_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value) +{ + return target_write_u32(bank->target, stm32l4_get_flash_reg(bank, reg_offset), value); } static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) { - struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;;) { - retval = stm32l4_get_flash_status(bank, &status); + retval = stm32l4_read_flash_reg(bank, STM32_FLASH_SR, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); @@ -195,20 +285,20 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) /* If this operation fails, we ignore it and report the original * retval */ - target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), - status & FLASH_ERROR); + stm32l4_write_flash_reg(bank, STM32_FLASH_SR, status & FLASH_ERROR); } + return retval; } -static int stm32l4_unlock_reg(struct target *target) +static int stm32l4_unlock_reg(struct flash_bank *bank) { uint32_t ctrl; /* first check if not already unlocked * otherwise writing on STM32_FLASH_KEYR will fail */ - int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); + int retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; @@ -216,15 +306,15 @@ static int stm32l4_unlock_reg(struct target *target) return ERROR_OK; /* unlock flash registers */ - retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; - retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); + retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; @@ -236,11 +326,11 @@ static int stm32l4_unlock_reg(struct target *target) return ERROR_OK; } -static int stm32l4_unlock_option_reg(struct target *target) +static int stm32l4_unlock_option_reg(struct flash_bank *bank) { uint32_t ctrl; - int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); + int retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; @@ -248,15 +338,15 @@ static int stm32l4_unlock_option_reg(struct target *target) return ERROR_OK; /* unlock option registers */ - retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_OPTKEYR, OPTKEY1); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_OPTKEYR, OPTKEY2); if (retval != ERROR_OK) return retval; - retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); + retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; @@ -268,36 +358,29 @@ static int stm32l4_unlock_option_reg(struct target *target) return ERROR_OK; } -static int stm32l4_read_option(struct flash_bank *bank, uint32_t address, uint32_t* value) +static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset, uint32_t value, uint32_t mask) { - struct target *target = bank->target; - return target_read_u32(target, address, value); -} - -static int stm32l4_write_option(struct flash_bank *bank, uint32_t address, uint32_t value, uint32_t mask) -{ - struct target *target = bank->target; uint32_t optiondata; - int retval = target_read_u32(target, address, &optiondata); + int retval = stm32l4_read_flash_reg(bank, reg_offset, &optiondata); if (retval != ERROR_OK) return retval; - retval = stm32l4_unlock_reg(target); + retval = stm32l4_unlock_reg(bank); if (retval != ERROR_OK) return retval; - retval = stm32l4_unlock_option_reg(target); + retval = stm32l4_unlock_option_reg(bank); if (retval != ERROR_OK) return retval; optiondata = (optiondata & ~mask) | (value & mask); - retval = target_write_u32(target, address, optiondata); + retval = stm32l4_write_flash_reg(bank, reg_offset, optiondata); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_OPTSTRT); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_OPTSTRT); if (retval != ERROR_OK) return retval; @@ -311,11 +394,12 @@ static int stm32l4_write_option(struct flash_bank *bank, uint32_t address, uint3 static int stm32l4_protect_check(struct flash_bank *bank) { struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + uint32_t wrp1ar, wrp1br, wrp2ar, wrp2br; - stm32l4_read_option(bank, STM32_FLASH_WRP1AR, &wrp1ar); - stm32l4_read_option(bank, STM32_FLASH_WRP1BR, &wrp1br); - stm32l4_read_option(bank, STM32_FLASH_WRP2AR, &wrp2ar); - stm32l4_read_option(bank, STM32_FLASH_WRP2BR, &wrp2br); + stm32l4_read_flash_reg(bank, STM32_FLASH_WRP1AR, &wrp1ar); + stm32l4_read_flash_reg(bank, STM32_FLASH_WRP1BR, &wrp1br); + stm32l4_read_flash_reg(bank, STM32_FLASH_WRP2AR, &wrp2ar); + stm32l4_read_flash_reg(bank, STM32_FLASH_WRP2BR, &wrp2br); const uint8_t wrp1a_start = wrp1ar & 0xFF; const uint8_t wrp1a_end = (wrp1ar >> 16) & 0xFF; @@ -327,7 +411,7 @@ static int stm32l4_protect_check(struct flash_bank *bank) const uint8_t wrp2b_end = (wrp2br >> 16) & 0xFF; for (int i = 0; i < bank->num_sectors; i++) { - if (i < stm32l4_info->bank2_start) { + if (i < stm32l4_info->bank1_sectors) { if (((i >= wrp1a_start) && (i <= wrp1a_end)) || ((i >= wrp1b_start) && @@ -337,7 +421,7 @@ static int stm32l4_protect_check(struct flash_bank *bank) bank->sectors[i].is_protected = 0; } else { uint8_t snb; - snb = i - stm32l4_info->bank2_start; + snb = i - stm32l4_info->bank1_sectors; if (((snb >= wrp2a_start) && (snb <= wrp2a_end)) || ((snb >= wrp2b_start) && @@ -352,8 +436,9 @@ static int stm32l4_protect_check(struct flash_bank *bank) static int stm32l4_erase(struct flash_bank *bank, int first, int last) { - struct target *target = bank->target; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; int i; + int retval; assert(first < bank->num_sectors); assert(last < bank->num_sectors); @@ -363,8 +448,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last) return ERROR_TARGET_NOT_HALTED; } - int retval; - retval = stm32l4_unlock_reg(target); + retval = stm32l4_unlock_reg(bank); if (retval != ERROR_OK) return retval; @@ -378,20 +462,18 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last) 3. Set the STRT bit in the FLASH_CR register 4. Wait for the BSY bit to be cleared */ - struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; for (i = first; i <= last; i++) { uint32_t erase_flags; erase_flags = FLASH_PER | FLASH_STRT; - if (i >= stm32l4_info->bank2_start) { + if (i >= stm32l4_info->bank1_sectors) { uint8_t snb; - snb = i - stm32l4_info->bank2_start; + snb = i - stm32l4_info->bank1_sectors; erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER; } else erase_flags |= i << FLASH_PAGE_SHIFT; - retval = target_write_u32(target, - stm32l4_get_flash_reg(bank, STM32_FLASH_CR), erase_flags); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, erase_flags); if (retval != ERROR_OK) return retval; @@ -402,8 +484,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last) bank->sectors[i].is_erased = 1; } - retval = target_write_u32( - target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; @@ -423,9 +504,9 @@ static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last int ret = ERROR_OK; /* Bank 2 */ uint32_t reg_value = 0xFF; /* Default to bank un-protected */ - if (last >= stm32l4_info->bank2_start) { + if (last >= stm32l4_info->bank1_sectors) { if (set == 1) { - uint8_t begin = first > stm32l4_info->bank2_start ? first : 0x00; + uint8_t begin = first > stm32l4_info->bank1_sectors ? first : 0x00; reg_value = ((last & 0xFF) << 16) | begin; } @@ -433,9 +514,9 @@ static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last } /* Bank 1 */ reg_value = 0xFF; /* Default to bank un-protected */ - if (first < stm32l4_info->bank2_start) { + if (first < stm32l4_info->bank1_sectors) { if (set == 1) { - uint8_t end = last >= stm32l4_info->bank2_start ? 0xFF : last; + uint8_t end = last >= stm32l4_info->bank1_sectors ? 0xFF : last; reg_value = (end << 16) | (first & 0xFF); } @@ -450,6 +531,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; @@ -503,7 +585,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, count / 4); - buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE); + buf_set_u32(reg_params[4].value, 0, 32, stm32l4_info->part_info->flash_regs_base); retval = target_run_flash_async_algorithm(target, buffer, count, 2, 0, NULL, @@ -523,7 +605,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, if (error != 0) { LOG_ERROR("flash write failed = %08" PRIx32, error); /* Clear but report errors */ - target_write_u32(target, STM32_FLASH_SR, error); + stm32l4_write_flash_reg(bank, STM32_FLASH_SR, error); retval = ERROR_FAIL; } } @@ -543,7 +625,6 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - struct target *target = bank->target; int retval; if (bank->target->state != TARGET_HALTED) { @@ -570,7 +651,7 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, */ } - retval = stm32l4_unlock_reg(target); + retval = stm32l4_unlock_reg(bank); if (retval != ERROR_OK) return retval; @@ -579,60 +660,69 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) { LOG_WARNING("block write failed"); return retval; - } + } LOG_WARNING("block write succeeded"); - return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + return stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); +} + +static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) +{ + int retval = target_read_u32(bank->target, DBGMCU_IDCODE, id); + if (retval != ERROR_OK) + return retval; + + return retval; } static int stm32l4_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + const struct stm32l4_part_info *part_info; int i; uint16_t flash_size_in_kb = 0xffff; - uint16_t max_flash_size_in_kb; uint32_t device_id; uint32_t options; - uint32_t base_address = 0x08000000; stm32l4_info->probed = 0; /* read stm32 device id register */ - int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id); + int retval = stm32l4_read_idcode(bank, &stm32l4_info->idcode); if (retval != ERROR_OK) return retval; - LOG_INFO("device id = 0x%08" PRIx32 "", device_id); - /* set max flash size depending on family */ - switch (device_id & 0xfff) { - case 0x470: - max_flash_size_in_kb = 2048; - break; - case 0x461: - case 0x415: - max_flash_size_in_kb = 1024; - break; - case 0x462: - max_flash_size_in_kb = 512; - break; - case 0x435: - max_flash_size_in_kb = 256; - break; - default: + device_id = stm32l4_info->idcode & 0xFFF; + + for (unsigned int n = 0; n < ARRAY_SIZE(stm32l4_parts); n++) { + if (device_id == stm32l4_parts[n].id) + stm32l4_info->part_info = &stm32l4_parts[n]; + } + + if (!stm32l4_info->part_info) { LOG_WARNING("Cannot identify target as an STM32L4 family device."); return ERROR_FAIL; } + part_info = stm32l4_info->part_info; + + char device_info[1024]; + retval = bank->driver->info(bank, device_info, sizeof(device_info)); + if (retval != ERROR_OK) + return retval; + + LOG_INFO("device idcode = 0x%08" PRIx32 " (%s)", stm32l4_info->idcode, device_info); + /* get flash size from target. */ - retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb); + retval = target_read_u16(target, part_info->fsize_addr, &flash_size_in_kb); /* failed reading flash size or flash size invalid (early silicon), * default to max target family */ - if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { + if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0 + || flash_size_in_kb > part_info->max_flash_size_kb) { LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash", - max_flash_size_in_kb); - flash_size_in_kb = max_flash_size_in_kb; + part_info->max_flash_size_kb); + flash_size_in_kb = part_info->max_flash_size_kb; } LOG_INFO("flash size = %dkbytes", flash_size_in_kb); @@ -640,91 +730,106 @@ static int stm32l4_probe(struct flash_bank *bank) /* did we assign a flash size? */ assert((flash_size_in_kb != 0xffff) && flash_size_in_kb); - /* get options for DUAL BANK. */ - retval = target_read_u32(target, STM32_FLASH_OPTR, &options); - + /* read flash option register */ + retval = stm32l4_read_flash_reg(bank, STM32_FLASH_OPTR, &options); if (retval != ERROR_OK) return retval; + stm32l4_info->bank1_sectors = 0; + stm32l4_info->hole_sectors = 0; + int num_pages = 0; int page_size = 0; - switch (device_id & 0xfff) { - case 0x470: - /* L4R/S have 1M or 2M FLASH and dual/single bank mode. - * Page size is 4K or 8K.*/ - if (flash_size_in_kb == 2048) { - stm32l4_info->bank2_start = 256; - if (options & OPT_DBANK_GE_2M) { - page_size = 4096; - num_pages = 512; - } else { - page_size = 8192; - num_pages = 256; - } - break; - } - if (flash_size_in_kb == 1024) { - stm32l4_info->bank2_start = 128; - if (options & OPT_DBANK_LE_1M) { - page_size = 4096; - num_pages = 256; - } else { - page_size = 8192; - num_pages = 128; - } - break; - } - /* Invalid FLASH size for this device. */ - LOG_WARNING("Invalid flash size for STM32L4+ family device."); - return ERROR_FAIL; - case 0x461: - case 0x415: - /* These are dual-bank devices, we need to check the OPT_DBANK_LE_1M bit here */ - page_size = 2048; - num_pages = flash_size_in_kb / 2; - /* check that calculation result makes sense */ - assert(num_pages > 0); - if ((flash_size_in_kb == 1024) || !(options & OPT_DBANK_LE_1M)) - stm32l4_info->bank2_start = 256; - else - stm32l4_info->bank2_start = num_pages / 2; - break; - case 0x462: - case 0x435: - default: - /* These are single-bank devices */ - page_size = 2048; - num_pages = flash_size_in_kb / 2; - /* check that calculation result makes sense */ - assert(num_pages > 0); - stm32l4_info->bank2_start = UINT16_MAX; - break; + stm32l4_info->dual_bank_mode = false; + + switch (device_id) { + case 0x415: + case 0x461: + /* if flash size is max (1M) the device is always dual bank + * 0x415: has variants with 512K + * 0x461: has variants with 512 and 256 + * for these variants: + * if DUAL_BANK = 0 -> single bank + * else -> dual bank without gap + * note: the page size is invariant + */ + page_size = 2048; + num_pages = flash_size_in_kb / 2; + stm32l4_info->bank1_sectors = num_pages; + + /* check DUAL_BANK bit[21] if the flash is less than 1M */ + if (flash_size_in_kb == 1024 || (options & BIT(21))) { + stm32l4_info->dual_bank_mode = true; + stm32l4_info->bank1_sectors = num_pages / 2; + } + break; + case 0x435: + case 0x462: + /* single bank flash */ + page_size = 2048; + num_pages = flash_size_in_kb / 2; + stm32l4_info->bank1_sectors = num_pages; + break; + case 0x470: + /* STM32L4R/S can be single/dual bank: + * if size = 2M check DBANK bit(22) + * if size = 1M check DB1M bit(21) + * in single bank configuration the page size is 8K + * else (dual bank) the page size is 4K without gap between banks + */ + page_size = 8192; + num_pages = flash_size_in_kb / 8; + stm32l4_info->bank1_sectors = num_pages; + if ((flash_size_in_kb == 2048 && (options & BIT(22))) || + (flash_size_in_kb == 1024 && (options & BIT(21)))) { + stm32l4_info->dual_bank_mode = true; + page_size = 4096; + num_pages = flash_size_in_kb / 4; + stm32l4_info->bank1_sectors = num_pages / 2; + } + break; + default: + LOG_ERROR("unsupported device"); + return ERROR_FAIL; + } + + LOG_INFO("flash mode : %s-bank", stm32l4_info->dual_bank_mode ? "dual" : "single"); + + const int gap_size = stm32l4_info->hole_sectors * page_size; + + if (stm32l4_info->dual_bank_mode & gap_size) { + LOG_INFO("gap detected starting from %0x08" PRIx32 " to %0x08" PRIx32, + 0x8000000 + stm32l4_info->bank1_sectors * page_size, + 0x8000000 + stm32l4_info->bank1_sectors * page_size + gap_size); } - /* Release sector table if allocated. */ if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } - /* Set bank configuration and construct sector table. */ - bank->base = base_address; - bank->size = num_pages * page_size; + bank->size = flash_size_in_kb * 1024 + gap_size; + bank->base = 0x08000000; bank->num_sectors = num_pages; - bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); - if (!bank->sectors) - return ERROR_FAIL; /* Checkme: What better error to use?*/ + bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + if (bank->sectors == NULL) { + LOG_ERROR("failed to allocate bank sectors"); + return ERROR_FAIL; + } - for (i = 0; i < num_pages; i++) { + for (i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = i * page_size; + /* in dual bank configuration, if there is a gap between banks + * we fix up the sector offset to consider this gap */ + if (i >= stm32l4_info->bank1_sectors && stm32l4_info->hole_sectors) + bank->sectors[i].offset += gap_size; bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } stm32l4_info->probed = 1; - return ERROR_OK; } @@ -733,87 +838,70 @@ static int stm32l4_auto_probe(struct flash_bank *bank) struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; if (stm32l4_info->probed) return ERROR_OK; + return stm32l4_probe(bank); } static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) { - struct target *target = bank->target; - uint32_t dbgmcu_idcode; - - /* read stm32 device id register */ - int retval = target_read_u32(target, DBGMCU_IDCODE, &dbgmcu_idcode); - if (retval != ERROR_OK) - return retval; - - uint16_t device_id = dbgmcu_idcode & 0xfff; - uint8_t rev_id = dbgmcu_idcode >> 28; - uint8_t rev_minor = 0; - int i; - - for (i = 16; i < 28; i++) { - if (dbgmcu_idcode & (1 << i)) - rev_minor++; - else - break; - } - - const char *device_str; - - switch (device_id) { - case 0x470: - device_str = "STM32L4R/4Sxx"; - break; - - case 0x461: - device_str = "STM32L496/4A6"; - break; - - case 0x415: - device_str = "STM32L475/476/486"; - break; - - case 0x462: - device_str = "STM32L45x/46x"; - break; - - case 0x435: - device_str = "STM32L43x/44x"; - break; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + const struct stm32l4_part_info *part_info = stm32l4_info->part_info; + + if (part_info) { + const char *rev_str = NULL; + uint16_t rev_id = stm32l4_info->idcode >> 16; + for (unsigned int i = 0; i < part_info->num_revs; i++) { + if (rev_id == part_info->revs[i].rev) { + rev_str = part_info->revs[i].str; + + if (rev_str != NULL) { + snprintf(buf, buf_size, "%s - Rev: %s", + part_info->device_str, rev_str); + return ERROR_OK; + } + } + } - default: - snprintf(buf, buf_size, "Cannot identify target as a STM32L4\n"); + snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", + part_info->device_str, rev_id); + return ERROR_OK; + } else { + snprintf(buf, buf_size, "Cannot identify target as a STM32L4x device"); return ERROR_FAIL; } - snprintf(buf, buf_size, "%s - Rev: %1d.%02d", - device_str, rev_id, rev_minor); - return ERROR_OK; } -static int stm32l4_mass_erase(struct flash_bank *bank, uint32_t action) +static int stm32l4_mass_erase(struct flash_bank *bank) { int retval; struct target *target = bank->target; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + + uint32_t action = FLASH_MER1; + + if (stm32l4_info->part_info->has_dual_bank) + action |= FLASH_MER2; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - retval = stm32l4_unlock_reg(target); + retval = stm32l4_unlock_reg(bank); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ - retval = target_write_u32( - target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), action); + retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT / 10); if (retval != ERROR_OK) return retval; - retval = target_write_u32( - target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), - action | FLASH_STRT); + + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action); + if (retval != ERROR_OK) + return retval; + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action | FLASH_STRT); if (retval != ERROR_OK) return retval; @@ -821,8 +909,7 @@ static int stm32l4_mass_erase(struct flash_bank *bank, uint32_t action) if (retval != ERROR_OK) return retval; - retval = target_write_u32( - target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; @@ -832,7 +919,6 @@ static int stm32l4_mass_erase(struct flash_bank *bank, uint32_t action) COMMAND_HANDLER(stm32l4_handle_mass_erase_command) { int i; - uint32_t action; if (CMD_ARGC < 1) { command_print(CMD, "stm32l4x mass_erase <STM32L4 bank>"); @@ -844,8 +930,7 @@ COMMAND_HANDLER(stm32l4_handle_mass_erase_command) if (ERROR_OK != retval) return retval; - action = FLASH_MER1 | FLASH_MER2; - retval = stm32l4_mass_erase(bank, action); + retval = stm32l4_mass_erase(bank); if (retval == ERROR_OK) { /* set all sectors as erased */ for (i = 0; i < bank->num_sectors; i++) @@ -871,12 +956,13 @@ COMMAND_HANDLER(stm32l4_handle_option_read_command) if (ERROR_OK != retval) return retval; - uint32_t reg_addr = STM32_FLASH_BASE; + uint32_t reg_offset, reg_addr; uint32_t value = 0; - reg_addr += strtoul(CMD_ARGV[1], NULL, 16); + reg_offset = strtoul(CMD_ARGV[1], NULL, 16); + reg_addr = stm32l4_get_flash_reg(bank, reg_offset); - retval = stm32l4_read_option(bank, reg_addr, &value); + retval = stm32l4_read_flash_reg(bank, reg_offset, &value); if (ERROR_OK != retval) return retval; @@ -897,11 +983,11 @@ COMMAND_HANDLER(stm32l4_handle_option_write_command) if (ERROR_OK != retval) return retval; - uint32_t reg_addr = STM32_FLASH_BASE; + uint32_t reg_offset; uint32_t value = 0; uint32_t mask = 0xFFFFFFFF; - reg_addr += strtoul(CMD_ARGV[1], NULL, 16); + reg_offset = strtoul(CMD_ARGV[1], NULL, 16); value = strtoul(CMD_ARGV[2], NULL, 16); if (CMD_ARGC > 3) mask = strtoul(CMD_ARGV[3], NULL, 16); @@ -910,7 +996,7 @@ COMMAND_HANDLER(stm32l4_handle_option_write_command) "INFO: a reset or power cycle is required " "for the new settings to take effect.", bank->driver->name); - retval = stm32l4_write_option(bank, reg_addr, value, mask); + retval = stm32l4_write_option(bank, reg_offset, value, mask); return retval; } @@ -924,18 +1010,16 @@ COMMAND_HANDLER(stm32l4_handle_option_load_command) if (ERROR_OK != retval) return retval; - struct target *target = bank->target; - - retval = stm32l4_unlock_reg(target); + retval = stm32l4_unlock_reg(bank); if (ERROR_OK != retval) return retval; - retval = stm32l4_unlock_option_reg(target); + retval = stm32l4_unlock_option_reg(bank); if (ERROR_OK != retval) return retval; /* Write the OBLLAUNCH bit in CR -> Cause device "POR" and option bytes reload */ - retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_OBLLAUNCH); + retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_OBLLAUNCH); command_print(CMD, "stm32l4x option load (POR) completed."); return retval; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 590 +++++++++++++++++++++++++++-------------------- 1 file changed, 337 insertions(+), 253 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-14 11:42:12
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via ed8fa09cfff93dc29903e33e92d36988a30a9529 (commit) from d2308da6e9adc21acd8428afec770670e57bea25 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ed8fa09cfff93dc29903e33e92d36988a30a9529 Author: Christopher Head <ch...@za...> Date: Thu Jun 6 11:40:12 2019 -0700 target/target: parse value as proper type The `value` variable is passed into `target_fill_mem` as its second-to-last parameter. That parameter is of type `uint64_t`. It is appropriate to parse the value as that type, since otherwise a target with a 32-bit address space but 64-bit data write capabilities would not be able to exercise those capabilities. Change-Id: Ib336d47d42c27cd2b5ba1206b04e8f740f167dba Signed-off-by: Christopher Head <ch...@za...> Reviewed-on: http://openocd.zylin.com/5219 Reviewed-by: Tomas Vanek <va...@fb...> Tested-by: jenkins diff --git a/src/target/target.c b/src/target/target.c index 2bfbd5700..1ec2ee2ed 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3338,8 +3338,8 @@ COMMAND_HANDLER(handle_mw_command) target_addr_t address; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - target_addr_t value; - COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value); + uint64_t value; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], value); unsigned count = 1; if (CMD_ARGC == 3) ----------------------------------------------------------------------- Summary of changes: src/target/target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-01-14 11:41:40
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via d2308da6e9adc21acd8428afec770670e57bea25 (commit) via 944d3e6771bd34e6495276a154929c2c0baf5e0a (commit) via a61ec3c1d73dc0c9915662f7b9383b6f786a5fea (commit) from c6b6fdeb2c4c644addf7b2e1d8c5f0b800d359b7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d2308da6e9adc21acd8428afec770670e57bea25 Author: Antonio Borneo <bor...@gm...> Date: Thu Feb 28 10:28:26 2019 +0100 stlink: fix handling of DPv1 and DPv2 banked registers Arm DPv1 and DPv2 support banked registers by setting the bank in field DPBANKSEL of register DP_SELECT. Old ST-Link firmware don't support banked registers and setting a bank other than bank zero on DPv1 or DPv2 cause issues in the firmware because it cannot set back bank zero to read CTRL/STAT. New ST-Link firmware mask away DPBANKSEL bits while writing in DP_SELECT but support banked register using the same packed method used by OpenOCD: #define BANK_REG(bank, reg) (((bank) << 4) | (reg)) Add a new macro STLINK_F_HAS_DPBANKSEL for firmware that support arm DPv1 and DPv2, plus trigger an error if banked registers are requested on old firmware. Prevent changing DPBANKSEL on old firmware. Log a debug message when changing DPBANKSEL will be ignored. Change-Id: Iaa592517831d63f8da2290db54f6b32504e3081b Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/4978 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index e121eb42b..5c904d4ff 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -316,6 +316,7 @@ enum stlink_mode { #define STLINK_F_HAS_DAP_REG BIT(5) #define STLINK_F_QUIRK_JTAG_DP_READ BIT(6) #define STLINK_F_HAS_AP_INIT BIT(7) +#define STLINK_F_HAS_DPBANKSEL BIT(8) /* aliases */ #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE @@ -1021,6 +1022,10 @@ static int stlink_usb_version(void *handle) if (h->version.jtag >= 28) flags |= STLINK_F_HAS_AP_INIT; + /* Banked regs (DPv1 & DPv2) support from V2J32 */ + if (h->version.jtag >= 32) + flags |= STLINK_F_HAS_DPBANKSEL; + break; case 3: /* all STLINK-V3 use api-v3 */ @@ -1044,6 +1049,10 @@ static int stlink_usb_version(void *handle) /* API required to init AP before any AP access */ flags |= STLINK_F_HAS_AP_INIT; + /* Banked regs (DPv1 & DPv2) support from V3J2 */ + if (h->version.jtag >= 2) + flags |= STLINK_F_HAS_DPBANKSEL; + break; default: break; @@ -3259,6 +3268,12 @@ static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t dummy; int retval; + if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DPBANKSEL)) + if (reg & 0x000000F0) { + LOG_ERROR("Banked DP registers not supported in current STLink FW"); + return ERROR_COMMAND_NOTFOUND; + } + retval = stlink_dap_check_reconnect(dap); if (retval != ERROR_OK) return retval; @@ -3286,6 +3301,18 @@ static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned reg, { int retval; + if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DPBANKSEL)) + if (reg & 0x000000F0) { + LOG_ERROR("Banked DP registers not supported in current STLink FW"); + return ERROR_COMMAND_NOTFOUND; + } + + if (reg == DP_SELECT && (data & DP_SELECT_DPBANK) != 0) { + /* ignored if STLINK_F_HAS_DPBANKSEL, not properly managed otherwise */ + LOG_DEBUG("Ignoring DPBANKSEL while write SELECT"); + data &= ~DP_SELECT_DPBANK; + } + retval = stlink_dap_check_reconnect(dap); if (retval != ERROR_OK) return retval; commit 944d3e6771bd34e6495276a154929c2c0baf5e0a Author: Antonio Borneo <bor...@gm...> Date: Mon Jan 28 18:53:53 2019 +0100 stlink: add DAP direct driver STLINK-V3 and the new firmware V2J24 for ST-LINK/V2 provide API to directly access the DAP registers. This mode permits to use the native target in cortex_m.c, with no need to override it with the target in hla_target.c. Other advantages wrt HLA are: support for Cortex-A cores, support for SoC multi-core and/or multi AP, support for OpenOCD commands "dap" thus including control of CSW. This obsoletes the existing HLA driver for ST-Link, that should anyway be kept for those cases where it's not possible to update the ST-Link firmware. This commit introduces the minimal implementation for direct DAP access. The implementation is much slower than the HLA because every memory transfer requires several USB packets. Further commits will close the performance gap. The whole ST-Link driver is compiled under BUILD_HLADAPTER, to remove the need to split the driver between the two modes. This has to be reworked, but it's quite invasive! A new interface file stlink-dap.cfg is added and should be used in place of stlink.cfg to enable the DAP mode. Documentation is updated and reports limitation on the maximum AP number that can be accessed by ST-Link for some firmware already tested. Change-Id: I932ffe16bc81d00b1fe489e2944fda13470cce9b Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/4904 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 5da0f806b..b79325276 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3096,6 +3096,29 @@ passed as is to the underlying adapter layout handler. @end deffn @end deffn +@anchor{st_link_dap_interface} +@deffn {Interface Driver} {st-link} +This is a driver that supports STMicroelectronics adapters ST-LINK/V2 +(from firmware V2J24) and STLINK-V3, thanks to a new API that provides +directly access the arm ADIv5 DAP. + +The new API provide access to multiple AP on the same DAP, but the +maximum number of the AP port is limited by the specific firmware version +(e.g. firmware V2J29 has 3 as maximum AP number, while V2J32 has 8). +An error is returned for any AP number above the maximum allowed value. + +@emph{Note:} Either these same adapters and their older versions are +also supported by @ref{hla_interface, the hla interface driver}. + +@deffn {Config Command} {st-link serial} serial +Specifies the serial number of the adapter. +@end deffn + +@deffn {Config Command} {st-link vid_pid} [vid pid]+ +Pairs of vendor IDs and product IDs of the device. +@end deffn +@end deffn + @deffn {Interface Driver} {opendous} opendous-jtag is a freely programmable USB adapter. @end deffn @@ -3204,9 +3227,10 @@ JTAG supports both debugging and boundary scan testing. Flash programming support is built on top of debug support. JTAG transport is selected with the command @command{transport select -jtag}. Unless your adapter uses @ref{hla_interface,the hla interface -driver}, in which case the command is @command{transport select -hla_jtag}. +jtag}. Unless your adapter uses either @ref{hla_interface,the hla interface +driver} (in which case the command is @command{transport select hla_jtag}) +or @ref{st_link_dap_interface,the st-link interface driver} (in which case +the command is @command{transport select dapdirect_jtag}). @subsection SWD Transport @cindex SWD @@ -3219,9 +3243,10 @@ Flash programming support is built on top of debug support. (Some processors support both JTAG and SWD.) SWD transport is selected with the command @command{transport select -swd}. Unless your adapter uses @ref{hla_interface,the hla interface -driver}, in which case the command is @command{transport select -hla_swd}. +swd}. Unless your adapter uses either @ref{hla_interface,the hla interface +driver} (in which case the command is @command{transport select hla_swd}) +or @ref{st_link_dap_interface,the st-link interface driver} (in which case +the command is @command{transport select dapdirect_swd}). @deffn Command {swd newdap} ... Declares a single DAP which uses SWD transport. diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a16810413..e121eb42b 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -31,11 +31,13 @@ /* project specific includes */ #include <helper/binarybuffer.h> +#include <helper/bits.h> #include <jtag/interface.h> #include <jtag/hla/hla_layout.h> #include <jtag/hla/hla_transport.h> #include <jtag/hla/hla_interface.h> #include <target/target.h> +#include <transport/transport.h> #include <target/cortex_m.h> @@ -265,10 +267,14 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_GET_TRACE_NB 0x42 #define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43 #define STLINK_DEBUG_APIV2_JTAG_SET_FREQ 0x44 - +#define STLINK_DEBUG_APIV2_READ_DAP_REG 0x45 +#define STLINK_DEBUG_APIV2_WRITE_DAP_REG 0x46 #define STLINK_DEBUG_APIV2_READMEM_16BIT 0x47 #define STLINK_DEBUG_APIV2_WRITEMEM_16BIT 0x48 +#define STLINK_DEBUG_APIV2_INIT_AP 0x4B +#define STLINK_DEBUG_APIV2_CLOSE_AP_DBG 0x4C + #define STLINK_APIV3_SET_COM_FREQ 0x61 #define STLINK_APIV3_GET_COM_FREQ 0x62 @@ -278,6 +284,8 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 +#define STLINK_DEBUG_PORT_ACCESS 0xffff + #define STLINK_TRACE_SIZE 4096 #define STLINK_TRACE_MAX_HZ 2000000 @@ -300,11 +308,14 @@ enum stlink_mode { * Map the relevant features, quirks and workaround for specific firmware * version of stlink */ -#define STLINK_F_HAS_TRACE (1UL << 0) -#define STLINK_F_HAS_SWD_SET_FREQ (1UL << 1) -#define STLINK_F_HAS_JTAG_SET_FREQ (1UL << 2) -#define STLINK_F_HAS_MEM_16BIT (1UL << 3) -#define STLINK_F_HAS_GETLASTRWSTATUS2 (1UL << 4) +#define STLINK_F_HAS_TRACE BIT(0) +#define STLINK_F_HAS_SWD_SET_FREQ BIT(1) +#define STLINK_F_HAS_JTAG_SET_FREQ BIT(2) +#define STLINK_F_HAS_MEM_16BIT BIT(3) +#define STLINK_F_HAS_GETLASTRWSTATUS2 BIT(4) +#define STLINK_F_HAS_DAP_REG BIT(5) +#define STLINK_F_QUIRK_JTAG_DP_READ BIT(6) +#define STLINK_F_HAS_AP_INIT BIT(7) /* aliases */ #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE @@ -992,13 +1003,24 @@ static int stlink_usb_version(void *handle) flags |= STLINK_F_HAS_SWD_SET_FREQ; /* API to set JTAG frequency from J24 */ - if (h->version.jtag >= 24) + /* API to access DAP registers from J24 */ + if (h->version.jtag >= 24) { flags |= STLINK_F_HAS_JTAG_SET_FREQ; + flags |= STLINK_F_HAS_DAP_REG; + } + + /* Quirk for read DP in JTAG mode (V2 only) from J24, fixed in J32 */ + if (h->version.jtag >= 24 && h->version.jtag < 32) + flags |= STLINK_F_QUIRK_JTAG_DP_READ; /* API to read/write memory at 16 bit from J26 */ if (h->version.jtag >= 26) flags |= STLINK_F_HAS_MEM_16BIT; + /* API required to init AP before any AP access from J28 */ + if (h->version.jtag >= 28) + flags |= STLINK_F_HAS_AP_INIT; + break; case 3: /* all STLINK-V3 use api-v3 */ @@ -1013,9 +1035,15 @@ static int stlink_usb_version(void *handle) /* preferred API to get last R/W status */ flags |= STLINK_F_HAS_GETLASTRWSTATUS2; + /* API to access DAP registers */ + flags |= STLINK_F_HAS_DAP_REG; + /* API to read/write memory at 16 bit */ flags |= STLINK_F_HAS_MEM_16BIT; + /* API required to init AP before any AP access */ + flags |= STLINK_F_HAS_AP_INIT; + break; default: break; @@ -2930,6 +2958,89 @@ int stlink_config_trace(void *handle, bool enabled, return stlink_usb_trace_enable(h); } +/** */ +static int stlink_usb_init_access_port(void *handle, unsigned char ap_num) +{ + struct stlink_usb_handle_s *h = handle; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_AP_INIT)) + return ERROR_COMMAND_NOTFOUND; + + LOG_DEBUG_IO("init ap_num = %d", ap_num); + stlink_usb_init_buffer(handle, h->rx_ep, 16); + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_INIT_AP; + h->cmdbuf[h->cmdidx++] = ap_num; + + return stlink_usb_xfer_errcheck(handle, h->databuf, 2); +} + +/** */ +static int stlink_usb_close_access_port(void *handle, unsigned char ap_num) +{ + struct stlink_usb_handle_s *h = handle; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_AP_INIT)) + return ERROR_COMMAND_NOTFOUND; + + LOG_DEBUG_IO("close ap_num = %d", ap_num); + stlink_usb_init_buffer(handle, h->rx_ep, 16); + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_CLOSE_AP_DBG; + h->cmdbuf[h->cmdidx++] = ap_num; + + return stlink_usb_xfer_errcheck(handle, h->databuf, 2); +} + +/** */ +static int stlink_read_dap_register(void *handle, unsigned short dap_port, + unsigned short addr, uint32_t *val) +{ + struct stlink_usb_handle_s *h = handle; + int retval; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_DAP_REG)) + return ERROR_COMMAND_NOTFOUND; + + stlink_usb_init_buffer(handle, h->rx_ep, 16); + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READ_DAP_REG; + h_u16_to_le(&h->cmdbuf[2], dap_port); + h_u16_to_le(&h->cmdbuf[4], addr); + + retval = stlink_usb_xfer_errcheck(handle, h->databuf, 8); + *val = le_to_h_u32(h->databuf + 4); + LOG_DEBUG_IO("dap_port_read = %d, addr = 0x%x, value = 0x%x", dap_port, addr, *val); + return retval; +} + +/** */ +static int stlink_write_dap_register(void *handle, unsigned short dap_port, + unsigned short addr, uint32_t val) +{ + struct stlink_usb_handle_s *h = handle; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_DAP_REG)) + return ERROR_COMMAND_NOTFOUND; + + LOG_DEBUG_IO("dap_write port = %d, addr = 0x%x, value = 0x%x", dap_port, addr, val); + stlink_usb_init_buffer(handle, h->rx_ep, 16); + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITE_DAP_REG; + h_u16_to_le(&h->cmdbuf[2], dap_port); + h_u16_to_le(&h->cmdbuf[4], addr); + h_u32_to_le(&h->cmdbuf[6], val); + return stlink_usb_xfer_errcheck(handle, h->databuf, 2); +} + /** */ struct hl_layout_api_s stlink_usb_layout_api = { /** */ @@ -2971,3 +3082,531 @@ struct hl_layout_api_s stlink_usb_layout_api = { /** */ .poll_trace = stlink_usb_trace_read, }; + +/***************************************************************************** + * DAP direct interface + */ + +static struct stlink_usb_handle_s *stlink_dap_handle; +static struct hl_interface_param_s stlink_dap_param; +static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1); +static int stlink_dap_error = ERROR_OK; + +static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, + uint32_t *data); + +/** */ +static int stlink_dap_record_error(int error) +{ + if (stlink_dap_error == ERROR_OK) + stlink_dap_error = error; + return ERROR_OK; +} + +/** */ +static int stlink_dap_get_and_clear_error(void) +{ + int retval = stlink_dap_error; + stlink_dap_error = ERROR_OK; + return retval; +} + +/** */ +static int stlink_dap_open_ap(unsigned short apsel) +{ + int retval; + + /* nothing to do on old versions */ + if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT)) + return ERROR_OK; + + if (apsel > DP_APSEL_MAX) + return ERROR_FAIL; + + if (test_bit(apsel, opened_ap)) + return ERROR_OK; + + retval = stlink_usb_init_access_port(stlink_dap_handle, apsel); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("AP %d enabled", apsel); + set_bit(apsel, opened_ap); + return ERROR_OK; +} + +/** */ +static int stlink_dap_closeall_ap(void) +{ + int retval, apsel; + + /* nothing to do on old versions */ + if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT)) + return ERROR_OK; + + for (apsel = 0; apsel <= DP_APSEL_MAX; apsel++) { + if (!test_bit(apsel, opened_ap)) + continue; + retval = stlink_usb_close_access_port(stlink_dap_handle, apsel); + if (retval != ERROR_OK) + return retval; + clear_bit(apsel, opened_ap); + } + return ERROR_OK; +} + +/** */ +static int stlink_dap_reinit_interface(void) +{ + int retval; + enum stlink_mode mode; + + /* + * On JTAG only, it should be enough to call stlink_usb_reset(). But on + * some firmware version it does not work as expected, and there is no + * equivalent for SWD. + * At least for now, to reset the interface quit from JTAG/SWD mode then + * select the mode again. + */ + + mode = stlink_get_mode(stlink_dap_param.transport); + if (!stlink_dap_handle->reconnect_pending) { + stlink_dap_handle->reconnect_pending = true; + stlink_usb_mode_leave(stlink_dap_handle, mode); + } + + retval = stlink_usb_mode_enter(stlink_dap_handle, mode); + if (retval != ERROR_OK) + return retval; + + stlink_dap_handle->reconnect_pending = false; + /* on new FW, calling mode-leave closes all the opened AP; reopen them! */ + if (stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT) + for (int apsel = 0; apsel <= DP_APSEL_MAX; apsel++) + if (test_bit(apsel, opened_ap)) { + clear_bit(apsel, opened_ap); + stlink_dap_open_ap(apsel); + } + return ERROR_OK; +} + +/** */ +static int stlink_dap_op_connect(struct adiv5_dap *dap) +{ + uint32_t idcode; + int retval; + + LOG_INFO("stlink_dap_op_connect(%sconnect)", dap->do_reconnect ? "re" : ""); + + /* Check if we should reset srst already when connecting, but not if reconnecting. */ + if (!dap->do_reconnect) { + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) + adapter_assert_reset(); + else + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } + } + + dap->do_reconnect = false; + dap_invalidate_cache(dap); + + retval = dap_dp_init(dap); + if (retval != ERROR_OK) { + dap->do_reconnect = true; + return retval; + } + + retval = stlink_usb_idcode(stlink_dap_handle, &idcode); + if (retval == ERROR_OK) + LOG_INFO("%s %#8.8" PRIx32, + (stlink_dap_handle->transport == HL_TRANSPORT_JTAG) ? "JTAG IDCODE" : "SWD DPIDR", + idcode); + else + dap->do_reconnect = true; + + return retval; +} + +/** */ +static int stlink_dap_check_reconnect(struct adiv5_dap *dap) +{ + int retval; + + if (!dap->do_reconnect) + return ERROR_OK; + + retval = stlink_dap_reinit_interface(); + if (retval != ERROR_OK) + return retval; + + return stlink_dap_op_connect(dap); +} + +/** */ +static int stlink_dap_op_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + /* Ignore the request */ + return ERROR_OK; +} + +/** */ +static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, + uint32_t *data) +{ + uint32_t dummy; + int retval; + + retval = stlink_dap_check_reconnect(dap); + if (retval != ERROR_OK) + return retval; + + data = data ? : &dummy; + if (stlink_dap_handle->version.flags & STLINK_F_QUIRK_JTAG_DP_READ + && stlink_dap_handle->transport == HL_TRANSPORT_JTAG) { + /* Quirk required in JTAG. Read RDBUFF to get the data */ + retval = stlink_read_dap_register(stlink_dap_handle, + STLINK_DEBUG_PORT_ACCESS, reg, &dummy); + if (retval == ERROR_OK) + retval = stlink_read_dap_register(stlink_dap_handle, + STLINK_DEBUG_PORT_ACCESS, DP_RDBUFF, data); + } else { + retval = stlink_read_dap_register(stlink_dap_handle, + STLINK_DEBUG_PORT_ACCESS, reg, data); + } + + return stlink_dap_record_error(retval); +} + +/** */ +static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned reg, + uint32_t data) +{ + int retval; + + retval = stlink_dap_check_reconnect(dap); + if (retval != ERROR_OK) + return retval; + + /* ST-Link does not like that we set CORUNDETECT */ + if (reg == DP_CTRL_STAT) + data &= ~CORUNDETECT; + + retval = stlink_write_dap_register(stlink_dap_handle, + STLINK_DEBUG_PORT_ACCESS, reg, data); + return stlink_dap_record_error(retval); +} + +/** */ +static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned reg, + uint32_t *data) +{ + struct adiv5_dap *dap = ap->dap; + uint32_t dummy; + int retval; + + retval = stlink_dap_check_reconnect(dap); + if (retval != ERROR_OK) + return retval; + + if (reg != AP_REG_IDR) { + retval = stlink_dap_open_ap(ap->ap_num); + if (retval != ERROR_OK) + return retval; + } + data = data ? : &dummy; + retval = stlink_read_dap_register(stlink_dap_handle, ap->ap_num, reg, + data); + dap->stlink_flush_ap_write = false; + return stlink_dap_record_error(retval); +} + +/** */ +static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned reg, + uint32_t data) +{ + struct adiv5_dap *dap = ap->dap; + int retval; + + retval = stlink_dap_check_reconnect(dap); + if (retval != ERROR_OK) + return retval; + + retval = stlink_dap_open_ap(ap->ap_num); + if (retval != ERROR_OK) + return retval; + + retval = stlink_write_dap_register(stlink_dap_handle, ap->ap_num, reg, + data); + dap->stlink_flush_ap_write = true; + return stlink_dap_record_error(retval); +} + +/** */ +static int stlink_dap_op_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) +{ + LOG_WARNING("stlink_dap_op_queue_ap_abort()"); + return ERROR_OK; +} + +/** */ +static int stlink_dap_op_run(struct adiv5_dap *dap) +{ + uint32_t ctrlstat, pwrmask; + int retval, saved_retval; + + /* Here no LOG_DEBUG. This is called continuously! */ + + /* + * ST-Link returns immediately after a DAP write, without waiting for it + * to complete. + * Run a dummy read to DP_RDBUFF, as suggested in + * http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka16363.html + */ + if (dap->stlink_flush_ap_write) { + dap->stlink_flush_ap_write = false; + retval = stlink_dap_op_queue_dp_read(dap, DP_RDBUFF, NULL); + if (retval != ERROR_OK) { + dap->do_reconnect = true; + return retval; + } + } + + saved_retval = stlink_dap_get_and_clear_error(); + + retval = stlink_dap_op_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat); + if (retval != ERROR_OK) { + dap->do_reconnect = true; + return retval; + } + retval = stlink_dap_get_and_clear_error(); + if (retval != ERROR_OK) { + LOG_ERROR("Fail reading CTRL/STAT register. Force reconnect"); + dap->do_reconnect = true; + return retval; + } + + if (ctrlstat & SSTICKYERR) { + if (stlink_dap_param.transport == HL_TRANSPORT_JTAG) + retval = stlink_dap_op_queue_dp_write(dap, DP_CTRL_STAT, + ctrlstat & (dap->dp_ctrl_stat | SSTICKYERR)); + else + retval = stlink_dap_op_queue_dp_write(dap, DP_ABORT, STKERRCLR); + if (retval != ERROR_OK) { + dap->do_reconnect = true; + return retval; + } + retval = stlink_dap_get_and_clear_error(); + if (retval != ERROR_OK) { + dap->do_reconnect = true; + return retval; + } + } + + /* check for power lost */ + pwrmask = dap->dp_ctrl_stat & (CDBGPWRUPREQ | CSYSPWRUPREQ); + if ((ctrlstat & pwrmask) != pwrmask) + dap->do_reconnect = true; + + return saved_retval; +} + +/** */ +static void stlink_dap_op_quit(struct adiv5_dap *dap) +{ + int retval; + + retval = stlink_dap_closeall_ap(); + if (retval != ERROR_OK) + LOG_ERROR("Error closing APs"); +} + +/** */ +COMMAND_HANDLER(stlink_dap_serial_command) +{ + LOG_DEBUG("stlink_dap_serial_command"); + + if (CMD_ARGC != 1) { + LOG_ERROR("Expected exactly one argument for \"st-link serial <serial-number>\"."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (stlink_dap_param.serial) { + LOG_WARNING("Command \"st-link serial\" already used. Replacing previous value"); + free((void *)stlink_dap_param.serial); + } + + stlink_dap_param.serial = strdup(CMD_ARGV[0]); + return ERROR_OK; +} + +/** */ +COMMAND_HANDLER(stlink_dap_vid_pid) +{ + unsigned int i, max_usb_ids = HLA_MAX_USB_IDS; + + if (CMD_ARGC > max_usb_ids * 2) { + LOG_WARNING("ignoring extra IDs in vid_pid " + "(maximum is %d pairs)", max_usb_ids); + CMD_ARGC = max_usb_ids * 2; + } + if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { + LOG_WARNING("incomplete vid_pid configuration directive"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + for (i = 0; i < CMD_ARGC; i += 2) { + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], stlink_dap_param.vid[i / 2]); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], stlink_dap_param.pid[i / 2]); + } + + /* null termination */ + stlink_dap_param.vid[i / 2] = stlink_dap_param.pid[i / 2] = 0; + + return ERROR_OK; +} + +/** */ +static const struct command_registration stlink_dap_subcommand_handlers[] = { + { + .name = "serial", + .handler = stlink_dap_serial_command, + .mode = COMMAND_CONFIG, + .help = "set the serial number of the adapter", + .usage = "<serial_number>", + }, + { + .name = "vid_pid", + .handler = stlink_dap_vid_pid, + .mode = COMMAND_CONFIG, + .help = "USB VID and PID of the adapter", + .usage = "(vid pid)+", + }, + COMMAND_REGISTRATION_DONE +}; + +/** */ +static const struct command_registration stlink_dap_command_handlers[] = { + { + .name = "st-link", + .mode = COMMAND_ANY, + .help = "perform st-link management", + .chain = stlink_dap_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +/** */ +static int stlink_dap_init(void) +{ + enum reset_types jtag_reset_config = jtag_get_reset_config(); + int retval; + + LOG_DEBUG("stlink_dap_init()"); + + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) + stlink_dap_param.connect_under_reset = true; + else + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } + + if (transport_is_dapdirect_swd()) + stlink_dap_param.transport = HL_TRANSPORT_SWD; + else if (transport_is_dapdirect_jtag()) + stlink_dap_param.transport = HL_TRANSPORT_JTAG; + else { + LOG_ERROR("Unsupported transport"); + return ERROR_FAIL; + } + + retval = stlink_usb_open(&stlink_dap_param, (void **)&stlink_dap_handle); + if (retval != ERROR_OK) + return retval; + + if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DAP_REG)) { + LOG_ERROR("ST-Link version does not support DAP direct transport"); + return ERROR_FAIL; + } + return ERROR_OK; +} + +/** */ +static int stlink_dap_quit(void) +{ + LOG_DEBUG("stlink_dap_quit()"); + + free((void *)stlink_dap_param.serial); + stlink_dap_param.serial = NULL; + + return stlink_usb_close(stlink_dap_handle); +} + +/** */ +static int stlink_dap_reset(int req_trst, int req_srst) +{ + LOG_DEBUG("stlink_dap_reset(%d)", req_srst); + return stlink_usb_assert_srst(stlink_dap_handle, + req_srst ? STLINK_DEBUG_APIV2_DRIVE_NRST_LOW + : STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH); +} + +/** */ +static int stlink_dap_speed(int speed) +{ + if (speed == 0) { + LOG_ERROR("RTCK not supported. Set nonzero adapter_khz."); + return ERROR_JTAG_NOT_IMPLEMENTED; + } + + stlink_dap_param.initial_interface_speed = speed; + stlink_speed(stlink_dap_handle, speed, false); + return ERROR_OK; +} + +/** */ +static int stlink_dap_khz(int khz, int *jtag_speed) +{ + *jtag_speed = khz; + return ERROR_OK; +} + +/** */ +static int stlink_dap_speed_div(int speed, int *khz) +{ + *khz = speed; + return ERROR_OK; +} + +static const struct dap_ops stlink_dap_ops = { + .connect = stlink_dap_op_connect, + .send_sequence = stlink_dap_op_send_sequence, + .queue_dp_read = stlink_dap_op_queue_dp_read, + .queue_dp_write = stlink_dap_op_queue_dp_write, + .queue_ap_read = stlink_dap_op_queue_ap_read, + .queue_ap_write = stlink_dap_op_queue_ap_write, + .queue_ap_abort = stlink_dap_op_queue_ap_abort, + .run = stlink_dap_op_run, + .sync = NULL, /* optional */ + .quit = stlink_dap_op_quit, /* optional */ +}; + +static const char *const stlink_dap_transport[] = { "dapdirect_jtag", "dapdirect_swd", NULL }; + +struct adapter_driver stlink_dap_adapter_driver = { + .name = "st-link", + .transports = stlink_dap_transport, + .commands = stlink_dap_command_handlers, + + .init = stlink_dap_init, + .quit = stlink_dap_quit, + .reset = stlink_dap_reset, + .speed = stlink_dap_speed, + .khz = stlink_dap_khz, + .speed_div = stlink_dap_speed_div, + + .dap_jtag_ops = &stlink_dap_ops, + .dap_swd_ops = &stlink_dap_ops, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index c35484693..17d45415a 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -135,6 +135,9 @@ extern struct adapter_driver imx_gpio_adapter_driver; #if BUILD_XDS110 == 1 extern struct adapter_driver xds110_adapter_driver; #endif +#if BUILD_HLADAPTER == 1 +extern struct adapter_driver stlink_dap_adapter_driver; +#endif #endif /* standard drivers */ /** @@ -240,6 +243,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_XDS110 == 1 &xds110_adapter_driver, #endif +#if BUILD_HLADAPTER == 1 + &stlink_dap_adapter_driver, +#endif #endif /* standard drivers */ NULL, }; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 88b7e5c87..17365bddb 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -279,6 +279,12 @@ struct adiv5_dap { * swizzle appropriately. */ bool ti_be_32_quirks; + /** + * STLINK adapter need to know if last AP operation was read or write, and + * in case of write has to flush it with a dummy read from DP_RDBUFF + */ + bool stlink_flush_ap_write; + /** * Signals that an attempt to reestablish communication afresh * should be performed before the next access. diff --git a/tcl/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg new file mode 100644 index 000000000..f889f74ed --- /dev/null +++ b/tcl/interface/stlink-dap.cfg @@ -0,0 +1,17 @@ +# +# STMicroelectronics ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit +# debugger/programmer +# +# This new interface driver creates a ST-Link wrapper for ARM-DAP +# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support this method +# + +interface st-link +st-link vid_pid 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 + +# transport select dapdirect_jtag +# transport select dapdirect_swd + +# Optionally specify the serial number of usb device +# e.g. +# st-link serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" commit a61ec3c1d73dc0c9915662f7b9383b6f786a5fea Author: Antonio Borneo <bor...@gm...> Date: Wed Jan 23 10:52:28 2019 +0100 adi_v5_dapdirect: add support for adapter drivers that provide DAP API Some high level adapters, like STLINK-V3 and new firmware for ST-Link/V2, provide API to directly access the DAP registers hiding the details of the physical transport JTAG or SWD. OpenOCD has already the intermediate API in struct dap_ops that are suitable for such adapters, but are not exposed to the adapter drivers. Add in struct adapter_driver two independent struct dap_ops for the cases of physical JTAG and SWD transport. Add new transport names "dapdirect_jtag" and "dapdirect_swd", to be used by the drivers that provide one or both DAP API. Add the necessarily glue in target/adi_v5_dapdirect.c Change-Id: I2bb8e3a80fba750f2c218d877cfa5888428e3c28 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/4903 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/core.c b/src/jtag/core.c index 6239573d1..111b122d9 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -2052,7 +2052,8 @@ int adapter_assert_reset(void) else jtag_add_reset(0, 1); return ERROR_OK; - } else if (transport_is_swd() || transport_is_hla()) + } else if (transport_is_swd() || transport_is_hla() || + transport_is_dapdirect_jtag() || transport_is_dapdirect_swd()) return adapter_system_reset(1); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", @@ -2067,7 +2068,8 @@ int adapter_deassert_reset(void) if (transport_is_jtag()) { jtag_add_reset(0, 0); return ERROR_OK; - } else if (transport_is_swd() || transport_is_hla()) + } else if (transport_is_swd() || transport_is_hla() || + transport_is_dapdirect_jtag() || transport_is_dapdirect_swd()) return adapter_system_reset(0); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", diff --git a/src/jtag/interface.h b/src/jtag/interface.h index feda35699..f4c6a98ba 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -351,6 +351,12 @@ struct adapter_driver { /** Low-level SWD APIs */ const struct swd_driver *swd_ops; + + /* DAP APIs over JTAG transport */ + const struct dap_ops *dap_jtag_ops; + + /* DAP APIs over SWD transport */ + const struct dap_ops *dap_swd_ops; }; extern const char * const jtag_only[]; diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 08a4b961f..5a16def55 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -98,6 +98,7 @@ ARM_DEBUG_SRC = \ %D%/arm_dap.c \ %D%/armv7a_cache.c \ %D%/armv7a_cache_l2x.c \ + %D%/adi_v5_dapdirect.c \ %D%/adi_v5_jtag.c \ %D%/adi_v5_swd.c \ %D%/embeddedice.c \ diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c new file mode 100644 index 000000000..f12015198 --- /dev/null +++ b/src/target/adi_v5_dapdirect.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + * Author(s): Antonio Borneo <bor...@gm...> for STMicroelectronics + * + * 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 2 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 <http://www.gnu.org/licenses/>. + */ + +/** + * @file + * Utilities to support in-circuit debuggers that provide APIs to access + * directly ARM DAP, hiding the access to the underlining transport used + * for the physical connection (either JTAG or SWD). + * E.g. STMicroelectronics ST-Link/V2 (from version V2J24) and STLINK-V3. + * + * Single-DAP support only. + * + * For details, see "ARM IHI 0031A" + * ARM Debug Interface v5 Architecture Specification + * + * FIXME: in JTAG mode, trst is not managed + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <jtag/interface.h> +#include <jtag/tcl.h> +#include <transport/transport.h> + +COMMAND_HANDLER(dapdirect_jtag_empty_command) +{ + LOG_DEBUG("dapdirect_jtag_empty_command(\"%s\")", CMD_NAME); + + return ERROR_OK; +} + +COMMAND_HANDLER(dapdirect_jtag_reset_command) +{ + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + /* + * in case the adapter has not already handled asserting srst + * we will attempt it again + */ + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) { + adapter_assert_reset(); + return ERROR_OK; + } + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } + adapter_deassert_reset(); + return ERROR_OK; +} + +static const struct command_registration dapdirect_jtag_subcommand_handlers[] = { + { + .name = "newtap", + .mode = COMMAND_CONFIG, + .jim_handler = jim_jtag_newtap, + .help = "declare a new TAP" + }, + { + .name = "init", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "" + }, + { + .name = "arp_init", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "" + }, + { + .name = "arp_init-reset", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_reset_command, + .usage = "" + }, + { + .name = "tapisenabled", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_tap_enabler, + }, + { + .name = "tapenable", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_tap_enabler, + }, + { + .name = "tapdisable", + .mode = COMMAND_EXEC, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + { + .name = "configure", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + { + .name = "cget", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_configure, + }, + { + .name = "names", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_jtag_handlers[] = { + { + .name = "jtag", + .mode = COMMAND_ANY, + .chain = dapdirect_jtag_subcommand_handlers, + .usage = "", + }, + { + .name = "jtag_ntrst_delay", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_swd_subcommand_handlers[] = { + { + .name = "newdap", + .mode = COMMAND_CONFIG, + .jim_handler = jim_jtag_newtap, + .help = "declare a new SWD DAP", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_swd_handlers[] = { + { + .name = "swd", + .mode = COMMAND_ANY, + .help = "SWD command group", + .usage = "", + .chain = dapdirect_swd_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +static int dapdirect_jtag_select(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_jtag_select()"); + + return register_commands(ctx, NULL, dapdirect_jtag_handlers); +} + +static int dapdirect_swd_select(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_swd_select()"); + + return register_commands(ctx, NULL, dapdirect_swd_handlers); +} + +static int dapdirect_init(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_init()"); + + adapter_deassert_reset(); + return ERROR_OK; +} + +static struct transport dapdirect_jtag_transport = { + .name = "dapdirect_jtag", + .select = dapdirect_jtag_select, + .init = dapdirect_init, +}; + +static struct transport dapdirect_swd_transport = { + .name = "dapdirect_swd", + .select = dapdirect_swd_select, + .init = dapdirect_init, +}; + +static void dapdirect_constructor(void) __attribute__((constructor)); +static void dapdirect_constructor(void) +{ + transport_register(&dapdirect_jtag_transport); + transport_register(&dapdirect_swd_transport); +} + +/** + * Returns true if the current debug session + * is using JTAG as its transport. + */ +bool transport_is_dapdirect_jtag(void) +{ + return get_current_transport() == &dapdirect_jtag_transport; +} + +/** + * Returns true if the current debug session + * is using SWD as its transport. + */ +bool transport_is_dapdirect_swd(void) +{ + return get_current_transport() == &dapdirect_swd_transport; +} diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 4be94b41b..56442f183 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -119,6 +119,10 @@ static int dap_init_all(void) if (transport_is_swd()) { dap->ops = &swd_dap_ops; obj->swd = adapter_driver->swd_ops; + } else if (transport_is_dapdirect_swd()) { + dap->ops = adapter_driver->dap_swd_ops; + } else if (transport_is_dapdirect_jtag()) { + dap->ops = adapter_driver->dap_jtag_ops; } else dap->ops = &jtag_dp_ops; diff --git a/src/transport/transport.h b/src/transport/transport.h index 140ef503d..4effca5d5 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -96,6 +96,8 @@ bool transports_are_declared(void); bool transport_is_jtag(void); bool transport_is_swd(void); +bool transport_is_dapdirect_jtag(void); +bool transport_is_dapdirect_swd(void); #if BUILD_HLADAPTER bool transport_is_hla(void); ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 37 ++- src/jtag/core.c | 6 +- src/jtag/drivers/stlink_usb.c | 680 +++++++++++++++++++++++++++++++++++++++++- src/jtag/interface.h | 6 + src/jtag/interfaces.c | 6 + src/target/Makefile.am | 1 + src/target/adi_v5_dapdirect.c | 223 ++++++++++++++ src/target/arm_adi_v5.h | 6 + src/target/arm_dap.c | 4 + src/transport/transport.h | 2 + tcl/interface/stlink-dap.cfg | 17 ++ 11 files changed, 973 insertions(+), 15 deletions(-) create mode 100644 src/target/adi_v5_dapdirect.c create mode 100644 tcl/interface/stlink-dap.cfg hooks/post-receive -- Main OpenOCD repository |