From eb6a5faf6ac8aa1791ada64e95768ff4ed29084c Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Tue, 6 Apr 2021 18:51:57 +0900 Subject: [PATCH 01/58] doc: Group adapter sub-commands The commit 5280eb618a8cab46 fixed all `adapter_khz` and `adapter_nsrst_*` commands in the doc but missed grouping them. This let the commands `adapter speed`, `adapter srst pulse_width`, and `adapter srst delay` not indexed. Tell texinfo about adapter sub-commands by grouping them in one. Change-Id: Ida53c4f5cfe28827320c145c8d501d53e831623c Signed-off-by: Yasushi SHOJI Reviewed-on: http://openocd.zylin.com/6134 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 6b74243b8..e39ff86f3 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3415,7 +3415,7 @@ may not be the fastest solution. instead of @command{adapter speed}, but only for (ARM) cores and boards which support adaptive clocking. -@deffn {Command} adapter speed 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 @@ -3585,13 +3585,13 @@ needing to cope with both architecture and board specific constraints. @section Commands for Handling Resets -@deffn {Command} adapter srst pulse_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 srst 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 From 7c4458fe283bf01fb6bb7042c00d63ea781d6d15 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 6 Apr 2021 23:24:49 +0200 Subject: [PATCH 02/58] doc: [1/3] uniform the texinfo syntax for commands definition To avoid errors in the documentation, like the one fixed by change http://openocd.zylin.com/6134/ , use a uniform notation across the file so simple copy-paste will work. Both 'Command' and '{Command}' are in use, with the following statistics: 0 @deffnx {Command} 45 @deffn {Command} 31 @deffnx Command 382 @deffn Command While 'Command' is the most popular, prefer the version within curly-brackets that has to be used for multi-word definition like '{NAND Driver}', '{Config Command}', '{FPGA Driver}', ... Patch generated through: sed -i 's/^\(@deffn \)\(Command\)/\1{\2}/' doc/openocd.texi sed -i 's/^\(@deffnx \)\(Command\)/\1{\2}/' doc/openocd.texi Change-Id: If692bbf7e546c5287f466a6aa6940d42b3d4655d Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6150 Reviewed-by: Yasushi SHOJI Tested-by: jenkins --- doc/openocd.texi | 826 +++++++++++++++++++++++------------------------ 1 file changed, 413 insertions(+), 413 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index e39ff86f3..247938fae 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2265,7 +2265,7 @@ to the various active targets. There is a command to manage and monitor that polling, which is normally done in the background. -@deffn Command poll [@option{on}|@option{off}] +@deffn {Command} poll [@option{on}|@option{off}] Poll the current target for its current state. (Also, @pxref{targetcurstate,,target curstate}.) If that target is in debug mode, architecture @@ -2339,11 +2339,11 @@ Use the adapter driver @var{name} to connect to the target. @end deffn -@deffn Command {adapter list} +@deffn {Command} {adapter list} List the debug adapter drivers that have been built into the running copy of OpenOCD. @end deffn -@deffn Command {adapter 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 @@ -2352,12 +2352,12 @@ the hardware can support. -@deffn Command {adapter name} +@deffn {Command} {adapter name} Returns the name of the debug adapter driver being used. @end deffn @anchor{adapter_usb_location} -@deffn Command {adapter usb location} [-[.]...] +@deffn {Command} {adapter usb location} [-[.]...] Displays or specifies the physical USB port of the adapter to use. The path roots at @var{bus} and walks down the physical ports, with each @var{port} option specifying a deeper level in the bus topology, the last @@ -2393,7 +2393,7 @@ Optionally sets that option first. Olimex ARM-JTAG-EW USB adapter This has one driver-specific command: -@deffn Command {armjtagew_info} +@deffn {Command} {armjtagew_info} Logs some status @end deffn @end deffn @@ -2992,7 +2992,7 @@ When using PPDEV to access the parallel port, use the number of the parallel por you may encounter a problem. @end deffn -@deffn Command {parport_toggling_time} [nanoseconds] +@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 speed} configuration. @@ -3283,12 +3283,12 @@ As noted earlier, depending on the version of OpenOCD you use, and the debug adapter you are using, several transports may be available to communicate with debug targets (or perhaps to program flash memory). -@deffn Command {transport list} +@deffn {Command} {transport list} displays the names of the transports supported by this version of OpenOCD. @end deffn -@deffn Command {transport select} @option{transport_name} +@deffn {Command} {transport select} @option{transport_name} Select which of the supported transports to use in this OpenOCD session. When invoked with @option{transport_name}, attempts to select the named @@ -3335,12 +3335,12 @@ 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} ... +@deffn {Command} {swd newdap} ... Declares a single DAP which uses SWD transport. Parameters are currently the same as "jtag newtap" but this is expected to change. @end deffn -@deffn Command {swd wcr trn prescale} +@deffn {Command} {swd wcr trn prescale} Updates TRN (turnaround delay) and prescaling.fields of the Wire Control Register (WCR). No parameters: displays current settings. @@ -3415,7 +3415,7 @@ may not be the fastest solution. instead of @command{adapter speed}, but only for (ARM) cores and boards which support adaptive clocking. -@deffn Command {adapter speed} 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 @@ -3585,13 +3585,13 @@ needing to cope with both architecture and board specific constraints. @section Commands for Handling Resets -@deffn Command {adapter srst pulse_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 srst 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 @@ -3768,7 +3768,7 @@ This is done by calling @command{jtag arp_init} (or @command{jtag arp_init-reset}). @end deffn -@deffn Command {jtag arp_init} +@deffn {Command} {jtag arp_init} This validates the scan chain using just the four standard JTAG signals (TMS, TCK, TDI, TDO). It starts by issuing a JTAG-only reset. @@ -3781,7 +3781,7 @@ If these tests all pass, TAP @code{setup} events are issued to all TAPs with handlers for that event. @end deffn -@deffn Command {jtag arp_init-reset} +@deffn {Command} {jtag arp_init-reset} This uses TRST and SRST to try resetting everything on the JTAG scan chain (and anything else connected to SRST). @@ -3889,7 +3889,7 @@ Actual config files typically use a variable such as @code{$_CHIPNAME} instead of literals like @option{str912}, to support more than one chip of each type. @xref{Config File Guidelines}. -@deffn Command {jtag names} +@deffn {Command} {jtag names} Returns the names of all current TAPs in the scan chain. Use @command{jtag cget} or @command{jtag tapisenabled} to examine attributes and state of each TAP. @@ -3900,7 +3900,7 @@ foreach t [jtag names] @{ @end example @end deffn -@deffn Command {scan_chain} +@deffn {Command} {scan_chain} Displays the TAPs in the scan chain configuration, and their status. The set of TAPs listed by this command is fixed by @@ -3934,7 +3934,7 @@ and underscores are OK; while others (including dots!) are not. @section TAP Declaration Commands @c shouldn't this be(come) a {Config Command}? -@deffn Command {jtag newtap} chipname tapname configparams... +@deffn {Command} {jtag newtap} chipname tapname configparams... Declares a new TAP with the dotted name @var{chipname}.@var{tapname}, and configured according to the various @var{configparams}. @@ -4026,12 +4026,12 @@ devices do not set the ack bit until sometime later. @section Other TAP commands -@deffn Command {jtag cget} dotted.name @option{-idcode} +@deffn {Command} {jtag cget} dotted.name @option{-idcode} Get the value of the IDCODE found in hardware. @end deffn -@deffn Command {jtag cget} dotted.name @option{-event} event_name -@deffnx Command {jtag configure} dotted.name @option{-event} event_name handler +@deffn {Command} {jtag cget} dotted.name @option{-event} event_name +@deffnx {Command} {jtag configure} dotted.name @option{-event} event_name handler At this writing this TAP attribute mechanism is limited and used mostly for event handling. (It is not a direct analogue of the @code{cget}/@code{configure} @@ -4152,7 +4152,7 @@ uses quotes to evaluate @code{$CHIP} when the event is configured. Using brackets @{ @} would cause it to be evaluated later, at runtime, when it might have a different value. -@deffn Command {jtag tapdisable} dotted.name +@deffn {Command} {jtag tapdisable} dotted.name If necessary, disables the tap by sending it a @option{tap-disable} event. Returns the string "1" if the tap @@ -4160,7 +4160,7 @@ specified by @var{dotted.name} is enabled, and "0" if it is disabled. @end deffn -@deffn Command {jtag tapenable} dotted.name +@deffn {Command} {jtag tapenable} dotted.name If necessary, enables the tap by sending it a @option{tap-enable} event. Returns the string "1" if the tap @@ -4168,7 +4168,7 @@ specified by @var{dotted.name} is enabled, and "0" if it is disabled. @end deffn -@deffn Command {jtag tapisenabled} dotted.name +@deffn {Command} {jtag tapisenabled} dotted.name Returns the string "1" if the tap specified by @var{dotted.name} is enabled, and "0" if it is disabled. @@ -4260,7 +4260,7 @@ instead of "@option{-chain-position} @var{dotted.name}" when the target is creat The @command{dap} command group supports the following sub-commands: -@deffn Command {dap create} dap_name @option{-chain-position} dotted.name configparams... +@deffn {Command} {dap create} dap_name @option{-chain-position} dotted.name configparams... Declare a DAP instance named @var{dap_name} linked to the JTAG tap @var{dotted.name}. This also creates a new command (@command{dap_name}) which is used for various purposes including additional configuration. @@ -4277,17 +4277,17 @@ devices do not set the ack bit until sometime later. @end itemize @end deffn -@deffn Command {dap names} +@deffn {Command} {dap names} This command returns a list of all registered DAP objects. It it useful mainly for TCL scripting. @end deffn -@deffn Command {dap info} [num] +@deffn {Command} {dap info} [num] Displays the ROM table for MEM-AP @var{num}, defaulting to the currently selected AP of the currently selected target. @end deffn -@deffn Command {dap init} +@deffn {Command} {dap init} Initialize all registered DAPs. This command is used internally during initialization. It can be issued at any time after the initialization, too. @@ -4295,27 +4295,27 @@ initialization, too. The following commands exist as subcommands of DAP instances: -@deffn Command {$dap_name info} [num] +@deffn {Command} {$dap_name info} [num] Displays the ROM table for MEM-AP @var{num}, defaulting to the currently selected AP. @end deffn -@deffn Command {$dap_name apid} [num] +@deffn {Command} {$dap_name apid} [num] Displays ID register from AP @var{num}, defaulting to the currently selected AP. @end deffn @anchor{DAP subcommand apreg} -@deffn Command {$dap_name apreg} ap_num reg [value] +@deffn {Command} {$dap_name apreg} ap_num reg [value] Displays content of a register @var{reg} from AP @var{ap_num} or set a new value @var{value}. @var{reg} is byte address of a word register, 0, 4, 8 ... 0xfc. @end deffn -@deffn Command {$dap_name apsel} [num] +@deffn {Command} {$dap_name apsel} [num] Select AP @var{num}, defaulting to 0. @end deffn -@deffn Command {$dap_name dpreg} reg [value] +@deffn {Command} {$dap_name dpreg} reg [value] Displays the content of DP register at address @var{reg}, or set it to a new value @var{value}. @@ -4327,18 +4327,18 @@ In case of JTAG it only assumes values 0, 4, 8 and 0xc. background activity by OpenOCD while you are operating at such low-level. @end deffn -@deffn Command {$dap_name baseaddr} [num] +@deffn {Command} {$dap_name baseaddr} [num] Displays debug base address from MEM-AP @var{num}, defaulting to the currently selected AP. @end deffn -@deffn Command {$dap_name memaccess} [value] +@deffn {Command} {$dap_name memaccess} [value] Displays the number of extra tck cycles in the JTAG idle to use for MEM-AP memory bus access [0-255], giving additional time to respond to reads. If @var{value} is defined, first assigns that. @end deffn -@deffn Command {$dap_name apcsw} [value [mask]] +@deffn {Command} {$dap_name apcsw} [value [mask]] Displays or changes CSW bit pattern for MEM-AP transfers. At the begin of each memory access the CSW pattern is extended (bitwise or-ed) @@ -4381,7 +4381,7 @@ xxx.dap apcsw default @end example @end deffn -@deffn Command {$dap_name ti_be_32_quirks} [@option{enable}] +@deffn {Command} {$dap_name ti_be_32_quirks} [@option{enable}] Set/get quirks mode for TI TMS450/TMS570 processors Disabled by default @end deffn @@ -4430,11 +4430,11 @@ are examples; and there are many more. Several commands let you examine the list of targets: -@deffn Command {target current} +@deffn {Command} {target current} Returns the name of the current target. @end deffn -@deffn Command {target names} +@deffn {Command} {target names} Lists the names of all current targets in the list. @example foreach t [target names] @{ @@ -4446,7 +4446,7 @@ foreach t [target names] @{ @c yep, "target list" would have been better. @c plus maybe "target setdefault". -@deffn Command targets [name] +@deffn {Command} targets [name] @emph{Note: the name of this command is plural. Other target command names are singular.} @@ -4477,7 +4477,7 @@ It's easy to see what target types are supported, since there's a command to list them. @anchor{targettypes} -@deffn Command {target types} +@deffn {Command} {target types} Lists all supported target types. At this writing, the supported CPU types are: @@ -4612,7 +4612,7 @@ That may be needed to let you write the boot loader into flash, in order to ``de-brick'' your board; or to load programs into external DDR memory without having run the boot loader. -@deffn Command {target create} target_name type configparams... +@deffn {Command} {target create} target_name type configparams... This command creates a GDB debug target that refers to a specific JTAG tap. It enters that target into a list, and creates a new command (@command{@var{target_name}}) which is used for various @@ -4637,7 +4637,7 @@ You @emph{must} set the @code{-chain-position @var{dotted.name}} or @end itemize @end deffn -@deffn Command {$target_name configure} configparams... +@deffn {Command} {$target_name configure} configparams... The options accepted by this command may also be specified as parameters to @command{target create}. Their values can later be queried one at a time by @@ -4760,18 +4760,18 @@ omap3530.cpu mww 0x5555 123 The commands supported by OpenOCD target objects are: -@deffn Command {$target_name arp_examine} @option{allow-defer} -@deffnx Command {$target_name arp_halt} -@deffnx Command {$target_name arp_poll} -@deffnx Command {$target_name arp_reset} -@deffnx Command {$target_name arp_waitstate} +@deffn {Command} {$target_name arp_examine} @option{allow-defer} +@deffnx {Command} {$target_name arp_halt} +@deffnx {Command} {$target_name arp_poll} +@deffnx {Command} {$target_name arp_reset} +@deffnx {Command} {$target_name arp_waitstate} Internal OpenOCD scripts (most notably @file{startup.tcl}) use these to deal with specific reset cases. They are not otherwise documented here. @end deffn -@deffn Command {$target_name array2mem} arrayname width address count -@deffnx Command {$target_name mem2array} arrayname width address count +@deffn {Command} {$target_name array2mem} arrayname width address count +@deffnx {Command} {$target_name mem2array} arrayname width address count These provide an efficient script-oriented interface to memory. The @code{array2mem} primitive writes bytes, halfwords, or words; while @code{mem2array} reads them. @@ -4793,7 +4793,7 @@ and neither store nor return those values. @end itemize @end deffn -@deffn Command {$target_name cget} queryparm +@deffn {Command} {$target_name cget} queryparm Each configuration parameter accepted by @command{$target_name configure} can be individually queried, to return its current value. @@ -4826,7 +4826,7 @@ foreach name [target names] @{ @end deffn @anchor{targetcurstate} -@deffn Command {$target_name curstate} +@deffn {Command} {$target_name curstate} Displays the current target state: @code{debug-running}, @code{halted}, @@ -4835,22 +4835,22 @@ Displays the current target state: (Also, @pxref{eventpolling,,Event Polling}.) @end deffn -@deffn Command {$target_name eventlist} +@deffn {Command} {$target_name eventlist} Displays a table listing all event handlers currently associated with this target. @xref{targetevents,,Target Events}. @end deffn -@deffn Command {$target_name invoke-event} event_name +@deffn {Command} {$target_name invoke-event} event_name Invokes the handler for the event named @var{event_name}. (This is primarily intended for use by OpenOCD framework code, for example by the reset code in @file{startup.tcl}.) @end deffn -@deffn Command {$target_name mdd} [phys] addr [count] -@deffnx Command {$target_name mdw} [phys] addr [count] -@deffnx Command {$target_name mdh} [phys] addr [count] -@deffnx Command {$target_name mdb} [phys] addr [count] +@deffn {Command} {$target_name mdd} [phys] addr [count] +@deffnx {Command} {$target_name mdw} [phys] addr [count] +@deffnx {Command} {$target_name mdh} [phys] addr [count] +@deffnx {Command} {$target_name mdb} [phys] addr [count] Display contents of address @var{addr}, as 64-bit doublewords (@command{mdd}), 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), @@ -4864,10 +4864,10 @@ If @var{count} is specified, displays that many units. see the @code{mem2array} primitives.) @end deffn -@deffn Command {$target_name mwd} [phys] addr doubleword [count] -@deffnx Command {$target_name mww} [phys] addr word [count] -@deffnx Command {$target_name mwh} [phys] addr halfword [count] -@deffnx Command {$target_name mwb} [phys] addr byte [count] +@deffn {Command} {$target_name mwd} [phys] addr doubleword [count] +@deffnx {Command} {$target_name mww} [phys] addr word [count] +@deffnx {Command} {$target_name mwh} [phys] addr halfword [count] +@deffnx {Command} {$target_name mwb} [phys] addr byte [count] Writes the specified @var{doubleword} (64 bits), @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) value, at the specified address @var{addr}. @@ -5105,20 +5105,20 @@ Use it in board specific configuration files, not interactively. @end deffn @comment less confusing would be: "flash list" (like "nand list") -@deffn Command {flash banks} +@deffn {Command} {flash banks} Prints a one-line summary of each device that was declared using @command{flash bank}, numbered from zero. Note that this is the @emph{plural} form; the @emph{singular} form is a very different command. @end deffn -@deffn Command {flash list} +@deffn {Command} {flash list} Retrieves a list of associative arrays for each device that was declared using @command{flash bank}, numbered from zero. This returned list can be manipulated easily from within scripts. @end deffn -@deffn Command {flash probe} num +@deffn {Command} {flash probe} num Identify the flash, or validate the parameters of the configured flash. Operation depends on the flash type. The @var{num} parameter is a value shown by @command{flash banks}. @@ -5180,7 +5180,7 @@ Examples include CFI flash such as ``Intel Advanced Bootblock flash'', and AT91SAM7 on-chip flash. @xref{flashprotect,,flash protect}. -@deffn Command {flash erase_sector} num first last +@deffn {Command} {flash erase_sector} num first last Erase sectors in bank @var{num}, starting at sector @var{first} up to and including @var{last}. Sector numbering starts at 0. @@ -5189,7 +5189,7 @@ specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash erase_address} [@option{pad}] [@option{unlock}] address length +@deffn {Command} {flash erase_address} [@option{pad}] [@option{unlock}] address length Erase sectors starting at @var{address} for @var{length} bytes. Unless @option{pad} is specified, @math{address} must begin a flash sector, and @math{address + length - 1} must end a sector. @@ -5203,10 +5203,10 @@ If @option{unlock} is specified, then the flash is unprotected before erase starts. @end deffn -@deffn Command {flash filld} address double-word length -@deffnx Command {flash fillw} address word length -@deffnx Command {flash fillh} address halfword length -@deffnx Command {flash fillb} address byte length +@deffn {Command} {flash filld} address double-word length +@deffnx {Command} {flash fillw} address word length +@deffnx {Command} {flash fillh} address halfword length +@deffnx {Command} {flash fillb} address byte length Fills flash memory with the specified @var{double-word} (64 bits), @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) pattern, starting at @var{address} and continuing @@ -5220,9 +5220,9 @@ each block, and the specified length must stay within that bank. @end deffn @comment no current checks for errors if fill blocks touch multiple banks! -@deffn Command {flash mdw} addr [count] -@deffnx Command {flash mdh} addr [count] -@deffnx Command {flash mdb} addr [count] +@deffn {Command} {flash mdw} addr [count] +@deffnx {Command} {flash mdh} addr [count] +@deffnx {Command} {flash mdb} addr [count] Display contents of address @var{addr}, as 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), or 8-bit bytes (@command{mdb}). @@ -5233,14 +5233,14 @@ The flash bank to use is inferred from the @var{address} of each block, and the specified length must stay within that bank. @end deffn -@deffn Command {flash write_bank} num filename [offset] +@deffn {Command} {flash write_bank} num filename [offset] Write the binary @file{filename} to flash bank @var{num}, starting at @var{offset} bytes from the beginning of the bank. If @var{offset} is omitted, start at the beginning of the flash bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash read_bank} num filename [offset [length]] +@deffn {Command} {flash read_bank} num filename [offset [length]] Read @var{length} bytes from the flash bank @var{num} starting at @var{offset} and write the contents to the binary @file{filename}. If @var{offset} is omitted, start at the beginning of the flash bank. If @var{length} is omitted, @@ -5248,14 +5248,14 @@ read the remaining bytes from the flash bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash verify_bank} num filename [offset] +@deffn {Command} {flash verify_bank} num filename [offset] Compare the contents of the binary file @var{filename} with the contents of the flash bank @var{num} starting at @var{offset}. If @var{offset} is omitted, start at the beginning of the flash bank. Fail if the contents do not match. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash write_image} [erase] [unlock] filename [offset] [type] +@deffn {Command} {flash write_image} [erase] [unlock] filename [offset] [type] Write the image @file{filename} to the current target's flash bank(s). Only loadable sections from the image are written. A relocation @var{offset} may be specified, in which case it is added @@ -5292,7 +5292,7 @@ it has been removed by the @option{unlock} flag. @end deffn -@deffn Command {flash verify_image} filename [offset] [type] +@deffn {Command} {flash verify_image} filename [offset] [type] Verify the image @file{filename} to the current target's flash bank(s). Parameters follow the description of 'flash write_image'. In contrast to the 'verify_image' command, for banks with specific @@ -5307,13 +5307,13 @@ check for successful programming. @section Other Flash commands @cindex flash protection -@deffn Command {flash erase_check} num +@deffn {Command} {flash erase_check} num Check erase state of sectors in flash bank @var{num}, and display that status. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash info} num [sectors] +@deffn {Command} {flash info} num [sectors] Print info about flash bank @var{num}, a list of protection blocks and their status. Use @option{sectors} to show a list of sectors instead. @@ -5323,7 +5323,7 @@ and possibly stale information. @end deffn @anchor{flashprotect} -@deffn Command {flash protect} num first last (@option{on}|@option{off}) +@deffn {Command} {flash protect} num first last (@option{on}|@option{off}) Enable (@option{on}) or disable (@option{off}) protection of flash blocks in flash bank @var{num}, starting at protection block @var{first} and continuing up to and including @var{last}. @@ -5335,14 +5335,14 @@ Some devices may utilize a protection block distinct from flash sector. See @command{flash info} for a list of protection blocks. @end deffn -@deffn Command {flash padded_value} num value +@deffn {Command} {flash padded_value} num value Sets the default value used for padding any image sections, This should normally match the flash bank erased value. If not specified by this command or the flash driver then it defaults to 0xff. @end deffn @anchor{program} -@deffn Command {program} filename [preverify] [verify] [reset] [exit] [offset] +@deffn {Command} {program} filename [preverify] [verify] [reset] [exit] [offset] This is a helper script that simplifies using OpenOCD as a standalone programmer. The only required parameter is @option{filename}, the others are optional. @xref{Flash Programming}. @@ -5473,7 +5473,7 @@ only difference is special registers controlling its FPGA specific behavior. They must be properly configured for successful FPGA loading using additional @var{xcf} driver command: -@deffn Command {xcf ccb} +@deffn {Command} {xcf ccb} command accepts additional parameters: @itemize @item @var{external|internal} ... selects clock source. @@ -5492,7 +5492,7 @@ every time you erase/program data sectors because it stores in dedicated sector. @end deffn -@deffn Command {xcf configure} +@deffn {Command} {xcf configure} Initiates FPGA loading procedure. Useful if your board has no "configure" button. @example @@ -5621,12 +5621,12 @@ flash bank $_FLASHNAME stmqspi 0x70000000 0 0 0 \ @end example There are three specific commands -@deffn Command {stmqspi mass_erase} bank_id +@deffn {Command} {stmqspi mass_erase} bank_id Clears sector protections and performs a mass erase. Works only if there is no chip specific write protection engaged. @end deffn -@deffn Command {stmqspi set} bank_id name total_size page_size read_cmd fread_cmd pprg_cmd mass_erase_cmd sector_size sector_erase_cmd +@deffn {Command} {stmqspi set} bank_id name total_size page_size read_cmd fread_cmd pprg_cmd mass_erase_cmd sector_size sector_erase_cmd Set flash parameters: @var{name} human readable string, @var{total_size} size in bytes, @var{page_size} is write page size. @var{read_cmd}, @var{fread_cmd} and @var{pprg_cmd} are commands for reading and page programming. @var{fread_cmd} is used in DPI and QPI modes, @@ -5640,7 +5640,7 @@ In dual mode parameters of both chips are set identically. The parameters refer a single chip, so the whole bank gets twice the specified capacity etc. @end deffn -@deffn Command {stmqspi cmd} bank_id resp_num cmd_byte ... +@deffn {Command} {stmqspi cmd} bank_id resp_num cmd_byte ... If @var{resp_num} is zero, sends command @var{cmd_byte} and following data bytes. In dual mode command byte is sent to @emph{both} chips but data bytes are sent @emph{alternatingly} to chip 1 and 2, first to flash 1, second to flash 2, etc., @@ -5787,13 +5787,13 @@ are available to the user. The @var{ambiqmicro} driver adds some additional commands: -@deffn Command {ambiqmicro mass_erase} +@deffn {Command} {ambiqmicro mass_erase} Erase entire bank. @end deffn -@deffn Command {ambiqmicro page_erase} +@deffn {Command} {ambiqmicro page_erase} Erase device pages. @end deffn -@deffn Command {ambiqmicro program_otp} +@deffn {Command} {ambiqmicro program_otp} Program OTP is a one time operation to create write protected flash. The user writes sectors to SRAM starting at 0x10000010. Program OTP will write these sectors from SRAM to flash, and write protect @@ -5815,13 +5815,13 @@ The devices have one flash bank: flash bank $_FLASHNAME at91samd 0x00000000 0 1 1 $_TARGETNAME @end example -@deffn Command {at91samd chip-erase} +@deffn {Command} {at91samd chip-erase} Issues a complete Flash erase via the Device Service Unit (DSU). This can be used to erase a chip back to its factory state and does not require the processor to be halted. @end deffn -@deffn Command {at91samd set-security} +@deffn {Command} {at91samd set-security} Secures the Flash via the Set Security Bit (SSB) command. This prevents access to the Flash and can only be undone by using the chip-erase command which erases the Flash contents and turns off the security bit. Warning: at this @@ -5833,7 +5833,7 @@ at91samd set-security enable @end example @end deffn -@deffn Command {at91samd eeprom} +@deffn {Command} {at91samd eeprom} Shows or sets the EEPROM emulation size configuration, stored in the User Row of the Flash. When setting, the EEPROM size must be specified in bytes and it must be one of the permitted sizes according to the datasheet. Settings are @@ -5848,7 +5848,7 @@ at91samd eeprom 1024 @end example @end deffn -@deffn Command {at91samd bootloader} +@deffn {Command} {at91samd bootloader} Shows or sets the bootloader size configuration, stored in the User Row of the Flash. This is called the BOOTPROT region. When setting, the bootloader size must be specified in bytes and it must be one of the permitted sizes according @@ -5861,13 +5861,13 @@ at91samd bootloader 16384 @end example @end deffn -@deffn Command {at91samd dsu_reset_deassert} +@deffn {Command} {at91samd dsu_reset_deassert} This command releases internal reset held by DSU and prepares reset vector catch in case of reset halt. Command is used internally in event reset-deassert-post. @end deffn -@deffn Command {at91samd nvmuserrow} +@deffn {Command} {at91samd nvmuserrow} Writes or reads the entire 64 bit wide NVM user row register which is located at 0x804000. This register includes various fuses lock-bits and factory calibration data. Reading the register is done by invoking this command without any @@ -5927,10 +5927,10 @@ to the @command{flash bank} command: The AT91SAM3 driver adds some additional commands: -@deffn Command {at91sam3 gpnvm} -@deffnx Command {at91sam3 gpnvm clear} number -@deffnx Command {at91sam3 gpnvm set} number -@deffnx Command {at91sam3 gpnvm show} [@option{all}|number] +@deffn {Command} {at91sam3 gpnvm} +@deffnx {Command} {at91sam3 gpnvm clear} number +@deffnx {Command} {at91sam3 gpnvm set} number +@deffnx {Command} {at91sam3 gpnvm show} [@option{all}|number] With no parameters, @command{show} or @command{show all}, shows the status of all GPNVM bits. With @command{show} @var{number}, displays that bit. @@ -5939,7 +5939,7 @@ With @command{set} @var{number} or @command{clear} @var{number}, modifies that GPNVM bit. @end deffn -@deffn Command {at91sam3 info} +@deffn {Command} {at91sam3 info} This command attempts to display information about the AT91SAM3 chip. @emph{First} it read the @code{CHIPID_CIDR} [address 0x400e0740, see Section 28.2.1, page 505 of the AT91SAM3U 29/may/2009 datasheet, @@ -5949,7 +5949,7 @@ believes the chip is configured. By default, the SLOWCLK is assumed to be 32768 Hz, see the command @command{at91sam3 slowclk}. @end deffn -@deffn Command {at91sam3 slowclk} [value] +@deffn {Command} {at91sam3 slowclk} [value] This command shows/sets the slow clock frequency used in the @command{at91sam3 info} command calculations above. @end deffn @@ -5969,7 +5969,7 @@ Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same command names/syntax as @xref{at91sam3}. The AT91SAM4L driver adds some additional commands: -@deffn Command {at91sam4l smap_reset_deassert} +@deffn {Command} {at91sam4l smap_reset_deassert} This command releases internal reset held by SMAP and prepares reset vector catch in case of reset halt. Command is used internally in event reset-deassert-post. @@ -5991,7 +5991,7 @@ Bank swapping is not supported yet. flash bank $_FLASHNAME atsame5 0x00000000 0 1 1 $_TARGETNAME @end example -@deffn Command {atsame5 bootloader} +@deffn {Command} {atsame5 bootloader} Shows or sets the bootloader size configuration, stored in the User Page of the Flash. This is called the BOOTPROT region. When setting, the bootloader size must be specified in bytes. The nearest bigger protection size is used. @@ -6004,19 +6004,19 @@ atsame5 bootloader 16384 @end example @end deffn -@deffn Command {atsame5 chip-erase} +@deffn {Command} {atsame5 chip-erase} Issues a complete Flash erase via the Device Service Unit (DSU). This can be used to erase a chip back to its factory state and does not require the processor to be halted. @end deffn -@deffn Command {atsame5 dsu_reset_deassert} +@deffn {Command} {atsame5 dsu_reset_deassert} This command releases internal reset held by DSU and prepares reset vector catch in case of reset halt. Command is used internally in event reset-deassert-post. @end deffn -@deffn Command {atsame5 userpage} +@deffn {Command} {atsame5 userpage} Writes or reads the first 64 bits of NVM User Page which is located at 0x804000. This field includes various fuses. Reading is done by invoking this command without any arguments. @@ -6082,7 +6082,7 @@ However, there is an ``EraseAll`` command that can erase an entire flash plane (of up to 256KB), and it will be used automatically when you issue @command{flash erase_sector} or @command{flash erase_address} commands. -@deffn Command {at91sam7 gpnvm} bitnum (@option{set}|@option{clear}) +@deffn {Command} {at91sam7 gpnvm} bitnum (@option{set}|@option{clear}) Set or clear a ``General Purpose Non-Volatile Memory'' (GPNVM) bit for the processor. Each processor has a number of such bits, used for controlling features such as brownout detection (so they @@ -6177,11 +6177,11 @@ flash bank $_FLASHNAME esirisc base_address size_bytes 0 0 \ $_TARGETNAME cfg_address clock_hz wait_states @end example -@deffn Command {esirisc flash mass_erase} bank_id +@deffn {Command} {esirisc flash mass_erase} bank_id Erase all pages in data memory for the bank identified by @option{bank_id}. @end deffn -@deffn Command {esirisc flash ref_erase} bank_id +@deffn {Command} {esirisc flash ref_erase} bank_id Erase the reference cell for the bank identified by @option{bank_id}. @emph{This is an uncommon operation.} @end deffn @@ -6238,13 +6238,13 @@ The @var{kinetis} driver defines option: flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME @end example -@deffn Command {kinetis create_banks} +@deffn {Command} {kinetis create_banks} Configuration command enables automatic creation of additional flash banks based on real flash layout of device. Banks are created during device probe. Use 'flash probe 0' to force probe. @end deffn -@deffn Command {kinetis fcf_source} [protection|write] +@deffn {Command} {kinetis fcf_source} [protection|write] Select what source is used when writing to a Flash Configuration Field. @option{protection} mode builds FCF content from protection bits previously set by 'flash protect' command. @@ -6256,29 +6256,29 @@ with the rest of a flash image. @emph{BEWARE: Incorrect flash configuration may permanently lock the device!} @end deffn -@deffn Command {kinetis fopt} [num] +@deffn {Command} {kinetis fopt} [num] Set value to write to FOPT byte of Flash Configuration Field. Used in kinetis 'fcf_source protection' mode only. @end deffn -@deffn Command {kinetis mdm check_security} +@deffn {Command} {kinetis mdm check_security} Checks status of device security lock. Used internally in examine-end and examine-fail event. @end deffn -@deffn Command {kinetis mdm halt} +@deffn {Command} {kinetis mdm halt} Issues a halt via the MDM-AP. This command can be used to break a watchdog reset loop when connecting to an unsecured target. @end deffn -@deffn Command {kinetis mdm mass_erase} +@deffn {Command} {kinetis mdm mass_erase} Issues a complete flash erase via the MDM-AP. This can be used to erase a chip back to its factory state, removing security. It does not require the processor to be halted, however the target will remain in a halted state after this command completes. @end deffn -@deffn Command {kinetis nvm_partition} +@deffn {Command} {kinetis nvm_partition} For FlexNVM devices only (KxxDX and KxxFX). Command shows or sets data flash or EEPROM backup size in kilobytes, sets two EEPROM blocks sizes in bytes and enables/disables loading @@ -6308,12 +6308,12 @@ kinetis nvm_partition eebkp 16 1024 1024 off @end example @end deffn -@deffn Command {kinetis mdm reset} +@deffn {Command} {kinetis mdm reset} Issues a reset via the MDM-AP. This causes the MCU to output a low pulse on the RESET pin, which can be used to reset other hardware on board. @end deffn -@deffn Command {kinetis disable_wdog} +@deffn {Command} {kinetis disable_wdog} For Kx devices only (KLx has different COP watchdog, it is not supported). Command disables watchdog timer. @end deffn @@ -6331,18 +6331,18 @@ Use kinetis (not kinetis_ke) driver for KE1x devices. flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME @end example -@deffn Command {kinetis_ke mdm check_security} +@deffn {Command} {kinetis_ke mdm check_security} Checks status of device security lock. Used internally in examine-end event. @end deffn -@deffn Command {kinetis_ke mdm mass_erase} +@deffn {Command} {kinetis_ke mdm mass_erase} Issues a complete Flash erase via the MDM-AP. This can be used to erase a chip back to its factory state. Command removes security lock from a device (use of SRST highly recommended). It does not require the processor to be halted. @end deffn -@deffn Command {kinetis_ke disable_wdog} +@deffn {Command} {kinetis_ke disable_wdog} Command disables watchdog timer. @end deffn @end deffn @@ -6452,7 +6452,7 @@ Some @code{lpc2900}-specific commands are defined. In the following command list the @var{bank} parameter is the bank number as obtained by the @code{flash banks} command. -@deffn Command {lpc2900 signature} bank +@deffn {Command} {lpc2900 signature} bank Calculates a 128-bit hash value, the @emph{signature}, from the whole flash content. This is a hardware feature of the flash block, hence the calculation is very fast. You may use this to verify the content of a programmed device against @@ -6464,7 +6464,7 @@ lpc2900 signature 0 @end example @end deffn -@deffn Command {lpc2900 read_custom} bank filename +@deffn {Command} {lpc2900 read_custom} bank filename Reads the 912 bytes of customer information from the flash index sector, and saves it to a file in binary format. Example: @@ -6478,7 +6478,7 @@ erased! In order to guard against unintentional write access, all following commands need to be preceded by a successful call to the @code{password} command: -@deffn Command {lpc2900 password} bank password +@deffn {Command} {lpc2900 password} bank password You need to use this command right before each of the following commands: @code{lpc2900 write_custom}, @code{lpc2900 secure_sector}, @code{lpc2900 secure_jtag}. @@ -6491,7 +6491,7 @@ lpc2900 password 0 I_know_what_I_am_doing @end example @end deffn -@deffn Command {lpc2900 write_custom} bank filename type +@deffn {Command} {lpc2900 write_custom} bank filename type Writes the content of the file into the customer info space of the flash index sector. The filetype can be specified with the @var{type} field. Possible values for @var{type} are: @var{bin} (binary), @var{ihex} (Intel hex format), @@ -6507,7 +6507,7 @@ lpc2900 write_custom 0 /path_to/customer_info.bin bin @end example @end deffn -@deffn Command {lpc2900 secure_sector} bank first last +@deffn {Command} {lpc2900 secure_sector} bank first last Secures the sector range from @var{first} to @var{last} (including) against further program and erase operations. The sector security will be effective after the next power cycle. @@ -6526,7 +6526,7 @@ flash info 0 @end example @end deffn -@deffn Command {lpc2900 secure_jtag} bank +@deffn {Command} {lpc2900 secure_jtag} bank Irreversibly disable the JTAG port. The new JTAG security setting will be effective after the next power cycle. @quotation Attention @@ -6578,7 +6578,7 @@ MSP432P4 versions starts at address 0x200000. flash bank $_FLASHNAME msp432 0 0 0 0 $_TARGETNAME @end example -@deffn Command {msp432 mass_erase} bank_id [main|all] +@deffn {Command} {msp432 mass_erase} bank_id [main|all] Performs a complete erase of flash. By default, @command{mass_erase} will erase only the main program flash. @@ -6587,7 +6587,7 @@ main program and information flash regions. To also erase the BSL in information flash, the user must first use the @command{bsl} command. @end deffn -@deffn Command {msp432 bsl} bank_id [unlock|lock] +@deffn {Command} {msp432 bsl} bank_id [unlock|lock] On MSP432P4 versions, @command{bsl} unlocks and locks the bootstrap loader (BSL) region in information flash so that flash commands can erase or write the BSL. Leave the BSL locked to prevent accidentally corrupting the bootstrap loader. @@ -6620,43 +6620,43 @@ flash bank $_FLASHNAME niietcm4 0 0 0 0 $_TARGETNAME Some niietcm4-specific commands are defined: -@deffn Command {niietcm4 uflash_read_byte} bank ('main'|'info') address +@deffn {Command} {niietcm4 uflash_read_byte} bank ('main'|'info') address Read byte from main or info userflash region. @end deffn -@deffn Command {niietcm4 uflash_write_byte} bank ('main'|'info') address value +@deffn {Command} {niietcm4 uflash_write_byte} bank ('main'|'info') address value Write byte to main or info userflash region. @end deffn -@deffn Command {niietcm4 uflash_full_erase} bank +@deffn {Command} {niietcm4 uflash_full_erase} bank Erase all userflash including info region. @end deffn -@deffn Command {niietcm4 uflash_erase} bank ('main'|'info') first_sector last_sector +@deffn {Command} {niietcm4 uflash_erase} bank ('main'|'info') first_sector last_sector Erase sectors of main or info userflash region, starting at sector first up to and including last. @end deffn -@deffn Command {niietcm4 uflash_protect_check} bank ('main'|'info') +@deffn {Command} {niietcm4 uflash_protect_check} bank ('main'|'info') Check sectors protect. @end deffn -@deffn Command {niietcm4 uflash_protect} bank ('main'|'info') first_sector last_sector ('on'|'off') +@deffn {Command} {niietcm4 uflash_protect} bank ('main'|'info') first_sector last_sector ('on'|'off') Protect sectors of main or info userflash region, starting at sector first up to and including last. @end deffn -@deffn Command {niietcm4 bflash_info_remap} bank ('on'|'off') +@deffn {Command} {niietcm4 bflash_info_remap} bank ('on'|'off') Enable remapping bootflash info region to 0x00000000 (or 0x40000000 if external memory boot used). @end deffn -@deffn Command {niietcm4 extmem_cfg} bank ('gpioa'|'gpiob'|'gpioc'|'gpiod'|'gpioe'|'gpiof'|'gpiog'|'gpioh') pin_num ('func1'|'func3') +@deffn {Command} {niietcm4 extmem_cfg} bank ('gpioa'|'gpiob'|'gpioc'|'gpiod'|'gpioe'|'gpiof'|'gpiog'|'gpioh') pin_num ('func1'|'func3') Configure external memory interface for boot. @end deffn -@deffn Command {niietcm4 service_mode_erase} bank +@deffn {Command} {niietcm4 service_mode_erase} bank Perform emergency erase of all flash (bootflash and userflash). @end deffn -@deffn Command {niietcm4 driver_info} bank +@deffn {Command} {niietcm4 driver_info} bank Show information about flash driver. @end deffn @@ -6674,14 +6674,14 @@ flash bank $_FLASHNAME nrf5 0 0x00000000 0 0 $_TARGETNAME Some nrf5-specific commands are defined: -@deffn Command {nrf5 mass_erase} +@deffn {Command} {nrf5 mass_erase} Erases the contents of the code memory and user information configuration registers as well. It must be noted that this command works only for chips that do not have factory pre-programmed region 0 code. @end deffn -@deffn Command {nrf5 info} +@deffn {Command} {nrf5 info} Decodes and shows information from FICR and UICR registers. @end deffn @@ -6715,11 +6715,11 @@ flash bank $_FLASHNAME pix32mx 0x1d000000 0 0 0 $_TARGETNAME @comment - lock, unlock ... pointless given protect on/off (yes?) @comment - pgm_word ... shouldn't bank be deduced from address?? Some pic32mx-specific commands are defined: -@deffn Command {pic32mx pgm_word} address value bank +@deffn {Command} {pic32mx pgm_word} address value bank Programs the specified 32-bit @var{value} at the given @var{address} in the specified chip @var{bank}. @end deffn -@deffn Command {pic32mx unlock} bank +@deffn {Command} {pic32mx unlock} bank Unlock and erase specified chip @var{bank}. This will remove any Code Protection. @end deffn @@ -6739,7 +6739,7 @@ flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME @end example psoc4-specific commands -@deffn Command {psoc4 flash_autoerase} num (on|off) +@deffn {Command} {psoc4 flash_autoerase} num (on|off) Enables or disables autoerase mode for a flash bank. If flash_autoerase is off, use mass_erase before flash programming. @@ -6752,7 +6752,7 @@ This mode is suitable for gdb load. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {psoc4 mass_erase} num +@deffn {Command} {psoc4 mass_erase} num Erases the contents of the flash memory, protection and security lock. The @var{num} parameter is a value shown by @command{flash banks}. @@ -6779,7 +6779,7 @@ Writing to the ECC data bytes in ECC-disabled mode is not implemented. Commands defined in the @var{psoc5lp} driver: -@deffn Command {psoc5lp mass_erase} +@deffn {Command} {psoc5lp mass_erase} Erases all flash data and ECC/configuration bytes, all flash protection rows, and all row latches in all flash arrays on the device. @end deffn @@ -6875,7 +6875,7 @@ flash bank super_flash_toc2_cm4 psoc6 0x16007C00 0 0 0 \ @end example psoc6-specific commands -@deffn Command {psoc6 reset_halt} +@deffn {Command} {psoc6 reset_halt} Command can be used to simulate broken Vector Catch from gdbinit or tcl scripts. When invoked for CM0+ target, it will set break point at application entry point and issue SYSRESETREQ. This will reset both cores and all peripherals. CM0+ will @@ -6883,7 +6883,7 @@ reset CM4 during boot anyway so this is safe. On CM4 target, VECTRESET is used instead of SYSRESETREQ to avoid unwanted reset of CM0+; @end deffn -@deffn Command {psoc6 mass_erase} num +@deffn {Command} {psoc6 mass_erase} num Erases the contents given flash bank. The @var{num} parameter is a value shown by @command{flash banks}. Note: only Main and Work flash regions support Erase operation. @@ -6903,12 +6903,12 @@ flash bank $_FLASHNAME sim3x 0 $_CPUROMSIZE 0 0 $_TARGETNAME There are 2 commands defined in the @var{sim3x} driver: -@deffn Command {sim3x mass_erase} +@deffn {Command} {sim3x mass_erase} Erases the complete flash. This is used to unlock the flash. And this command is only possible when using the SWD interface. @end deffn -@deffn Command {sim3x lock} +@deffn {Command} {sim3x lock} Lock the flash. To unlock use the @command{sim3x mass_erase} command. @end deffn @end deffn @@ -6923,7 +6923,7 @@ identification register, and autoconfigures itself. flash bank $_FLASHNAME stellaris 0 0 0 0 $_TARGETNAME @end example -@deffn Command {stellaris recover} +@deffn {Command} {stellaris recover} Performs the @emph{Recovering a "Locked" Device} procedure to restore the flash and its associated nonvolatile registers to their factory default values (erased). This is the only way to remove flash @@ -6965,35 +6965,35 @@ flash bank $_FLASHNAME stm32f1x 0x08080000 0 0 0 $_TARGETNAME Some stm32f1x-specific commands are defined: -@deffn Command {stm32f1x lock} num +@deffn {Command} {stm32f1x lock} num Locks the entire stm32 device against reading. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f1x unlock} num +@deffn {Command} {stm32f1x unlock} num Unlocks the entire stm32 device for reading. This command will cause a mass erase of the entire stm32 device if previously locked. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f1x mass_erase} num +@deffn {Command} {stm32f1x mass_erase} num Mass erases the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f1x options_read} num +@deffn {Command} {stm32f1x options_read} num Reads and displays active stm32 option bytes loaded during POR or upon executing the @command{stm32f1x options_load} command. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f1x options_write} num (@option{SWWDG}|@option{HWWDG}) (@option{RSTSTNDBY}|@option{NORSTSTNDBY}) (@option{RSTSTOP}|@option{NORSTSTOP}) (@option{USEROPT} user_data) +@deffn {Command} {stm32f1x options_write} num (@option{SWWDG}|@option{HWWDG}) (@option{RSTSTNDBY}|@option{NORSTSTNDBY}) (@option{RSTSTOP}|@option{NORSTSTOP}) (@option{USEROPT} user_data) Writes the stm32 option byte with the specified values. The @var{num} parameter is a value shown by @command{flash banks}. The @var{user_data} parameter is content of higher 16 bits of the option byte register (Data0 and Data1 as one 16bit number). @end deffn -@deffn Command {stm32f1x options_load} num +@deffn {Command} {stm32f1x options_load} num Generates a special kind of reset to re-load the stm32 option bytes written by the @command{stm32f1x options_write} or @command{flash protect} commands without having to power cycle the target. Not applicable to stm32f1x devices. @@ -7017,7 +7017,7 @@ as per the following example. flash bank $_FLASHNAME stm32f2x 0x1FFF7800 0 0 0 $_TARGETNAME @end example -@deffn Command {stm32f2x otp } num (@option{enable}|@option{disable}|@option{show}) +@deffn {Command} {stm32f2x otp } num (@option{enable}|@option{disable}|@option{show}) Enables or disables OTP write commands for bank @var{num}. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @@ -7032,27 +7032,27 @@ flash bank $_FLASHNAME stm32f2x 0 0x20000 0 0 $_TARGETNAME Some stm32f2x-specific commands are defined: -@deffn Command {stm32f2x lock} num +@deffn {Command} {stm32f2x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f2x unlock} num +@deffn {Command} {stm32f2x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f2x mass_erase} num +@deffn {Command} {stm32f2x mass_erase} num Mass erases the entire stm32f2x device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f2x options_read} num +@deffn {Command} {stm32f2x options_read} num Reads and displays user options and (where implemented) boot_addr0, boot_addr1, optcr2. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32f2x options_write} num user_options boot_addr0 boot_addr1 +@deffn {Command} {stm32f2x options_write} num user_options boot_addr0 boot_addr1 Writes user options and (where implemented) boot_addr0 and boot_addr1 in raw format. Warning: The meaning of the various bits depends on the device, always check datasheet! The @var{num} parameter is a value shown by @command{flash banks}, @var{user_options} a @@ -7060,7 +7060,7 @@ The @var{num} parameter is a value shown by @command{flash banks}, @var{user_opt @var{boot_addr1} two halfwords (of FLASH_OPTCR1). @end deffn -@deffn Command {stm32f2x optcr2_write} num optcr2 +@deffn {Command} {stm32f2x optcr2_write} num optcr2 Writes FLASH_OPTCR2 options. Warning: Clearing PCROPi bits requires a full mass erase! The @var{num} parameter is a value shown by @command{flash banks}, @var{optcr2} a 32-bit word. @end deffn @@ -7086,22 +7086,22 @@ flash bank $_FLASHNAME stm32h7x 0 0x20000 0 0 $_TARGETNAME Some stm32h7x-specific commands are defined: -@deffn Command {stm32h7x lock} num +@deffn {Command} {stm32h7x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32h7x unlock} num +@deffn {Command} {stm32h7x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32h7x mass_erase} num +@deffn {Command} {stm32h7x mass_erase} num Mass erases the entire stm32h7x device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32h7x option_read} num reg_offset +@deffn {Command} {stm32h7x option_read} num reg_offset Reads an option byte register from the stm32h7x device. The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offset} is the register offset of the option byte to read from the used bank registers' base. @@ -7118,7 +7118,7 @@ stm32h7x option_read 1 0x38 @end example @end deffn -@deffn Command {stm32h7x option_write} num reg_offset value [reg_mask] +@deffn {Command} {stm32h7x option_write} num reg_offset value [reg_mask] Writes an option byte register of the stm32h7x device. The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offset} is the register offset of the option byte to write from the used bank register base, @@ -7156,17 +7156,17 @@ flash bank $_FLASHNAME stm32lx 0x08000000 0x20000 0 0 $_TARGETNAME Some stm32lx-specific commands are defined: -@deffn Command {stm32lx lock} num +@deffn {Command} {stm32lx lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32lx unlock} num +@deffn {Command} {stm32lx unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32lx mass_erase} num +@deffn {Command} {stm32lx mass_erase} num Mass erases the entire stm32lx device (all flash banks and EEPROM data). This is the only way to unlock a protected flash (unless RDP Level is 2 which can't be unlocked at all). @@ -7191,7 +7191,7 @@ as per the following example. flash bank $_FLASHNAME stm32l4x 0x1FFF7000 0 0 0 $_TARGETNAME @end example -@deffn Command {stm32l4x otp} num (@option{enable}|@option{disable}|@option{show}) +@deffn {Command} {stm32l4x otp} num (@option{enable}|@option{disable}|@option{show}) Enables or disables OTP write commands for bank @var{num}. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @@ -7207,22 +7207,22 @@ flash bank $_FLASHNAME stm32l4x 0x08000000 0x40000 0 0 $_TARGETNAME Some stm32l4x-specific commands are defined: -@deffn Command {stm32l4x lock} num +@deffn {Command} {stm32l4x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32l4x unlock} num +@deffn {Command} {stm32l4x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32l4x mass_erase} num +@deffn {Command} {stm32l4x mass_erase} num Mass erases the entire stm32l4x device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {stm32l4x option_read} num reg_offset +@deffn {Command} {stm32l4x option_read} num reg_offset Reads an option byte register from the stm32l4x device. The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offset} is the register offset of the Option byte to read. @@ -7239,7 +7239,7 @@ The above example will read out the FLASH_OPTR register which contains the RDP option byte, Watchdog configuration, BOR level etc. @end deffn -@deffn Command {stm32l4x option_write} num reg_offset reg_mask +@deffn {Command} {stm32l4x option_write} num reg_offset reg_mask Write an option byte register of the stm32l4x device. The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offset} is the register offset of the Option byte to write, and @var{reg_mask} is the mask @@ -7255,7 +7255,7 @@ Area A for bank 1. The above example set WRP1AR_END=255, WRP1AR_START=0. This will effectively write protect all sectors in flash bank 1. @end deffn -@deffn Command {stm32l4x wrp_info} num [device_bank] +@deffn {Command} {stm32l4x wrp_info} num [device_bank] List the protected areas using WRP. The @var{num} parameter is a value shown by @command{flash banks}. @var{device_bank} parameter is optional, possible values 'bank1' or 'bank2', @@ -7269,7 +7269,7 @@ write protected areas in a specific @var{device_bank} @end deffn -@deffn Command {stm32l4x option_load} num +@deffn {Command} {stm32l4x option_load} num Forces a re-load of the option byte registers. Will cause a system reset of the device. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @@ -7286,7 +7286,7 @@ flash bank $_FLASHNAME str7x \ 0x40000000 0x00040000 0 0 $_TARGETNAME STR71x @end example -@deffn Command {str7x disable_jtag} bank +@deffn {Command} {str7x disable_jtag} bank Activate the Debug/Readout protection mechanism for the specified flash bank. @end deffn @@ -7303,7 +7303,7 @@ flash bank $_FLASHNAME str9x 0x40000000 0x00040000 0 0 $_TARGETNAME str9x flash_config 0 4 2 0 0x80000 @end example -@deffn Command {str9x flash_config} num bbsr nbbsr bbadr nbbadr +@deffn {Command} {str9x flash_config} num bbsr nbbsr bbadr nbbadr Configures the str9 flash controller. The @var{num} parameter is a value shown by @command{flash banks}. @@ -7364,49 +7364,49 @@ as mentioned above, just issue the commands above manually or from a telnet prom Several str9xpec-specific commands are defined: -@deffn Command {str9xpec disable_turbo} num +@deffn {Command} {str9xpec disable_turbo} num Restore the str9 into JTAG chain. @end deffn -@deffn Command {str9xpec enable_turbo} num +@deffn {Command} {str9xpec enable_turbo} num Enable turbo mode, will simply remove the str9 from the chain and talk directly to the embedded flash controller. @end deffn -@deffn Command {str9xpec lock} num +@deffn {Command} {str9xpec lock} num Lock str9 device. The str9 will only respond to an unlock command that will erase the device. @end deffn -@deffn Command {str9xpec part_id} num +@deffn {Command} {str9xpec part_id} num Prints the part identifier for bank @var{num}. @end deffn -@deffn Command {str9xpec options_cmap} num (@option{bank0}|@option{bank1}) +@deffn {Command} {str9xpec options_cmap} num (@option{bank0}|@option{bank1}) Configure str9 boot bank. @end deffn -@deffn Command {str9xpec options_lvdsel} num (@option{vdd}|@option{vdd_vddq}) +@deffn {Command} {str9xpec options_lvdsel} num (@option{vdd}|@option{vdd_vddq}) Configure str9 lvd source. @end deffn -@deffn Command {str9xpec options_lvdthd} num (@option{2.4v}|@option{2.7v}) +@deffn {Command} {str9xpec options_lvdthd} num (@option{2.4v}|@option{2.7v}) Configure str9 lvd threshold. @end deffn -@deffn Command {str9xpec options_lvdwarn} bank (@option{vdd}|@option{vdd_vddq}) +@deffn {Command} {str9xpec options_lvdwarn} bank (@option{vdd}|@option{vdd_vddq}) Configure str9 lvd reset warning source. @end deffn -@deffn Command {str9xpec options_read} num +@deffn {Command} {str9xpec options_read} num Read str9 option bytes. @end deffn -@deffn Command {str9xpec options_write} num +@deffn {Command} {str9xpec options_write} num Write str9 option bytes. @end deffn -@deffn Command {str9xpec unlock} num +@deffn {Command} {str9xpec unlock} num unlock str9 device. @end deffn @@ -7422,7 +7422,7 @@ flash bank $_FLASHNAME swm050 0x0 0x2000 0 0 $_TARGETNAME One swm050-specific command is defined: -@deffn Command {swm050 mass_erase} bank_id +@deffn {Command} {swm050 mass_erase} bank_id Erases the entire flash bank. @end deffn @@ -7436,15 +7436,15 @@ This driver doesn't require the chip and bus width to be specified. Some tms470-specific commands are defined: -@deffn Command {tms470 flash_keyset} key0 key1 key2 key3 +@deffn {Command} {tms470 flash_keyset} key0 key1 key2 key3 Saves programming keys in a register, to enable flash erase and write commands. @end deffn -@deffn Command {tms470 osc_mhz} clock_mhz +@deffn {Command} {tms470 osc_mhz} clock_mhz Reports the clock speed, which is used to calculate timings. @end deffn -@deffn Command {tms470 plldis} (0|1) +@deffn {Command} {tms470 plldis} (0|1) Disables (@var{1}) or enables (@var{0}) use of the PLL to speed up the flash clock. @end deffn @@ -7472,11 +7472,11 @@ This driver does not require the chip and bus width to be specified. Some xmc4xxx-specific commands are defined: -@deffn Command {xmc4xxx flash_password} bank_id passwd1 passwd2 +@deffn {Command} {xmc4xxx flash_password} bank_id passwd1 passwd2 Saves flash protection passwords which are used to lock the user flash @end deffn -@deffn Command {xmc4xxx flash_unprotect} bank_id user_level[0-1] +@deffn {Command} {xmc4xxx flash_unprotect} bank_id user_level[0-1] Removes Flash write protection from the selected user bank @end deffn @@ -7581,7 +7581,7 @@ for more information. @end itemize @end deffn -@deffn Command {nand list} +@deffn {Command} {nand list} Prints a summary of each device declared using @command{nand device}, numbered from zero. Note that un-probed devices show no details. @@ -7595,7 +7595,7 @@ Note that un-probed devices show no details. @end example @end deffn -@deffn Command {nand probe} num +@deffn {Command} {nand probe} num Probes the specified device to determine key characteristics like its page and block sizes, and how many blocks it has. The @var{num} parameter is the value shown by @command{nand list}. @@ -7605,7 +7605,7 @@ it with most other NAND commands. @subsection Erasing, Reading, Writing to NAND Flash -@deffn Command {nand dump} num filename offset length [oob_option] +@deffn {Command} {nand dump} num filename offset length [oob_option] @cindex NAND reading Reads binary data from the NAND device and writes it to the file, starting at the specified offset. @@ -7642,7 +7642,7 @@ spare areas associated with each data page. @end itemize @end deffn -@deffn Command {nand erase} num [offset length] +@deffn {Command} {nand erase} num [offset length] @cindex NAND erasing @cindex NAND programming Erases blocks on the specified NAND device, starting at the @@ -7660,7 +7660,7 @@ For the remainder of the current server session, @command{nand info} will still report that the block ``is'' bad. @end deffn -@deffn Command {nand write} num filename offset [option...] +@deffn {Command} {nand write} num filename offset [option...] @cindex NAND writing @cindex NAND programming Writes binary data from the file into the specified NAND device, @@ -7719,7 +7719,7 @@ the underlying driver from applying hardware ECC. @end itemize @end deffn -@deffn Command {nand verify} num filename offset [option...] +@deffn {Command} {nand verify} num filename offset [option...] @cindex NAND verification @cindex NAND programming Verify the binary data in the file has been programmed to the @@ -7748,7 +7748,7 @@ be removed in a future release. @subsection Other NAND commands @cindex NAND other commands -@deffn Command {nand check_bad_blocks} num [offset length] +@deffn {Command} {nand check_bad_blocks} num [offset length] Checks for manufacturer bad block markers on the specified NAND device. If no parameters are provided, checks the whole device; otherwise, starts at the specified @var{offset} and @@ -7762,14 +7762,14 @@ with @command{nand raw_access enable} to ensure that the underlying driver will not try to apply hardware ECC. @end deffn -@deffn Command {nand info} num +@deffn {Command} {nand info} num The @var{num} parameter is the value shown by @command{nand list}. This prints the one-line summary from "nand list", plus for devices which have been probed this also prints any known status for each block. @end deffn -@deffn Command {nand raw_access} num (@option{enable}|@option{disable}) +@deffn {Command} {nand raw_access} num (@option{enable}|@option{disable}) Sets or clears an flag affecting how page I/O is done. The @var{num} parameter is the value shown by @command{nand list}. @@ -7806,23 +7806,23 @@ AT91SAM9 chips support single-bit ECC hardware. The @code{write_page} and disabled by using the @command{nand raw_access} command. There are four additional commands that are needed to fully configure the AT91SAM9 NAND controller. Two are optional; most boards use the same wiring for ALE/CLE: -@deffn Command {at91sam9 cle} num addr_line +@deffn {Command} {at91sam9 cle} num addr_line Configure the address line used for latching commands. The @var{num} parameter is the value shown by @command{nand list}. @end deffn -@deffn Command {at91sam9 ale} num addr_line +@deffn {Command} {at91sam9 ale} num addr_line Configure the address line used for latching addresses. The @var{num} parameter is the value shown by @command{nand list}. @end deffn For the next two commands, it is assumed that the pins have already been properly configured for input or output. -@deffn Command {at91sam9 rdy_busy} num pio_base_addr pin +@deffn {Command} {at91sam9 rdy_busy} num pio_base_addr pin Configure the RDY/nBUSY input from the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @end deffn -@deffn Command {at91sam9 ce} num pio_base_addr pin +@deffn {Command} {at91sam9 ce} num pio_base_addr pin Configure the chip enable input to the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @@ -7850,7 +7850,7 @@ the @command{nand raw_access} command. @deffn {NAND Driver} lpc3180 These controllers require an extra @command{nand device} parameter: the clock rate used by the controller. -@deffn Command {lpc3180 select} num [mlc|slc] +@deffn {Command} {lpc3180 select} num [mlc|slc] Configures use of the MLC or SLC controller mode. MLC implies use of hardware ECC. The @var{num} parameter is the value shown by @command{nand list}. @@ -7878,7 +7878,7 @@ main area and spare area (@option{biswap}), defaults to off. @example nand device mx35.nand mxc imx35.cpu mx35 hwecc biswap @end example -@deffn Command {mxc biswap} bank_num [enable|disable] +@deffn {Command} {mxc biswap} bank_num [enable|disable] Turns on/off bad block information swapping from main area, without parameter query status. @end deffn @@ -8047,7 +8047,7 @@ In most cases, no such restriction is listed; this indicates commands which are only available after the configuration stage has completed. @end deffn -@deffn Command sleep msec [@option{busy}] +@deffn {Command} sleep msec [@option{busy}] Wait for at least @var{msec} milliseconds before resuming. If @option{busy} is passed, busy-wait instead of sleeping. (This option is strongly discouraged.) @@ -8055,7 +8055,7 @@ Useful in connection with script files (@command{script} command and @command{target_name} configuration). @end deffn -@deffn Command shutdown [@option{error}] +@deffn {Command} shutdown [@option{error}] Close the OpenOCD server, disconnecting all clients (GDB, telnet, other). If option @option{error} is used, OpenOCD will return a non-zero exit code to the parent process. @@ -8075,7 +8075,7 @@ or its replacement will be automatically executed before OpenOCD exits. @end deffn @anchor{debuglevel} -@deffn Command debug_level [n] +@deffn {Command} debug_level [n] @cindex message level Display debug level. If @var{n} (from 0..4) is provided, then set it to that level. @@ -8091,7 +8091,7 @@ file (which is normally the server's standard output). @xref{Running}. @end deffn -@deffn Command echo [-n] message +@deffn {Command} echo [-n] message Logs a message at "user" priority. Output @var{message} to stdout. Option "-n" suppresses trailing newline. @@ -8100,16 +8100,16 @@ echo "Downloading kernel -- please wait" @end example @end deffn -@deffn Command log_output [filename | "default"] +@deffn {Command} log_output [filename | "default"] Redirect logging to @var{filename} or set it back to default output; the default log output channel is stderr. @end deffn -@deffn Command add_script_search_dir [directory] +@deffn {Command} add_script_search_dir [directory] Add @var{directory} to the file/script search path. @end deffn -@deffn Command bindto [@var{name}] +@deffn {Command} bindto [@var{name}] Specify hostname or IPv4 address on which to listen for incoming TCP/IP connections. By default, OpenOCD will listen on the loopback interface only. If your network environment is safe, @code{bindto @@ -8130,7 +8130,7 @@ various operations. The current target may be changed by using @command{targets} command with the name of the target which should become current. -@deffn Command reg [(number|name) [(value|'force')]] +@deffn {Command} reg [(number|name) [(value|'force')]] Access a single register by @var{number} or by its @var{name}. The target must generally be halted before access to CPU core registers is allowed. Depending on the hardware, some other @@ -8169,8 +8169,8 @@ Debug and trace infrastructure: @end example @end deffn -@deffn Command halt [ms] -@deffnx Command wait_halt [ms] +@deffn {Command} halt [ms] +@deffnx {Command} wait_halt [ms] The @command{halt} command first sends a halt request to the target, which @command{wait_halt} doesn't. Otherwise these behave the same: wait up to @var{ms} milliseconds, @@ -8204,22 +8204,22 @@ power consumption (because the CPU is needlessly clocked). @end deffn -@deffn Command resume [address] +@deffn {Command} resume [address] Resume the target at its current code position, or the optional @var{address} if it is provided. OpenOCD will wait 5 seconds for the target to resume. @end deffn -@deffn Command step [address] +@deffn {Command} step [address] Single-step the target at its current code position, or the optional @var{address} if it is provided. @end deffn @anchor{resetcommand} -@deffn Command reset -@deffnx Command {reset run} -@deffnx Command {reset halt} -@deffnx Command {reset init} +@deffn {Command} reset +@deffnx {Command} {reset run} +@deffnx {Command} {reset halt} +@deffnx {Command} {reset init} Perform as hard a reset as possible, using SRST if possible. @emph{All defined targets will be reset, and target events will fire during the reset sequence.} @@ -8237,7 +8237,7 @@ The other options will not work on all systems. @end itemize @end deffn -@deffn Command soft_reset_halt +@deffn {Command} soft_reset_halt Requesting target halt and executing a soft reset. This is often used when a target cannot be reset and halted. The target, after reset is released begins to execute code. OpenOCD attempts to stop the CPU and @@ -8246,8 +8246,8 @@ the code that was executed may have left the hardware in an unknown state. @end deffn -@deffn Command {adapter assert} [signal [assert|deassert signal]] -@deffnx Command {adapter deassert} [signal [assert|deassert signal]] +@deffn {Command} {adapter assert} [signal [assert|deassert signal]] +@deffnx {Command} {adapter deassert} [signal [assert|deassert signal]] Set values of reset signals. Without parameters returns current status of the signals. The @var{signal} parameter values may be @@ -8293,10 +8293,10 @@ Please use their TARGET object siblings to avoid making assumptions about what TAP is the current target, or about MMU configuration. @end enumerate -@deffn Command mdd [phys] addr [count] -@deffnx Command mdw [phys] addr [count] -@deffnx Command mdh [phys] addr [count] -@deffnx Command mdb [phys] addr [count] +@deffn {Command} mdd [phys] addr [count] +@deffnx {Command} mdw [phys] addr [count] +@deffnx {Command} mdh [phys] addr [count] +@deffnx {Command} mdb [phys] addr [count] Display contents of address @var{addr}, as 64-bit doublewords (@command{mdd}), 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), @@ -8310,10 +8310,10 @@ If @var{count} is specified, displays that many units. see the @code{mem2array} primitives.) @end deffn -@deffn Command mwd [phys] addr doubleword [count] -@deffnx Command mww [phys] addr word [count] -@deffnx Command mwh [phys] addr halfword [count] -@deffnx Command mwb [phys] addr byte [count] +@deffn {Command} mwd [phys] addr doubleword [count] +@deffnx {Command} mww [phys] addr word [count] +@deffnx {Command} mwh [phys] addr halfword [count] +@deffnx {Command} mwb [phys] addr byte [count] Writes the specified @var{doubleword} (64 bits), @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) value, at the specified address @var{addr}. @@ -8329,17 +8329,17 @@ If @var{count} is specified, fills that many units of consecutive address. @cindex image loading @cindex image dumping -@deffn Command {dump_image} filename address size +@deffn {Command} {dump_image} filename address size Dump @var{size} bytes of target memory starting at @var{address} to the binary file named @var{filename}. @end deffn -@deffn Command {fast_load} +@deffn {Command} {fast_load} Loads an image stored in memory by @command{fast_load_image} to the current target. Must be preceded by fast_load_image. @end deffn -@deffn Command {fast_load_image} filename address [@option{bin}|@option{ihex}|@option{elf}|@option{s19}] +@deffn {Command} {fast_load_image} filename address [@option{bin}|@option{ihex}|@option{elf}|@option{s19}] Normally you should be using @command{load_image} or GDB load. However, for testing purposes or when I/O overhead is significant(OpenOCD running on an embedded host), storing the image in memory and uploading the image to the target @@ -8350,7 +8350,7 @@ target programming performance as I/O and target programming can easily be profi separately. @end deffn -@deffn Command {load_image} filename address [[@option{bin}|@option{ihex}|@option{elf}|@option{s19}] @option{min_addr} @option{max_length}] +@deffn {Command} {load_image} filename address [[@option{bin}|@option{ihex}|@option{elf}|@option{s19}] @option{min_addr} @option{max_length}] Load image from file @var{filename} to target memory offset by @var{address} from its load address. The file format may optionally be specified (@option{bin}, @option{ihex}, @option{elf}, or @option{s19}). @@ -8367,7 +8367,7 @@ proc load_image_bin @{fname foffset address length @} @{ @end example @end deffn -@deffn Command {test_image} filename [address [@option{bin}|@option{ihex}|@option{elf}]] +@deffn {Command} {test_image} filename [address [@option{bin}|@option{ihex}|@option{elf}]] Displays image section sizes and addresses as if @var{filename} were loaded into target memory starting at @var{address} (defaults to zero). @@ -8375,14 +8375,14 @@ The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) @end deffn -@deffn Command {verify_image} filename address [@option{bin}|@option{ihex}|@option{elf}] +@deffn {Command} {verify_image} filename address [@option{bin}|@option{ihex}|@option{elf}] Verify @var{filename} against target memory starting at @var{address}. The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. @end deffn -@deffn Command {verify_image_checksum} filename address [@option{bin}|@option{ihex}|@option{elf}] +@deffn {Command} {verify_image_checksum} filename address [@option{bin}|@option{ihex}|@option{elf}] Verify @var{filename} against target memory starting at @var{address}. The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) @@ -8399,7 +8399,7 @@ hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. -@deffn Command {bp} [address len [@option{hw}]] +@deffn {Command} {bp} [address len [@option{hw}]] With no parameters, lists all active breakpoints. Else sets a breakpoint on code execution starting at @var{address} for @var{length} bytes. @@ -8410,15 +8410,15 @@ in which case it will be a hardware breakpoint. for similar mechanisms that do not consume hardware breakpoints.) @end deffn -@deffn Command {rbp} @option{all} | address +@deffn {Command} {rbp} @option{all} | address Remove the breakpoint at @var{address} or all breakpoints. @end deffn -@deffn Command {rwp} address +@deffn {Command} {rwp} address Remove data watchpoint on @var{address} @end deffn -@deffn Command {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]] +@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]] With no parameters, lists all active watchpoints. Else sets a data watchpoint on data from @var{address} for @var{length} bytes. The watch point is an "access" watchpoint unless @@ -8460,43 +8460,43 @@ Channels are exposed via raw TCP/IP connections. One or more RTT servers can be assigned to each channel to make them accessible to an unlimited number of TCP/IP connections. -@deffn Command {rtt setup} address size ID +@deffn {Command} {rtt setup} address size ID Configure RTT for the currently selected target. Once RTT is started, OpenOCD searches for a control block with the identifier @var{ID} starting at the memory address @var{address} within the next @var{size} bytes. @end deffn -@deffn Command {rtt start} +@deffn {Command} {rtt start} Start RTT. If the control block location is not known, OpenOCD starts searching for it. @end deffn -@deffn Command {rtt stop} +@deffn {Command} {rtt stop} Stop RTT. @end deffn -@deffn Command {rtt polling_interval [interval]} +@deffn {Command} {rtt polling_interval [interval]} Display the polling interval. If @var{interval} is provided, set the polling interval. The polling interval determines (in milliseconds) how often the up-channels are checked for new data. @end deffn -@deffn Command {rtt channels} +@deffn {Command} {rtt channels} Display a list of all channels and their properties. @end deffn -@deffn Command {rtt channellist} +@deffn {Command} {rtt channellist} Return a list of all channels and their properties as Tcl list. The list can be manipulated easily from within scripts. @end deffn -@deffn Command {rtt server start} port channel +@deffn {Command} {rtt server start} port channel Start a TCP server on @var{port} for the channel @var{channel}. @end deffn -@deffn Command {rtt server stop} port +@deffn {Command} {rtt server stop} port Stop the TCP sever with port @var{port}. @end deffn @@ -8520,7 +8520,7 @@ TCP/IP port 9090. @section Misc Commands @cindex profiling -@deffn Command {profile} seconds filename [start end] +@deffn {Command} {profile} seconds filename [start end] Profiling samples the CPU's program counter as quickly as possible, which is useful for non-intrusive stochastic profiling. Saves up to 10000 samples in @file{filename} using ``gmon.out'' @@ -8528,11 +8528,11 @@ format. Optional @option{start} and @option{end} parameters allow to limit the address range. @end deffn -@deffn Command {version} +@deffn {Command} {version} Displays a string identifying the version of this OpenOCD server. @end deffn -@deffn Command {virt2phys} virtual_address +@deffn {Command} {virt2phys} virtual_address Requests the current target to map the specified @var{virtual_address} to its corresponding physical address, and displays the result. @end deffn @@ -8641,21 +8641,21 @@ what CPU activities are traced. @end quotation @end deffn -@deffn Command {etm info} +@deffn {Command} {etm info} Displays information about the current target's ETM. This includes resource counts from the @code{ETM_CONFIG} register, as well as silicon capabilities (except on rather old modules). from the @code{ETM_SYS_CONFIG} register. @end deffn -@deffn Command {etm status} +@deffn {Command} {etm status} Displays status of the current target's ETM and trace port driver: is the ETM idle, or is it collecting data? Did trace data overflow? Was it triggered? @end deffn -@deffn Command {etm tracemode} [type context_id_bits cycle_accurate branch_output] +@deffn {Command} {etm tracemode} [type context_id_bits cycle_accurate branch_output] Displays what data that ETM will collect. If arguments are provided, first configures that data. When the configuration changes, tracing is stopped @@ -8679,7 +8679,7 @@ trace stream without an image of the code. @end itemize @end deffn -@deffn Command {etm trigger_debug} (@option{enable}|@option{disable}) +@deffn {Command} {etm trigger_debug} (@option{enable}|@option{disable}) Displays whether ETM triggering debug entry (like a breakpoint) is enabled or disabled, after optionally modifying that configuration. The default behaviour is @option{disable}. @@ -8726,28 +8726,28 @@ model with sequencer triggers which on entry and exit to the IRQ handler. At this writing, September 2009, there are no Tcl utility procedures to help set up any common tracing scenarios. -@deffn Command {etm analyze} +@deffn {Command} {etm analyze} Reads trace data into memory, if it wasn't already present. Decodes and prints the data that was collected. @end deffn -@deffn Command {etm dump} filename +@deffn {Command} {etm dump} filename Stores the captured trace data in @file{filename}. @end deffn -@deffn Command {etm image} filename [base_address] [type] +@deffn {Command} {etm image} filename [base_address] [type] Opens an image file. @end deffn -@deffn Command {etm load} filename +@deffn {Command} {etm load} filename Loads captured trace data from @file{filename}. @end deffn -@deffn Command {etm start} +@deffn {Command} {etm start} Starts trace data collection. @end deffn -@deffn Command {etm stop} +@deffn {Command} {etm stop} Stops trace data collection. @end deffn @@ -8773,7 +8773,7 @@ to use on-chip ETB memory. Associates the ETM for @var{target} with the ETB at @var{etb_tap}. You can see the ETB registers using the @command{reg} command. @end deffn -@deffn Command {etb trigger_percent} [percent] +@deffn {Command} {etb trigger_percent} [percent] This displays, or optionally changes, ETB behavior after the ETM's configured @emph{trigger} event fires. It controls how much more trace data is saved after the (single) @@ -8808,7 +8808,7 @@ CTI is mandatory for core run control and each core has an individual CTI instance attached to it. OpenOCD has limited support for CTI using the @emph{cti} group of commands. -@deffn Command {cti create} cti_name @option{-dap} dap_name @option{-ap-num} apn @option{-baseaddr} base_address +@deffn {Command} {cti create} cti_name @option{-dap} dap_name @option{-ap-num} apn @option{-baseaddr} base_address Creates a CTI instance @var{cti_name} on the DAP instance @var{dap_name} on MEM-AP @var{apn}. The @var{base_address} must match the base address of the CTI on the respective MEM-AP. All arguments are mandatory. This creates a @@ -8816,37 +8816,37 @@ new command @command{$cti_name} which is used for various purposes including additional configuration. @end deffn -@deffn Command {$cti_name enable} @option{on|off} +@deffn {Command} {$cti_name enable} @option{on|off} Enable (@option{on}) or disable (@option{off}) the CTI. @end deffn -@deffn Command {$cti_name dump} +@deffn {Command} {$cti_name dump} Displays a register dump of the CTI. @end deffn -@deffn Command {$cti_name write } @var{reg_name} @var{value} +@deffn {Command} {$cti_name write } @var{reg_name} @var{value} Write @var{value} to the CTI register with the symbolic name @var{reg_name}. @end deffn -@deffn Command {$cti_name read} @var{reg_name} +@deffn {Command} {$cti_name read} @var{reg_name} Print the value read from the CTI register with the symbolic name @var{reg_name}. @end deffn -@deffn Command {$cti_name ack} @var{event} +@deffn {Command} {$cti_name ack} @var{event} Acknowledge a CTI @var{event}. @end deffn -@deffn Command {$cti_name channel} @var{channel_number} @var{operation} +@deffn {Command} {$cti_name channel} @var{channel_number} @var{operation} Perform a specific channel operation, the possible operations are: gate, ungate, set, clear and pulse @end deffn -@deffn Command {$cti_name testmode} @option{on|off} +@deffn {Command} {$cti_name testmode} @option{on|off} Enable (@option{on}) or disable (@option{off}) the integration test mode of the CTI. @end deffn -@deffn Command {cti names} +@deffn {Command} {cti names} Prints a list of names of all CTI objects created. This command is mainly useful in TCL scripting. @end deffn @@ -8858,7 +8858,7 @@ These commands should be available on all ARM processors. They are available in addition to other core-specific commands that may be available. -@deffn Command {arm core_state} [@option{arm}|@option{thumb}] +@deffn {Command} {arm core_state} [@option{arm}|@option{thumb}] Displays the core_state, optionally changing it to process either @option{arm} or @option{thumb} instructions. The target may later be resumed in the currently set core_state. @@ -8866,7 +8866,7 @@ The target may later be resumed in the currently set core_state. that is not currently supported in OpenOCD.) @end deffn -@deffn Command {arm disassemble} address [count [@option{thumb}]] +@deffn {Command} {arm disassemble} address [count [@option{thumb}]] @cindex disassemble Disassembles @var{count} instructions starting at @var{address}. If @var{count} is not specified, a single instruction is disassembled. @@ -8884,7 +8884,7 @@ with a handful of exceptions. ThumbEE disassembly currently has no explicit support. @end deffn -@deffn Command {arm mcr} pX op1 CRn CRm op2 value +@deffn {Command} {arm mcr} pX op1 CRn CRm op2 value Write @var{value} to a coprocessor @var{pX} register passing parameters @var{CRn}, @var{CRm}, opcodes @var{opc1} and @var{opc2}, @@ -8893,7 +8893,7 @@ and using the MCR instruction. an ARM register.) @end deffn -@deffn Command {arm mrc} pX coproc op1 CRn CRm op2 +@deffn {Command} {arm mrc} pX coproc op1 CRn CRm op2 Read a coprocessor @var{pX} register passing parameters @var{CRn}, @var{CRm}, opcodes @var{opc1} and @var{opc2}, and the MRC instruction. @@ -8902,12 +8902,12 @@ Returns the result so it can be manipulated by Jim scripts. an ARM register.) @end deffn -@deffn Command {arm reg} +@deffn {Command} {arm reg} Display a table of all banked core registers, fetching the current value from every core mode if necessary. @end deffn -@deffn Command {arm semihosting} [@option{enable}|@option{disable}] +@deffn {Command} {arm semihosting} [@option{enable}|@option{disable}] @cindex ARM semihosting Display status of semihosting, after optionally changing that status. @@ -8919,7 +8919,7 @@ requests by using a special SVC instruction that is trapped at the Supervisor Call vector by OpenOCD. @end deffn -@deffn Command {arm semihosting_cmdline} [@option{enable}|@option{disable}] +@deffn {Command} {arm semihosting_cmdline} [@option{enable}|@option{disable}] @cindex ARM semihosting Set the command line to be passed to the debugger. @@ -8933,7 +8933,7 @@ standard C environment (argv[0]). Depending on the program (not much programs look at argv[0]), argv0 is ignored and can be any string. @end deffn -@deffn Command {arm semihosting_fileio} [@option{enable}|@option{disable}] +@deffn {Command} {arm semihosting_fileio} [@option{enable}|@option{disable}] @cindex ARM semihosting Display status of semihosting fileio, after optionally changing that status. @@ -8944,7 +8944,7 @@ interacting with remote files or displaying console messages in the debugger. @end deffn -@deffn Command {arm semihosting_resexit} [@option{enable}|@option{disable}] +@deffn {Command} {arm semihosting_resexit} [@option{enable}|@option{disable}] @cindex ARM semihosting Enable resumable SEMIHOSTING_SYS_EXIT. @@ -8986,7 +8986,7 @@ ARM9TDMI, ARM920T or ARM926EJ-S. They are available in addition to the ARM commands, and any other core-specific commands that may be available. -@deffn Command {arm7_9 dbgrq} [@option{enable}|@option{disable}] +@deffn {Command} {arm7_9 dbgrq} [@option{enable}|@option{disable}] Displays the value of the flag controlling use of the EmbeddedIce DBGRQ signal to force entry into debug mode, instead of breakpoints. @@ -8998,7 +8998,7 @@ This feature is enabled by default on most ARM9 cores, including ARM9TDMI, ARM920T, and ARM926EJ-S. @end deffn -@deffn Command {arm7_9 dcc_downloads} [@option{enable}|@option{disable}] +@deffn {Command} {arm7_9 dcc_downloads} [@option{enable}|@option{disable}] @cindex DCC Displays the value of the flag controlling use of the debug communications channel (DCC) to write larger (>128 byte) amounts of memory. @@ -9009,7 +9009,7 @@ unsafe, especially with targets running at very low speeds. This command was int with OpenOCD rev. 60, and requires a few bytes of working area. @end deffn -@deffn Command {arm7_9 fast_memory_access} [@option{enable}|@option{disable}] +@deffn {Command} {arm7_9 fast_memory_access} [@option{enable}|@option{disable}] Displays the value of the flag controlling use of memory writes and reads that don't check completion of the operation. If a boolean parameter is provided, first assigns that flag. @@ -9032,7 +9032,7 @@ Such cores include the ARM920T, ARM926EJ-S, and ARM966. @c versions have different rules about when they commit writes. @anchor{arm9vectorcatch} -@deffn Command {arm9 vector_catch} [@option{all}|@option{none}|list] +@deffn {Command} {arm9 vector_catch} [@option{all}|@option{none}|list] @cindex vector_catch Vector Catch hardware provides a sort of dedicated breakpoint for hardware events such as reset, interrupt, and abort. @@ -9059,12 +9059,12 @@ built using the ARM9TDMI integer core. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. -@deffn Command {arm920t cache_info} +@deffn {Command} {arm920t cache_info} Print information about the caches found. This allows to see whether your target is an ARM920T (2x16kByte cache) or ARM922T (2x8kByte cache). @end deffn -@deffn Command {arm920t cp15} regnum [value] +@deffn {Command} {arm920t cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. This uses "physical access" and the register number is as @@ -9072,11 +9072,11 @@ shown in bits 38..33 of table 9-9 in the ARM920T TRM. (Not all registers can be written.) @end deffn -@deffn Command {arm920t read_cache} filename +@deffn {Command} {arm920t read_cache} filename Dump the content of ICache and DCache to a file named @file{filename}. @end deffn -@deffn Command {arm920t read_mmu} filename +@deffn {Command} {arm920t read_mmu} filename Dump the content of the ITLB and DTLB to a file named @file{filename}. @end deffn @@ -9092,7 +9092,7 @@ and ARM9 commands. The Feroceon cores also support these commands, although they are not built from ARM926ej-s designs. -@deffn Command {arm926ejs cache_info} +@deffn {Command} {arm926ejs cache_info} Print information about the caches found. @end deffn @@ -9104,7 +9104,7 @@ which are implementations of the ARMv5TE architecture. They are available in addition to the ARM, ARM7/ARM9, and ARM9 commands. -@deffn Command {arm966e cp15} regnum [value] +@deffn {Command} {arm966e cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. The six bit @var{regnum} values are bits 37..32 from table 7-2 of the @@ -9192,50 +9192,50 @@ length of four, or one watchpoint with a length greater than four. These commands are available to XScale based CPUs, which are implementations of the ARMv5TE architecture. -@deffn Command {xscale analyze_trace} +@deffn {Command} {xscale analyze_trace} Displays the contents of the trace buffer. @end deffn -@deffn Command {xscale cache_clean_address} address +@deffn {Command} {xscale cache_clean_address} address Changes the address used when cleaning the data cache. @end deffn -@deffn Command {xscale cache_info} +@deffn {Command} {xscale cache_info} Displays information about the CPU caches. @end deffn -@deffn Command {xscale cp15} regnum [value] +@deffn {Command} {xscale cp15} regnum [value] Display cp15 register @var{regnum}; else if a @var{value} is provided, that value is written to that register. @end deffn -@deffn Command {xscale debug_handler} target address +@deffn {Command} {xscale debug_handler} target address Changes the address used for the specified target's debug handler. @end deffn -@deffn Command {xscale dcache} [@option{enable}|@option{disable}] +@deffn {Command} {xscale dcache} [@option{enable}|@option{disable}] Enables or disable the CPU's data cache. @end deffn -@deffn Command {xscale dump_trace} filename +@deffn {Command} {xscale dump_trace} filename Dumps the raw contents of the trace buffer to @file{filename}. @end deffn -@deffn Command {xscale icache} [@option{enable}|@option{disable}] +@deffn {Command} {xscale icache} [@option{enable}|@option{disable}] Enables or disable the CPU's instruction cache. @end deffn -@deffn Command {xscale mmu} [@option{enable}|@option{disable}] +@deffn {Command} {xscale mmu} [@option{enable}|@option{disable}] Enables or disable the CPU's memory management unit. @end deffn -@deffn Command {xscale trace_buffer} [@option{enable}|@option{disable} [@option{fill} [n] | @option{wrap}]] +@deffn {Command} {xscale trace_buffer} [@option{enable}|@option{disable} [@option{fill} [n] | @option{wrap}]] Displays the trace buffer status, after optionally enabling or disabling the trace buffer and modifying how it is emptied. @end deffn -@deffn Command {xscale trace_image} filename [offset [type]] +@deffn {Command} {xscale trace_image} filename [offset [type]] Opens a trace image from @file{filename}, optionally rebasing its segment addresses by @var{offset}. The image @var{type} may be one of @@ -9245,7 +9245,7 @@ The image @var{type} may be one of @end deffn @anchor{xscalevectorcatch} -@deffn Command {xscale vector_catch} [mask] +@deffn {Command} {xscale vector_catch} [mask] @cindex vector_catch Display a bitmask showing the hardware vectors to catch. If the optional parameter is provided, first set the bitmask to that value. @@ -9263,7 +9263,7 @@ The mask bits correspond with bit 16..23 in the DCSR: @end example @end deffn -@deffn Command {xscale vector_table} [(@option{low}|@option{high}) index value] +@deffn {Command} {xscale vector_table} [(@option{low}|@option{high}) index value] @cindex vector_table Set an entry in the mini-IC vector table. There are two tables: one for @@ -9282,7 +9282,7 @@ Without arguments, the current settings are displayed. @subsection ARM11 specific commands @cindex ARM11 -@deffn Command {arm11 memwrite burst} [@option{enable}|@option{disable}] +@deffn {Command} {arm11 memwrite burst} [@option{enable}|@option{disable}] Displays the value of the memwrite burst-enable flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. @@ -9293,21 +9293,21 @@ instead of polling for a status flag to verify that completion. This is usually safe, because JTAG runs much slower than the CPU. @end deffn -@deffn Command {arm11 memwrite error_fatal} [@option{enable}|@option{disable}] +@deffn {Command} {arm11 memwrite error_fatal} [@option{enable}|@option{disable}] Displays the value of the memwrite error_fatal flag, which is enabled by default. If a boolean parameter is provided, first assigns that flag. When set, certain memory write errors cause earlier transfer termination. @end deffn -@deffn Command {arm11 step_irq_enable} [@option{enable}|@option{disable}] +@deffn {Command} {arm11 step_irq_enable} [@option{enable}|@option{disable}] Displays the value of the flag controlling whether IRQs are enabled during single stepping; they are disabled by default. If a boolean parameter is provided, first assigns that. @end deffn -@deffn Command {arm11 vcr} [value] +@deffn {Command} {arm11 vcr} [value] @cindex vector_catch Displays the value of the @emph{Vector Catch Register (VCR)}, coprocessor 14 register 7. @@ -9327,39 +9327,39 @@ cores @emph{except the ARM1176} use the same six bits. @subsection ARMv7-A specific commands @cindex Cortex-A -@deffn Command {cortex_a cache_info} +@deffn {Command} {cortex_a cache_info} display information about target caches @end deffn -@deffn Command {cortex_a dacrfixup [@option{on}|@option{off}]} +@deffn {Command} {cortex_a dacrfixup [@option{on}|@option{off}]} Work around issues with software breakpoints when the program text is mapped read-only by the operating system. This option sets the CP15 DACR to "all-manager" to bypass MMU permission checks on memory access. Defaults to 'off'. @end deffn -@deffn Command {cortex_a dbginit} +@deffn {Command} {cortex_a dbginit} Initialize core debug Enables debug by unlocking the Software Lock and clearing sticky powerdown indications @end deffn -@deffn Command {cortex_a smp} [on|off] +@deffn {Command} {cortex_a smp} [on|off] Display/set the current SMP mode @end deffn -@deffn Command {cortex_a smp_gdb} [core_id] +@deffn {Command} {cortex_a smp_gdb} [core_id] Display/set the current core displayed in GDB @end deffn -@deffn Command {cortex_a maskisr} [@option{on}|@option{off}] +@deffn {Command} {cortex_a maskisr} [@option{on}|@option{off}] Selects whether interrupts will be processed when single stepping @end deffn -@deffn Command {cache_config l2x} [base way] +@deffn {Command} {cache_config l2x} [base way] configure l2x cache @end deffn -@deffn Command {cortex_a mmu dump} [@option{0}|@option{1}|@option{addr} address [@option{num_entries}]] +@deffn {Command} {cortex_a mmu dump} [@option{0}|@option{1}|@option{addr} address [@option{num_entries}]] Dump the MMU translation table from TTB0 or TTB1 register, or from physical memory location @var{address}. When dumping the table from @var{address}, print at most @var{num_entries} page table entries. @var{num_entries} is optional, if omitted, the maximum @@ -9369,12 +9369,12 @@ possible (4096) entries are printed. @subsection ARMv7-R specific commands @cindex Cortex-R -@deffn Command {cortex_r dbginit} +@deffn {Command} {cortex_r dbginit} Initialize core debug Enables debug by unlocking the Software Lock and clearing sticky powerdown indications @end deffn -@deffn Command {cortex_r maskisr} [@option{on}|@option{off}] +@deffn {Command} {cortex_r maskisr} [@option{on}|@option{off}] Selects whether interrupts will be processed when single stepping @end deffn @@ -9401,12 +9401,12 @@ The @command{tpiu} is used for either TPIU or SWO. A convenient alias @command{swo} is available to help distinguish, in scripts, the commands for SWO from the commands for TPIU. -@deffn Command {swo} ... +@deffn {Command} {swo} ... Alias of @command{tpiu ...}. Can be used in scripts to distinguish the commands for SWO from the commands for TPIU. @end deffn -@deffn Command {tpiu create} tpiu_name configparams... +@deffn {Command} {tpiu create} tpiu_name configparams... Creates a TPIU or a SWO object. The two commands are equivalent. Add the object in a list and add new commands (@command{@var{tpiu_name}}) which are used for various purposes including additional configuration. @@ -9422,23 +9422,23 @@ You @emph{must} set here the AP and MEM_AP base_address through @code{-dap @var{ @end itemize @end deffn -@deffn Command {tpiu names} +@deffn {Command} {tpiu names} Lists all the TPIU or SWO objects created so far. The two commands are equivalent. @end deffn -@deffn Command {tpiu init} +@deffn {Command} {tpiu init} Initialize all registered TPIU and SWO. The two commands are equivalent. These commands are used internally during initialization. They can be issued at any time after the initialization, too. @end deffn -@deffn Command {$tpiu_name cget} queryparm +@deffn {Command} {$tpiu_name cget} queryparm Each configuration parameter accepted by @command{$tpiu_name configure} can be individually queried, to return its current value. The @var{queryparm} is a parameter name accepted by that command, such as @code{-dap}. @end deffn -@deffn Command {$tpiu_name configure} configparams... +@deffn {Command} {$tpiu_name configure} configparams... The options accepted by this command may also be specified as parameters to @command{tpiu create}. Their values can later be queried one at a time by using the @command{$tpiu_name cget} command. @@ -9504,7 +9504,7 @@ default value is @var{0}. @end itemize @end deffn -@deffn Command {$tpiu_name enable} +@deffn {Command} {$tpiu_name enable} Uses the parameters specified by the previous @command{$tpiu_name configure} to configure and enable the TPIU or the SWO. If required, the adapter is also configured and enabled to receive the trace @@ -9513,7 +9513,7 @@ This command can be used before @command{init}, but it will take effect only after the @command{init}. @end deffn -@deffn Command {$tpiu_name disable} +@deffn {Command} {$tpiu_name disable} Disable the TPIU or the SWO, terminating the receiving of the trace data. @end deffn @@ -9561,19 +9561,19 @@ openocd -f interface/stlink.cfg \ @cindex ITM @cindex ETM -@deffn Command {itm port} @var{port} (@option{0}|@option{1}|@option{on}|@option{off}) +@deffn {Command} {itm port} @var{port} (@option{0}|@option{1}|@option{on}|@option{off}) Enable or disable trace output for ITM stimulus @var{port} (counting from 0). Port 0 is enabled on target creation automatically. @end deffn -@deffn Command {itm ports} (@option{0}|@option{1}|@option{on}|@option{off}) +@deffn {Command} {itm ports} (@option{0}|@option{1}|@option{on}|@option{off}) Enable or disable trace output for all ITM stimulus ports. @end deffn @subsection Cortex-M specific commands @cindex Cortex-M -@deffn Command {cortex_m maskisr} (@option{auto}|@option{on}|@option{off}|@option{steponly}) +@deffn {Command} {cortex_m maskisr} (@option{auto}|@option{on}|@option{off}|@option{steponly}) Control masking (disabling) interrupts during target step/resume. The @option{auto} option handles interrupts during stepping in a way that they @@ -9596,7 +9596,7 @@ does. Default is @option{auto}. @end deffn -@deffn Command {cortex_m vector_catch} [@option{all}|@option{none}|list] +@deffn {Command} {cortex_m vector_catch} [@option{all}|@option{none}|list] @cindex vector_catch Vector Catch hardware provides dedicated breakpoints for certain hardware events. @@ -9623,7 +9623,7 @@ must also be explicitly enabled. This finishes by listing the current vector catch configuration. @end deffn -@deffn Command {cortex_m reset_config} (@option{sysresetreq}|@option{vectreset}) +@deffn {Command} {cortex_m reset_config} (@option{sysresetreq}|@option{vectreset}) Control reset handling if hardware srst is not fitted @xref{reset_config,,reset_config}. @@ -9646,11 +9646,11 @@ instead. @cindex ARMv8-A @cindex aarch64 -@deffn Command {aarch64 cache_info} +@deffn {Command} {aarch64 cache_info} Display information about target caches @end deffn -@deffn Command {aarch64 dbginit} +@deffn {Command} {aarch64 dbginit} This command enables debugging by clearing the OS Lock and sticky power-down and reset indications. It also establishes the expected, basic cross-trigger configuration the aarch64 target code relies on. In a configuration file, the command would typically be called from a @@ -9658,25 +9658,25 @@ target code relies on. In a configuration file, the command would typically be c However, normally it is not necessary to use the command at all. @end deffn -@deffn Command {aarch64 disassemble} address [count] +@deffn {Command} {aarch64 disassemble} address [count] @cindex disassemble Disassembles @var{count} instructions starting at @var{address}. If @var{count} is not specified, a single instruction is disassembled. @end deffn -@deffn Command {aarch64 smp} [on|off] +@deffn {Command} {aarch64 smp} [on|off] Display, enable or disable SMP handling mode. The state of SMP handling influences the way targets in an SMP group are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger halting or resuming of all cores in the group. The command @code{target smp} defines which targets are in the SMP group. With SMP handling disabled, all targets need to be treated individually. @end deffn -@deffn Command {aarch64 maskisr} [@option{on}|@option{off}] +@deffn {Command} {aarch64 maskisr} [@option{on}|@option{off}] Selects whether interrupts will be processed when single stepping. The default configuration is @option{on}. @end deffn -@deffn Command {$target_name catch_exc} [@option{off}|@option{sec_el1}|@option{sec_el3}|@option{nsec_el1}|@option{nsec_el2}]+ +@deffn {Command} {$target_name catch_exc} [@option{off}|@option{sec_el1}|@option{sec_el3}|@option{nsec_el1}|@option{nsec_el2}]+ Cause @command{$target_name} to halt when an exception is taken. Any combination of Secure (sec) EL1/EL3 or Non-Secure (nsec) EL1/EL2 is valid. The target @command{$target_name} will halt before taking the exception. In order to resume @@ -9691,12 +9691,12 @@ provided by EnSilica. (See: @url{http://www.ensilica.com/risc-ip/}.) @subsection eSi-RISC Configuration -@deffn Command {esirisc cache_arch} (@option{harvard}|@option{von_neumann}) +@deffn {Command} {esirisc cache_arch} (@option{harvard}|@option{von_neumann}) Configure the caching architecture. Targets with the @code{UNIFIED_ADDRESS_SPACE} option disabled employ a Harvard architecture. By default, @option{von_neumann} is assumed. @end deffn -@deffn Command {esirisc hwdc} (@option{all}|@option{none}|mask ...) +@deffn {Command} {esirisc hwdc} (@option{all}|@option{none}|mask ...) Configure hardware debug control. The HWDC register controls which exceptions return control back to the debugger. Possible masks are @option{all}, @option{none}, @option{reset}, @option{interrupt}, @option{syscall}, @option{error}, and @option{debug}. @@ -9705,7 +9705,7 @@ By default, @option{reset}, @option{error}, and @option{debug} are enabled. @subsection eSi-RISC Operation -@deffn Command {esirisc flush_caches} +@deffn {Command} {esirisc flush_caches} Flush instruction and data caches. This command requires that the target is halted when the command is issued and configured with an instruction or data cache. @end deffn @@ -9736,22 +9736,22 @@ managed by enabling flow control, however this can impact timing-sensitive software operation on the CPU. @end quotation -@deffn Command {esirisc trace buffer} address size [@option{wrap}] +@deffn {Command} {esirisc trace buffer} address size [@option{wrap}] Configure trace buffer using the provided address and size. If the @option{wrap} option is specified, trace collection will continue once the end of the buffer is reached. By default, wrap is disabled. @end deffn -@deffn Command {esirisc trace fifo} address +@deffn {Command} {esirisc trace fifo} address Configure trace FIFO using the provided address. @end deffn -@deffn Command {esirisc trace flow_control} (@option{enable}|@option{disable}) +@deffn {Command} {esirisc trace flow_control} (@option{enable}|@option{disable}) Enable or disable stalling the CPU to collect trace data. By default, flow control is disabled. @end deffn -@deffn Command {esirisc trace format} (@option{full}|@option{branch}|@option{icache}) pc_bits +@deffn {Command} {esirisc trace format} (@option{full}|@option{branch}|@option{icache}) pc_bits Configure trace format and number of PC bits to be captured. @option{pc_bits} must be within 1 and 31 as the LSB is not collected. If external tooling is used to analyze collected trace data, these values must match. @@ -9766,7 +9766,7 @@ addresses. @end itemize @end deffn -@deffn Command {esirisc trace trigger start} (@option{condition}) [start_data start_mask] +@deffn {Command} {esirisc trace trigger start} (@option{condition}) [start_data start_mask] Configure trigger start condition using the provided start data and mask. A brief description of each condition is provided below; for more detail on how these values are used, see the eSi-RISC Architecture Manual. @@ -9789,7 +9789,7 @@ data and mask. @end itemize @end deffn -@deffn Command {esirisc trace trigger stop} (@option{condition}) [stop_data stop_mask] +@deffn {Command} {esirisc trace trigger stop} (@option{condition}) [stop_data stop_mask] Configure trigger stop condition using the provided stop data and mask. A brief description of each condition is provided below; for more detail on how these values are used, see the eSi-RISC Architecture Manual. @@ -9810,7 +9810,7 @@ data and mask. @end itemize @end deffn -@deffn Command {esirisc trace trigger delay} (@option{trigger}) [cycles] +@deffn {Command} {esirisc trace trigger delay} (@option{trigger}) [cycles] Configure trigger start/stop delay in clock cycles. Supported triggers: @@ -9825,36 +9825,36 @@ collection. @subsection eSi-Trace Operation -@deffn Command {esirisc trace init} +@deffn {Command} {esirisc trace init} Initialize trace collection. This command must be called any time the configuration changes. If a trace buffer has been configured, the contents will be overwritten when trace collection starts. @end deffn -@deffn Command {esirisc trace info} +@deffn {Command} {esirisc trace info} Display trace configuration. @end deffn -@deffn Command {esirisc trace status} +@deffn {Command} {esirisc trace status} Display trace collection status. @end deffn -@deffn Command {esirisc trace start} +@deffn {Command} {esirisc trace start} Start manual trace collection. @end deffn -@deffn Command {esirisc trace stop} +@deffn {Command} {esirisc trace stop} Stop manual trace collection. @end deffn -@deffn Command {esirisc trace analyze} [address size] +@deffn {Command} {esirisc trace analyze} [address size] Analyze collected trace data. This command may only be used if a trace buffer has been configured. If a trace FIFO has been configured, trace data must be copied to an in-memory buffer identified by the @option{address} and @option{size} options using DMA. @end deffn -@deffn Command {esirisc trace dump} [address size] @file{filename} +@deffn {Command} {esirisc trace dump} [address size] @file{filename} Dump collected trace data to file. This command may only be used if a trace buffer has been configured. If a trace FIFO has been configured, trace data must be copied to an in-memory buffer identified by the @option{address} and @@ -9878,27 +9878,27 @@ Useful docs are here: https://communities.intel.com/community/makers/documentati The three main address spaces for x86 are memory, I/O and configuration space. These commands allow a user to read and write to the 64Kbyte I/O address space. -@deffn Command {x86_32 idw} address +@deffn {Command} {x86_32 idw} address Display the contents of a 32-bit I/O port from address range 0x0000 - 0xffff. @end deffn -@deffn Command {x86_32 idh} address +@deffn {Command} {x86_32 idh} address Display the contents of a 16-bit I/O port from address range 0x0000 - 0xffff. @end deffn -@deffn Command {x86_32 idb} address +@deffn {Command} {x86_32 idb} address Display the contents of a 8-bit I/O port from address range 0x0000 - 0xffff. @end deffn -@deffn Command {x86_32 iww} address +@deffn {Command} {x86_32 iww} address Write the contents of a 32-bit I/O port to address range 0x0000 - 0xffff. @end deffn -@deffn Command {x86_32 iwh} address +@deffn {Command} {x86_32 iwh} address Write the contents of a 16-bit I/O port to address range 0x0000 - 0xffff. @end deffn -@deffn Command {x86_32 iwb} address +@deffn {Command} {x86_32 iwb} address Write the contents of a 8-bit I/O port to address range 0x0000 - 0xffff. @end deffn @@ -9908,10 +9908,10 @@ The OpenRISC CPU is a soft core. It is used in a programmable SoC which can be configured with any of the TAP / Debug Unit available. @subsection TAP and Debug Unit selection commands -@deffn Command {tap_select} (@option{vjtag}|@option{mohor}|@option{xilinx_bscan}) +@deffn {Command} {tap_select} (@option{vjtag}|@option{mohor}|@option{xilinx_bscan}) Select between the Altera Virtual JTAG , Xilinx Virtual JTAG and Mohor TAP. @end deffn -@deffn Command {du_select} (@option{adv}|@option{mohor}) [option] +@deffn {Command} {du_select} (@option{adv}|@option{mohor}) [option] Select between the Advanced Debug Interface and the classic one. An option can be passed as a second argument to the debug unit. @@ -9922,7 +9922,7 @@ between bytes while doing read or write bursts. @end deffn @subsection Registers commands -@deffn Command {addreg} [name] [address] [feature] [reg_group] +@deffn {Command} {addreg} [name] [address] [feature] [reg_group] Add a new register in the cpu register list. This register will be included in the generated target descriptor file. @@ -9939,7 +9939,7 @@ addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system @end deffn -@deffn Command {readgroup} (@option{group}) +@deffn {Command} {readgroup} (@option{group}) Display all registers in @emph{group}. @emph{group} can be "system", @@ -9964,7 +9964,7 @@ OpenOCD exposes each hart as a separate core. @subsection RISC-V Debug Configuration Commands -@deffn Command {riscv expose_csrs} n0[-m0][,n1[-m1]]... +@deffn {Command} {riscv expose_csrs} n0[-m0][,n1[-m1]]... Configure a list of inclusive ranges for CSRs to expose in addition to the standard ones. This must be executed before `init`. @@ -9974,7 +9974,7 @@ command can be used if OpenOCD gets this wrong, or a target implements custom CSRs. @end deffn -@deffn Command {riscv expose_custom} n0[-m0][,n1[-m1]]... +@deffn {Command} {riscv expose_custom} n0[-m0][,n1[-m1]]... The RISC-V Debug Specification allows targets to expose custom registers through abstract commands. (See Section 3.5.1.1 in that document.) This command configures a list of inclusive ranges of those registers to expose. Number 0 @@ -9982,39 +9982,39 @@ indicates the first custom register, whose abstract command number is 0xc000. This command must be executed before `init`. @end deffn -@deffn Command {riscv set_command_timeout_sec} [seconds] +@deffn {Command} {riscv set_command_timeout_sec} [seconds] Set the wall-clock timeout (in seconds) for individual commands. The default should work fine for all but the slowest targets (eg. simulators). @end deffn -@deffn Command {riscv set_reset_timeout_sec} [seconds] +@deffn {Command} {riscv set_reset_timeout_sec} [seconds] Set the maximum time to wait for a hart to come out of reset after reset is deasserted. @end deffn -@deffn Command {riscv set_scratch_ram} none|[address] +@deffn {Command} {riscv set_scratch_ram} none|[address] Set the address of 16 bytes of scratch RAM the debugger can use, or 'none'. This is used to access 64-bit floating point registers on 32-bit targets. @end deffn -@deffn Command {riscv set_prefer_sba} on|off +@deffn {Command} {riscv set_prefer_sba} on|off When on, prefer to use System Bus Access to access memory. When off (default), prefer to use the Program Buffer to access memory. @end deffn -@deffn Command {riscv set_enable_virtual} on|off +@deffn {Command} {riscv set_enable_virtual} on|off When on, memory accesses are performed on physical or virtual memory depending on the current system configuration. When off (default), all memory accessses are performed on physical memory. @end deffn -@deffn Command {riscv set_enable_virt2phys} on|off +@deffn {Command} {riscv set_enable_virt2phys} on|off When on (default), memory accesses are performed on physical or virtual memory depending on the current satp configuration. When off, all memory accessses are performed on physical memory. @end deffn -@deffn Command {riscv resume_order} normal|reversed +@deffn {Command} {riscv resume_order} normal|reversed Some software assumes all harts are executing nearly continuously. Such software may be sensitive to the order that harts are resumed in. On harts that don't support hasel, this option allows the user to choose the order the @@ -10025,7 +10025,7 @@ Normal order is from lowest hart index to highest. This is the default behavior. Reversed order is from highest hart index to lowest. @end deffn -@deffn Command {riscv set_ir} (@option{idcode}|@option{dtmcs}|@option{dmi}) [value] +@deffn {Command} {riscv set_ir} (@option{idcode}|@option{dtmcs}|@option{dmi}) [value] Set the IR value for the specified JTAG register. This is useful, for example, when using the existing JTAG interface on a Xilinx FPGA by way of BSCANE2 primitives that only permit a limited selection of IR @@ -10036,22 +10036,22 @@ When utilizing version 0.11 of the RISC-V Debug Specification, and DBUS registers, respectively. @end deffn -@deffn Command {riscv use_bscan_tunnel} value +@deffn {Command} {riscv use_bscan_tunnel} value Enable or disable use of a BSCAN tunnel to reach DM. Supply the width of the DM transport TAP's instruction register to enable. Supply a value of 0 to disable. @end deffn -@deffn Command {riscv set_ebreakm} on|off +@deffn {Command} {riscv set_ebreakm} on|off Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to OpenOCD. When off, they generate a breakpoint exception handled internally. @end deffn -@deffn Command {riscv set_ebreaks} on|off +@deffn {Command} {riscv set_ebreaks} on|off Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to OpenOCD. When off, they generate a breakpoint exception handled internally. @end deffn -@deffn Command {riscv set_ebreaku} on|off +@deffn {Command} {riscv set_ebreaku} on|off Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to OpenOCD. When off, they generate a breakpoint exception handled internally. @end deffn @@ -10066,11 +10066,11 @@ set challenge [riscv authdata_read] riscv authdata_write [expr $challenge + 1] @end example -@deffn Command {riscv authdata_read} +@deffn {Command} {riscv authdata_read} Return the 32-bit value read from authdata. @end deffn -@deffn Command {riscv authdata_write} value +@deffn {Command} {riscv authdata_write} value Write the 32-bit value to authdata. @end deffn @@ -10079,11 +10079,11 @@ Write the 32-bit value to authdata. The following commands allow direct access to the Debug Module Interface, which can be used to interact with custom debug features. -@deffn Command {riscv dmi_read} address +@deffn {Command} {riscv dmi_read} address Perform a 32-bit DMI read at address, returning the value. @end deffn -@deffn Command {riscv dmi_write} address value +@deffn {Command} {riscv dmi_write} address value Perform a 32-bit DMI write of value at address. @end deffn @@ -10275,7 +10275,7 @@ This is not the same format used by @file{libdcc}. Other software, such as the U-Boot boot loader, sometimes does the same thing. -@deffn Command {target_request debugmsgs} [@option{enable}|@option{disable}|@option{charmsg}] +@deffn {Command} {target_request debugmsgs} [@option{enable}|@option{disable}|@option{charmsg}] Displays current handling of target DCC message requests. These messages may be sent to the debugger while the target is running. The optional @option{enable} and @option{charmsg} parameters @@ -10286,7 +10286,7 @@ as used by Linux with CONFIG_DEBUG_ICEDCC; otherwise the libdcc format is used. @end deffn -@deffn Command {trace history} [@option{clear}|count] +@deffn {Command} {trace history} [@option{clear}|count] With no parameter, displays all the trace points that have triggered in the order they triggered. With the parameter @option{clear}, erases all current trace history records. @@ -10294,7 +10294,7 @@ With a @var{count} parameter, allocates space for that many history records. @end deffn -@deffn Command {trace point} [@option{clear}|identifier] +@deffn {Command} {trace point} [@option{clear}|identifier] With no parameter, displays all trace point identifiers and how many times they have been triggered. With the parameter @option{clear}, erases all current trace point counters. @@ -10348,7 +10348,7 @@ JTAG router), you probably won't need to use these commands. In a debug session that doesn't use JTAG for its transport protocol, these commands are not available. -@deffn Command {drscan} tap [numbits value]+ [@option{-endstate} tap_state] +@deffn {Command} {drscan} tap [numbits value]+ [@option{-endstate} tap_state] Loads the data register of @var{tap} with a series of bit fields that specify the entire register. Each field is @var{numbits} bits long with @@ -10383,7 +10383,7 @@ the register accessed by the INTEST instruction @end quotation @end deffn -@deffn Command {flush_count} +@deffn {Command} {flush_count} Returns the number of times the JTAG queue has been flushed. This may be used for performance tuning. @@ -10395,7 +10395,7 @@ tasks which waste bandwidth by flushing small transfers too often, instead of batching them into larger operations. @end deffn -@deffn Command {irscan} [tap instruction]+ [@option{-endstate} tap_state] +@deffn {Command} {irscan} [tap instruction]+ [@option{-endstate} tap_state] For each @var{tap} listed, loads the instruction register with its associated numeric @var{instruction}. (The number of bits in that instruction may be displayed @@ -10416,7 +10416,7 @@ portable scripts currently must issue only BYPASS instructions. @end quotation @end deffn -@deffn Command {pathmove} start_state [next_state ...] +@deffn {Command} {pathmove} start_state [next_state ...] Start by moving to @var{start_state}, which must be one of the @emph{stable} states. Unless it is the only state given, this will often be the @@ -10427,7 +10427,7 @@ each @var{next_state} in sequence, one per TCK cycle. The final state must also be stable. @end deffn -@deffn Command {runtest} @var{num_cycles} +@deffn {Command} {runtest} @var{num_cycles} Move to the @sc{run/idle} state, and execute at least @var{num_cycles} of the JTAG clock (TCK). Instructions often need some time @@ -10437,14 +10437,14 @@ to execute before they take effect. @c tms_sequence (short|long) @c ... temporary, debug-only, other than USBprog bug workaround... -@deffn Command {verify_ircapture} (@option{enable}|@option{disable}) +@deffn {Command} {verify_ircapture} (@option{enable}|@option{disable}) Verify values captured during @sc{ircapture} and returned during IR scans. Default is enabled, but this can be overridden by @command{verify_jtag}. This flag is ignored when validating JTAG chain configuration. @end deffn -@deffn Command {verify_jtag} (@option{enable}|@option{disable}) +@deffn {Command} {verify_jtag} (@option{enable}|@option{disable}) Enables verification of DR and IR scans, to help detect programming errors. For IR scans, @command{verify_ircapture} must also be enabled. @@ -10518,7 +10518,7 @@ way to represent JTAG test patterns in text files. In a debug session using JTAG for its transport protocol, OpenOCD supports running such test files. -@deffn Command {svf} @file{filename} [@option{-tap @var{tapname}}] [@option{[-]quiet}] @ +@deffn {Command} {svf} @file{filename} [@option{-tap @var{tapname}}] [@option{[-]quiet}] @ [@option{[-]nil}] [@option{[-]progress}] [@option{[-]ignore_error}] This issues a JTAG reset (Test-Logic-Reset) and then runs the SVF script from @file{filename}. @@ -10555,7 +10555,7 @@ OpenOCD supports running such test files. Not all XSVF commands are supported. @end quotation -@deffn Command {xsvf} (tapname|@option{plain}) filename [@option{virt2}] [@option{quiet}] +@deffn {Command} {xsvf} (tapname|@option{plain}) filename [@option{virt2}] [@option{quiet}] This issues a JTAG reset (Test-Logic-Reset) and then runs the XSVF script from @file{filename}. When a @var{tapname} is specified, the commands are directed at @@ -10613,24 +10613,24 @@ source [find tools/memtest.tcl] to get access to the following facilities: -@deffn Command {memTestDataBus} address +@deffn {Command} {memTestDataBus} address Test the data bus wiring in a memory region by performing a walking 1's test at a fixed address within that region. @end deffn -@deffn Command {memTestAddressBus} baseaddress size +@deffn {Command} {memTestAddressBus} baseaddress size Perform a walking 1's test on the relevant bits of the address and check for aliasing. This test will find single-bit address failures such as stuck-high, stuck-low, and shorted pins. @end deffn -@deffn Command {memTestDevice} baseaddress size +@deffn {Command} {memTestDevice} baseaddress size Test the integrity of a physical memory device by performing an increment/decrement test over the entire region. In the process every storage bit in the device is tested as zero and as one. @end deffn -@deffn Command {runAllMemTests} baseaddress size +@deffn {Command} {runAllMemTests} baseaddress size Run all of the above tests over a specified memory region. @end deffn From d4eecfaab57db2a3dbbd4ecdc713ffe61a07d6d8 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 6 Apr 2021 23:31:32 +0200 Subject: [PATCH 03/58] doc: [2/3] uniform the texinfo syntax for commands definition To avoid errors in the documentation, like the one fixed by change http://openocd.zylin.com/6134/ , use a uniform notation across the file so simple copy-paste will work. Enclose every Command within curly-brackets '{...}', even single word commands. Patch generated through: sed -i 's/^\(@deffn {Command} \)\([^{][^ ]*\)/\1{\2}/' doc/openocd.texi sed -i 's/^\(@deffnx {Command} \)\([^{][^ ]*\)/\1{\2}/' doc/openocd.texi Change-Id: I797e8d9f5ab0aa1936f350b340d3bdd52373f5aa Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6151 Tested-by: jenkins --- doc/openocd.texi | 72 ++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 247938fae..8b4113aac 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2115,7 +2115,7 @@ If you disable all access through TCP/IP, you will need to use the command line @option{-pipe} option. @anchor{gdb_port} -@deffn {Command} gdb_port [number] +@deffn {Command} {gdb_port} [number] @cindex GDB server Normally gdb listens to a TCP/IP port, but GDB can also communicate via pipes(stdin/out or named pipes). The name @@ -2148,7 +2148,7 @@ gdb (with 'set remotetimeout') is recommended. An insufficient timeout may cause initialization to fail with "Unknown remote qXfer reply: OK". @end deffn -@deffn {Command} tcl_port [number] +@deffn {Command} {tcl_port} [number] Specify or query the port used for a simplified RPC connection that can be used by clients to issue TCL commands and get the output from the Tcl engine. @@ -2158,7 +2158,7 @@ the port @var{number} defaults to 6666. When specified as "disabled", this service is not activated. @end deffn -@deffn {Command} telnet_port [number] +@deffn {Command} {telnet_port} [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. @@ -2177,7 +2177,7 @@ The ones listed here are static and global. @xref{targetevents,,Target Events}, about configuring target-specific event handling. @anchor{gdbbreakpointoverride} -@deffn {Command} gdb_breakpoint_override [@option{hard}|@option{soft}|@option{disable}] +@deffn {Command} {gdb_breakpoint_override} [@option{hard}|@option{soft}|@option{disable}] Force breakpoint type for gdb @command{break} commands. This option supports GDB GUIs which don't distinguish hard versus soft breakpoints, if the default OpenOCD and @@ -2220,7 +2220,7 @@ Set to @option{enable} to cause OpenOCD to send the target descriptions to gdb v The default behaviour is @option{enable}. @end deffn -@deffn {Command} gdb_save_tdesc +@deffn {Command} {gdb_save_tdesc} Saves the target description file to the local file system. The file name is @i{target_name}.xml. @@ -2265,7 +2265,7 @@ to the various active targets. There is a command to manage and monitor that polling, which is normally done in the background. -@deffn {Command} poll [@option{on}|@option{off}] +@deffn {Command} {poll} [@option{on}|@option{off}] Poll the current target for its current state. (Also, @pxref{targetcurstate,,target curstate}.) If that target is in debug mode, architecture @@ -3598,19 +3598,19 @@ When a board has a reset button connected to SRST line it will probably have hardware debouncing, implying you should use this. @end deffn -@deffn {Command} jtag_ntrst_assert_width milliseconds +@deffn {Command} {jtag_ntrst_assert_width} milliseconds Minimum amount of time (in milliseconds) OpenOCD should wait after asserting nTRST (active-low JTAG TAP reset) before allowing it to be deasserted. @end deffn -@deffn {Command} jtag_ntrst_delay milliseconds +@deffn {Command} {jtag_ntrst_delay} milliseconds How long (in milliseconds) OpenOCD should wait after deasserting nTRST (active-low JTAG TAP reset) before starting new JTAG operations. @end deffn @anchor{reset_config} -@deffn {Command} reset_config mode_flag ... +@deffn {Command} {reset_config} mode_flag ... This command displays or modifies the reset configuration of your combination of JTAG board and target in target configuration scripts. @@ -4446,7 +4446,7 @@ foreach t [target names] @{ @c yep, "target list" would have been better. @c plus maybe "target setdefault". -@deffn {Command} targets [name] +@deffn {Command} {targets} [name] @emph{Note: the name of this command is plural. Other target command names are singular.} @@ -8032,11 +8032,11 @@ port is 5555. @section Server Commands -@deffn {Command} exit +@deffn {Command} {exit} Exits the current telnet session. @end deffn -@deffn {Command} help [string] +@deffn {Command} {help} [string] With no parameters, prints help text for all commands. Otherwise, prints each helptext containing @var{string}. Not every command provides helptext. @@ -8047,7 +8047,7 @@ In most cases, no such restriction is listed; this indicates commands which are only available after the configuration stage has completed. @end deffn -@deffn {Command} sleep msec [@option{busy}] +@deffn {Command} {sleep} msec [@option{busy}] Wait for at least @var{msec} milliseconds before resuming. If @option{busy} is passed, busy-wait instead of sleeping. (This option is strongly discouraged.) @@ -8055,7 +8055,7 @@ Useful in connection with script files (@command{script} command and @command{target_name} configuration). @end deffn -@deffn {Command} shutdown [@option{error}] +@deffn {Command} {shutdown} [@option{error}] Close the OpenOCD server, disconnecting all clients (GDB, telnet, other). If option @option{error} is used, OpenOCD will return a non-zero exit code to the parent process. @@ -8075,7 +8075,7 @@ or its replacement will be automatically executed before OpenOCD exits. @end deffn @anchor{debuglevel} -@deffn {Command} debug_level [n] +@deffn {Command} {debug_level} [n] @cindex message level Display debug level. If @var{n} (from 0..4) is provided, then set it to that level. @@ -8091,7 +8091,7 @@ file (which is normally the server's standard output). @xref{Running}. @end deffn -@deffn {Command} echo [-n] message +@deffn {Command} {echo} [-n] message Logs a message at "user" priority. Output @var{message} to stdout. Option "-n" suppresses trailing newline. @@ -8100,16 +8100,16 @@ echo "Downloading kernel -- please wait" @end example @end deffn -@deffn {Command} log_output [filename | "default"] +@deffn {Command} {log_output} [filename | "default"] Redirect logging to @var{filename} or set it back to default output; the default log output channel is stderr. @end deffn -@deffn {Command} add_script_search_dir [directory] +@deffn {Command} {add_script_search_dir} [directory] Add @var{directory} to the file/script search path. @end deffn -@deffn {Command} bindto [@var{name}] +@deffn {Command} {bindto} [@var{name}] Specify hostname or IPv4 address on which to listen for incoming TCP/IP connections. By default, OpenOCD will listen on the loopback interface only. If your network environment is safe, @code{bindto @@ -8130,7 +8130,7 @@ various operations. The current target may be changed by using @command{targets} command with the name of the target which should become current. -@deffn {Command} reg [(number|name) [(value|'force')]] +@deffn {Command} {reg} [(number|name) [(value|'force')]] Access a single register by @var{number} or by its @var{name}. The target must generally be halted before access to CPU core registers is allowed. Depending on the hardware, some other @@ -8169,8 +8169,8 @@ Debug and trace infrastructure: @end example @end deffn -@deffn {Command} halt [ms] -@deffnx {Command} wait_halt [ms] +@deffn {Command} {halt} [ms] +@deffnx {Command} {wait_halt} [ms] The @command{halt} command first sends a halt request to the target, which @command{wait_halt} doesn't. Otherwise these behave the same: wait up to @var{ms} milliseconds, @@ -8204,19 +8204,19 @@ power consumption (because the CPU is needlessly clocked). @end deffn -@deffn {Command} resume [address] +@deffn {Command} {resume} [address] Resume the target at its current code position, or the optional @var{address} if it is provided. OpenOCD will wait 5 seconds for the target to resume. @end deffn -@deffn {Command} step [address] +@deffn {Command} {step} [address] Single-step the target at its current code position, or the optional @var{address} if it is provided. @end deffn @anchor{resetcommand} -@deffn {Command} reset +@deffn {Command} {reset} @deffnx {Command} {reset run} @deffnx {Command} {reset halt} @deffnx {Command} {reset init} @@ -8237,7 +8237,7 @@ The other options will not work on all systems. @end itemize @end deffn -@deffn {Command} soft_reset_halt +@deffn {Command} {soft_reset_halt} Requesting target halt and executing a soft reset. This is often used when a target cannot be reset and halted. The target, after reset is released begins to execute code. OpenOCD attempts to stop the CPU and @@ -8293,10 +8293,10 @@ Please use their TARGET object siblings to avoid making assumptions about what TAP is the current target, or about MMU configuration. @end enumerate -@deffn {Command} mdd [phys] addr [count] -@deffnx {Command} mdw [phys] addr [count] -@deffnx {Command} mdh [phys] addr [count] -@deffnx {Command} mdb [phys] addr [count] +@deffn {Command} {mdd} [phys] addr [count] +@deffnx {Command} {mdw} [phys] addr [count] +@deffnx {Command} {mdh} [phys] addr [count] +@deffnx {Command} {mdb} [phys] addr [count] Display contents of address @var{addr}, as 64-bit doublewords (@command{mdd}), 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), @@ -8310,10 +8310,10 @@ If @var{count} is specified, displays that many units. see the @code{mem2array} primitives.) @end deffn -@deffn {Command} mwd [phys] addr doubleword [count] -@deffnx {Command} mww [phys] addr word [count] -@deffnx {Command} mwh [phys] addr halfword [count] -@deffnx {Command} mwb [phys] addr byte [count] +@deffn {Command} {mwd} [phys] addr doubleword [count] +@deffnx {Command} {mww} [phys] addr word [count] +@deffnx {Command} {mwh} [phys] addr halfword [count] +@deffnx {Command} {mwb} [phys] addr byte [count] Writes the specified @var{doubleword} (64 bits), @var{word} (32 bits), @var{halfword} (16 bits), or @var{byte} (8-bit) value, at the specified address @var{addr}. @@ -11162,7 +11162,7 @@ type target_state state [state-name] type target_reset mode [reset-mode] @end verbatim -@deffn {Command} tcl_notifications [on/off] +@deffn {Command} {tcl_notifications} [on/off] Toggle output of target notifications to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off. @@ -11181,7 +11181,7 @@ Target trace data is emitted as a Tcl associative array in the following format. type target_trace data [trace-data-hex-encoded] @end verbatim -@deffn {Command} tcl_trace [on/off] +@deffn {Command} {tcl_trace} [on/off] Toggle output of target trace data to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off. From fa94a42a09aadc3851015bbaedecd0300732a8b1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 6 Apr 2021 23:44:37 +0200 Subject: [PATCH 04/58] doc: [3/3] uniform the texinfo syntax for commands definition To avoid errors in the documentation, like the one fixed by change http://openocd.zylin.com/6134/ , use a uniform notation across the file so simple copy-paste will work. Enclose every command within curly-brackets '{...}', even single word commands. Patch generated through: sed -i 's/^\(@deffn {[^{]*} \)\([^{][^ ]*\)/\1{\2}/' doc/openocd.texi sed -i 's/^\(@deffnx {[^{]*} \)\([^{][^ ]*\)/\1{\2}/' doc/openocd.texi Change-Id: I41a8447d487ec8f6f32c2babcbc73ac21c769344 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6152 Tested-by: jenkins --- doc/openocd.texi | 162 +++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 8b4113aac..fdef3309d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2063,7 +2063,7 @@ a target has been successfully instantiated. If you want to use those commands, you may need to force entry to the run stage. -@deffn {Config Command} init +@deffn {Config Command} {init} This command terminates the configuration stage and enters the run stage. This helps when you need to have the startup scripts manage tasks such as resetting the target, @@ -2082,7 +2082,7 @@ read/write memory on your target, @command{init} must occur before the memory read/write commands. This includes @command{nand probe}. @end deffn -@deffn {Overridable Procedure} jtag_init +@deffn {Overridable Procedure} {jtag_init} This is invoked at server startup to verify that it can talk to the scan chain (list of TAPs) which has been configured. @@ -2186,13 +2186,13 @@ breakpoints if the memory map has been set up for flash regions. @end deffn @anchor{gdbflashprogram} -@deffn {Config Command} gdb_flash_program (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb_flash_program} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to program the flash memory when a vFlash packet is received. The default behaviour is @option{enable}. @end deffn -@deffn {Config Command} gdb_memory_map (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb_memory_map} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the memory configuration to GDB when requested. GDB will then know when to set hardware breakpoints, and program flash using the GDB load command. @command{gdb_flash_program enable} must also be enabled @@ -2201,21 +2201,21 @@ Default behaviour is @option{enable}. @xref{gdbflashprogram,,gdb_flash_program}. @end deffn -@deffn {Config Command} gdb_report_data_abort (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb_report_data_abort} (@option{enable}|@option{disable}) Specifies whether data aborts cause an error to be reported by GDB memory read packets. The default behaviour is @option{disable}; use @option{enable} see these errors reported. @end deffn -@deffn {Config Command} gdb_report_register_access_error (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb_report_register_access_error} (@option{enable}|@option{disable}) Specifies whether register accesses requested by GDB register read/write packets report errors or not. The default behaviour is @option{disable}; use @option{enable} see these errors reported. @end deffn -@deffn {Config Command} gdb_target_description (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb_target_description} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the target descriptions to gdb via qXfer:features:read packet. The default behaviour is @option{enable}. @end deffn @@ -2383,7 +2383,7 @@ Specifies either the address of the I/O port (default: 0x378 for LPT1) or the number of the @file{/dev/parport} device. @end deffn -@deffn {Config Command} rtck [@option{enable}|@option{disable}] +@deffn {Config Command} {rtck} [@option{enable}|@option{disable}] Displays status of RTCK option. Optionally sets that option first. @end deffn @@ -3745,7 +3745,7 @@ schemes. For example, on a multi-target board the standard may need the ability to reset only one target at time and thus want to avoid using the board-wide SRST signal. -@deffn {Overridable Procedure} init_reset mode +@deffn {Overridable Procedure} {init_reset} mode This is invoked near the beginning of the @command{reset} command, usually to provide as much of a cold (power-up) reset as practical. By default it is also invoked from @command{jtag_init} if @@ -5354,7 +5354,7 @@ As noted above, the @command{flash bank} command requires a driver name, and allows driver-specific options and behaviors. Some drivers also activate driver-specific commands. -@deffn {Flash Driver} virtual +@deffn {Flash Driver} {virtual} This is a special driver that maps a previously defined bank to another address. All bank settings will be copied from the master physical bank. @@ -5378,7 +5378,7 @@ flash bank vbank1 virtual 0x9fc00000 0 0 0 \ @subsection External Flash -@deffn {Flash Driver} cfi +@deffn {Flash Driver} {cfi} @cindex Common Flash Interface @cindex CFI The ``Common Flash Interface'' (CFI) is the main standard for @@ -5423,7 +5423,7 @@ flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME @c "cfi part_id" disabled @end deffn -@deffn {Flash Driver} jtagspi +@deffn {Flash Driver} {jtagspi} @cindex Generic JTAG2SPI driver @cindex SPI @cindex jtagspi @@ -5464,7 +5464,7 @@ flash bank $_FLASHNAME spi 0x0 0 0 0 \ @end example @end deffn -@deffn {Flash Driver} xcf +@deffn {Flash Driver} {xcf} @cindex Xilinx Platform flash driver @cindex xcf Xilinx FPGAs can be configured from specialized flash ICs named Platform Flash. @@ -5510,7 +5510,7 @@ only "bin" (raw binary, do not confuse it with "bit") and "mcs" @end itemize @end deffn -@deffn {Flash Driver} lpcspifi +@deffn {Flash Driver} {lpcspifi} @cindex NXP SPI Flash Interface @cindex SPIFI @cindex lpcspifi @@ -5534,7 +5534,7 @@ flash bank $_FLASHNAME lpcspifi 0x14000000 0 0 0 $_TARGETNAME @end deffn -@deffn {Flash Driver} stmsmi +@deffn {Flash Driver} {stmsmi} @cindex STMicroelectronics Serial Memory Interface @cindex SMI @cindex stmsmi @@ -5562,7 +5562,7 @@ flash bank $_FLASHNAME stmsmi 0xf8000000 0 0 0 $_TARGETNAME @end deffn -@deffn {Flash Driver} stmqspi +@deffn {Flash Driver} {stmqspi} @cindex STMicroelectronics QuadSPI/OctoSPI Interface @cindex QuadSPI @cindex OctoSPI @@ -5677,7 +5677,7 @@ should return the status register contents. @end deffn -@deffn {Flash Driver} mrvlqspi +@deffn {Flash Driver} {mrvlqspi} This driver supports QSPI flash controller of Marvell's Wireless Microcontroller platform. @@ -5690,7 +5690,7 @@ flash bank $_FLASHNAME mrvlqspi 0x0 0 0 0 $_TARGETNAME 0x46010000 @end deffn -@deffn {Flash Driver} ath79 +@deffn {Flash Driver} {ath79} @cindex Atheros ath79 SPI driver @cindex ath79 Members of ATH79 SoC family from Atheros include a SPI interface with 3 @@ -5729,7 +5729,7 @@ flash bank flash2 ath79 0x20000000 0 0 0 $_TARGETNAME cs2 @end deffn -@deffn {Flash Driver} fespi +@deffn {Flash Driver} {fespi} @cindex Freedom E SPI @cindex fespi @@ -5742,7 +5742,7 @@ flash bank $_FLASHNAME fespi 0x20000000 0 0 0 $_TARGETNAME @subsection Internal Flash (Microcontrollers) -@deffn {Flash Driver} aduc702x +@deffn {Flash Driver} {aduc702x} The ADUC702x analog microcontrollers from Analog Devices include internal flash and use ARM7TDMI cores. The aduc702x flash driver works with models ADUC7019 through ADUC7028. @@ -5754,7 +5754,7 @@ flash bank $_FLASHNAME aduc702x 0 0 0 0 $_TARGETNAME @end example @end deffn -@deffn {Flash Driver} ambiqmicro +@deffn {Flash Driver} {ambiqmicro} @cindex ambiqmicro @cindex apollo All members of the Apollo microcontroller family from @@ -5802,7 +5802,7 @@ the flash. @end deffn @anchor{at91samd} -@deffn {Flash Driver} at91samd +@deffn {Flash Driver} {at91samd} @cindex at91samd All members of the ATSAM D2x, D1x, D0x, ATSAMR, ATSAML and ATSAMC microcontroller families from Atmel include internal flash and use ARM's Cortex-M0+ core. @@ -5891,7 +5891,7 @@ NVMUSERROW: 0xFFFFFC5DD8E0C788 @end deffn @anchor{at91sam3} -@deffn {Flash Driver} at91sam3 +@deffn {Flash Driver} {at91sam3} @cindex at91sam3 All members of the AT91SAM3 microcontroller family from Atmel include internal flash and use ARM's Cortex-M3 core. The driver @@ -5955,14 +5955,14 @@ This command shows/sets the slow clock frequency used in the @end deffn @end deffn -@deffn {Flash Driver} at91sam4 +@deffn {Flash Driver} {at91sam4} @cindex at91sam4 All members of the AT91SAM4 microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. This driver uses the same command names/syntax as @xref{at91sam3}. @end deffn -@deffn {Flash Driver} at91sam4l +@deffn {Flash Driver} {at91sam4l} @cindex at91sam4l All members of the AT91SAM4L microcontroller family from Atmel include internal flash and use ARM's Cortex-M4 core. @@ -5977,7 +5977,7 @@ Command is used internally in event reset-deassert-post. @end deffn @anchor{atsame5} -@deffn {Flash Driver} atsame5 +@deffn {Flash Driver} {atsame5} @cindex atsame5 All members of the SAM E54, E53, E51 and D51 microcontroller families from Microchip (former Atmel) include internal flash @@ -6040,14 +6040,14 @@ USER PAGE: 0xAEECFF80FE9A9239 @end deffn -@deffn {Flash Driver} atsamv +@deffn {Flash Driver} {atsamv} @cindex atsamv All members of the ATSAMV7x, ATSAMS70, and ATSAME70 families from Atmel include internal flash and use ARM's Cortex-M7 core. This driver uses the same command names/syntax as @xref{at91sam3}. @end deffn -@deffn {Flash Driver} at91sam7 +@deffn {Flash Driver} {at91sam7} All members of the AT91SAM7 microcontroller family from Atmel include internal flash and use ARM7TDMI cores. The driver automatically recognizes a number of these chips using the chip identification @@ -6094,13 +6094,13 @@ the appropriate at91sam7 target. @end deffn @end deffn -@deffn {Flash Driver} avr +@deffn {Flash Driver} {avr} The AVR 8-bit microcontrollers from Atmel integrate flash memory. @emph{The current implementation is incomplete.} @comment - defines mass_erase ... pointless given flash_erase_address @end deffn -@deffn {Flash Driver} bluenrg-x +@deffn {Flash Driver} {bluenrg-x} STMicroelectronics BlueNRG-1, BlueNRG-2 and BlueNRG-LP Bluetooth low energy wireless system-on-chip. They include ARM Cortex-M0/M0+ core and internal flash memory. The driver automatically recognizes these chips using the chip identification registers, and autoconfigures itself. @@ -6119,7 +6119,7 @@ flash erase_sector 0 0 last # It will perform a mass erase Triggering a mass erase is also useful when users want to disable readout protection. @end deffn -@deffn {Flash Driver} cc26xx +@deffn {Flash Driver} {cc26xx} All versions of the SimpleLink CC13xx and CC26xx microcontrollers from Texas Instruments include internal flash. The cc26xx flash driver supports both the CC13xx and CC26xx family of devices. The driver automatically recognizes the @@ -6131,7 +6131,7 @@ flash bank $_FLASHNAME cc26xx 0 0 0 0 $_TARGETNAME @end example @end deffn -@deffn {Flash Driver} cc3220sf +@deffn {Flash Driver} {cc3220sf} The CC3220SF version of the SimpleLink CC32xx microcontrollers from Texas Instruments includes 1MB of internal flash. The cc3220sf flash driver only supports the internal flash. The serial flash on SimpleLink boards is @@ -6145,7 +6145,7 @@ flash bank $_FLASHNAME cc3220sf 0 0 0 0 $_TARGETNAME @end example @end deffn -@deffn {Flash Driver} efm32 +@deffn {Flash Driver} {efm32} All members of the EFM32 microcontroller family from Energy Micro include internal flash and use ARM Cortex-M3 cores. The driver automatically recognizes a number of these chips using the chip identification register, and @@ -6165,7 +6165,7 @@ Note that in order for this command to take effect, the target needs to be reset supported.} @end deffn -@deffn {Flash Driver} esirisc +@deffn {Flash Driver} {esirisc} Members of the eSi-RISC family may optionally include internal flash programmed via the eSi-TSMC Flash interface. Additional parameters are required to configure the driver: @option{cfg_address} is the base address of the @@ -6187,7 +6187,7 @@ is an uncommon operation.} @end deffn @end deffn -@deffn {Flash Driver} fm3 +@deffn {Flash Driver} {fm3} All members of the FM3 microcontroller family from Fujitsu include internal flash and use ARM Cortex-M3 cores. The @var{fm3} driver uses the @var{target} parameter to select the @@ -6200,7 +6200,7 @@ flash bank $_FLASHNAME fm3 0 0 0 0 $_TARGETNAME @end example @end deffn -@deffn {Flash Driver} fm4 +@deffn {Flash Driver} {fm4} All members of the FM4 microcontroller family from Spansion (formerly Fujitsu) include internal flash and use ARM Cortex-M4 cores. The @var{fm4} driver uses a @var{family} parameter to select the @@ -6220,7 +6220,7 @@ flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 \ nor is Chip Erase (only Sector Erase is implemented).} @end deffn -@deffn {Flash Driver} kinetis +@deffn {Flash Driver} {kinetis} @cindex kinetis Kx, KLx, KVx and KE1x members of the Kinetis microcontroller family from NXP (former Freescale) include @@ -6319,7 +6319,7 @@ Command disables watchdog timer. @end deffn @end deffn -@deffn {Flash Driver} kinetis_ke +@deffn {Flash Driver} {kinetis_ke} @cindex kinetis_ke KE0x and KEAx members of the Kinetis microcontroller family from NXP include internal flash and use ARM Cortex-M0+. The driver automatically recognizes @@ -6347,7 +6347,7 @@ Command disables watchdog timer. @end deffn @end deffn -@deffn {Flash Driver} lpc2000 +@deffn {Flash Driver} {lpc2000} This is the driver to support internal flash of all members of the LPC11(x)00 and LPC1300 microcontroller families and most members of the LPC800, LPC1500, LPC1700, LPC1800, LPC2000, LPC4000, LPC54100, @@ -6404,7 +6404,7 @@ the specified flash @var{bank}. @end deffn @end deffn -@deffn {Flash Driver} lpc288x +@deffn {Flash Driver} {lpc288x} The LPC2888 microcontroller from NXP needs slightly different flash support from its lpc2000 siblings. The @var{lpc288x} driver defines one mandatory parameter, @@ -6416,7 +6416,7 @@ flash bank $_FLASHNAME lpc288x 0 0 0 0 $_TARGETNAME 12000000 @end example @end deffn -@deffn {Flash Driver} lpc2900 +@deffn {Flash Driver} {lpc2900} This driver supports the LPC29xx ARM968E based microcontroller family from NXP. @@ -6539,7 +6539,7 @@ lpc2900 secure_jtag 0 @end deffn @end deffn -@deffn {Flash Driver} mdr +@deffn {Flash Driver} {mdr} This drivers handles the integrated NOR flash on Milandr Cortex-M based controllers. A known limitation is that the Info memory can't be read or verified as it's not memory mapped. @@ -6567,7 +6567,7 @@ if @{ [info exists IMEMORY] && [string equal $IMEMORY true] @} @{ @end example @end deffn -@deffn {Flash Driver} msp432 +@deffn {Flash Driver} {msp432} All versions of the SimpleLink MSP432 microcontrollers from Texas Instruments include internal flash. The msp432 flash driver automatically recognizes the specific version's flash parameters and autoconfigures itself. @@ -6602,7 +6602,7 @@ msp432 bsl lock @end deffn @end deffn -@deffn {Flash Driver} niietcm4 +@deffn {Flash Driver} {niietcm4} This drivers handles the integrated NOR flash on NIIET Cortex-M4 based controllers. Flash size and sector layout are auto-configured by the driver. Main flash memory is called "Bootflash" and has main region and info region. @@ -6662,7 +6662,7 @@ Show information about flash driver. @end deffn -@deffn {Flash Driver} nrf5 +@deffn {Flash Driver} {nrf5} All members of the nRF51 microcontroller families from Nordic Semiconductor include internal flash and use ARM Cortex-M0 core. Also, the nRF52832 microcontroller from Nordic Semiconductor, which include @@ -6687,7 +6687,7 @@ Decodes and shows information from FICR and UICR registers. @end deffn -@deffn {Flash Driver} ocl +@deffn {Flash Driver} {ocl} This driver is an implementation of the ``on chip flash loader'' protocol proposed by Pavel Chromy. @@ -6701,7 +6701,7 @@ flash bank $_FLASHNAME ocl 0 0 0 0 $_TARGETNAME @end example @end deffn -@deffn {Flash Driver} pic32mx +@deffn {Flash Driver} {pic32mx} The PIC32MX microcontrollers are based on the MIPS 4K cores, and integrate flash memory. @@ -6725,7 +6725,7 @@ This will remove any Code Protection. @end deffn @end deffn -@deffn {Flash Driver} psoc4 +@deffn {Flash Driver} {psoc4} All members of the PSoC 41xx/42xx microcontroller family from Cypress include internal flash and use ARM Cortex-M0 cores. The driver automatically recognizes a number of these chips using @@ -6759,7 +6759,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn -@deffn {Flash Driver} psoc5lp +@deffn {Flash Driver} {psoc5lp} All members of the PSoC 5LP microcontroller family from Cypress include internal program flash and use ARM Cortex-M3 cores. The driver probes for a number of these chips and autoconfigures itself, @@ -6785,7 +6785,7 @@ and all row latches in all flash arrays on the device. @end deffn @end deffn -@deffn {Flash Driver} psoc5lp_eeprom +@deffn {Flash Driver} {psoc5lp_eeprom} All members of the PSoC 5LP microcontroller family from Cypress include internal EEPROM and use ARM Cortex-M3 cores. The driver probes for a number of these chips and autoconfigures itself, @@ -6797,7 +6797,7 @@ flash bank $_CHIPNAME.eeprom psoc5lp_eeprom 0x40008000 0 0 0 \ @end example @end deffn -@deffn {Flash Driver} psoc5lp_nvl +@deffn {Flash Driver} {psoc5lp_nvl} All members of the PSoC 5LP microcontroller family from Cypress include internal Nonvolatile Latches and use ARM Cortex-M3 cores. The driver probes for a number of these chips and autoconfigures itself. @@ -6822,7 +6822,7 @@ after successful write. @end quotation @end deffn -@deffn {Flash Driver} psoc6 +@deffn {Flash Driver} {psoc6} Supports PSoC6 (CY8C6xxx) family of Cypress microcontrollers. PSoC6 is a dual-core device with CM0+ and CM4 cores. Both cores share the same Flash/RAM/MMIO address space. @@ -6890,7 +6890,7 @@ Note: only Main and Work flash regions support Erase operation. @end deffn @end deffn -@deffn {Flash Driver} sim3x +@deffn {Flash Driver} {sim3x} All members of the SiM3 microcontroller family from Silicon Laboratories include internal flash and use ARM Cortex-M3 cores. It supports both JTAG and SWD interface. @@ -6913,7 +6913,7 @@ Lock the flash. To unlock use the @command{sim3x mass_erase} command. @end deffn @end deffn -@deffn {Flash Driver} stellaris +@deffn {Flash Driver} {stellaris} All members of the Stellaris LM3Sxxx, LM4x and Tiva C microcontroller families from Texas Instruments include internal flash. The driver automatically recognizes a number of these chips using the chip @@ -6939,7 +6939,7 @@ applied to all of them. @end deffn @end deffn -@deffn {Flash Driver} stm32f1x +@deffn {Flash Driver} {stm32f1x} All members of the STM32F0, STM32F1 and STM32F3 microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M0/M3/M4 cores. The driver automatically recognizes a number of these chips using @@ -7001,7 +7001,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn -@deffn {Flash Driver} stm32f2x +@deffn {Flash Driver} {stm32f2x} All members of the STM32F2, STM32F4 and STM32F7 microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M3/M4/M7 cores. The driver automatically recognizes a number of these chips using @@ -7066,7 +7066,7 @@ The @var{num} parameter is a value shown by @command{flash banks}, @var{optcr2} @end deffn @end deffn -@deffn {Flash Driver} stm32h7x +@deffn {Flash Driver} {stm32h7x} All members of the STM32H7 microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M7 core. The driver automatically recognizes a number of these chips using @@ -7134,7 +7134,7 @@ stm32h7x option_write 0 0x20 0x8000000 0x8000000 @end deffn @end deffn -@deffn {Flash Driver} stm32lx +@deffn {Flash Driver} {stm32lx} All members of the STM32L0 and STM32L1 microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M3 and Cortex-M0+ cores. The driver automatically recognizes a number of these chips using @@ -7174,7 +7174,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn -@deffn {Flash Driver} stm32l4x +@deffn {Flash Driver} {stm32l4x} All members of the STM32 G0, G4, L4, L4+, L5, WB and WL microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M0+, M4 and M33 cores. @@ -7275,7 +7275,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn -@deffn {Flash Driver} str7x +@deffn {Flash Driver} {str7x} All members of the STR7 microcontroller family from STMicroelectronics include internal flash and use ARM7TDMI cores. The @var{str7x} driver defines one mandatory parameter, @var{variant}, @@ -7292,7 +7292,7 @@ for the specified flash bank. @end deffn @end deffn -@deffn {Flash Driver} str9x +@deffn {Flash Driver} {str9x} Most members of the STR9 microcontroller family from STMicroelectronics include internal flash and use ARM966E cores. The str9 needs the flash controller to be configured using @@ -7317,7 +7317,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn {Flash Driver} str9xpec +@deffn {Flash Driver} {str9xpec} @cindex str9xpec Only use this driver for locking/unlocking the device or configuring the option bytes. @@ -7412,7 +7412,7 @@ unlock str9 device. @end deffn -@deffn {Flash Driver} swm050 +@deffn {Flash Driver} {swm050} @cindex swm050 All members of the swm050 microcontroller family from Foshan Synwit Tech. @@ -7429,7 +7429,7 @@ Erases the entire flash bank. @end deffn -@deffn {Flash Driver} tms470 +@deffn {Flash Driver} {tms470} Most members of the TMS470 microcontroller family from Texas Instruments include internal flash and use ARM7TDMI cores. This driver doesn't require the chip and bus width to be specified. @@ -7450,7 +7450,7 @@ the flash clock. @end deffn @end deffn -@deffn {Flash Driver} w600 +@deffn {Flash Driver} {w600} W60x series Wi-Fi SoC from WinnerMicro are designed with ARM Cortex-M3 and have 1M Byte QFLASH inside. The @var{w600} driver uses the @var{target} parameter to select the @@ -7461,12 +7461,12 @@ flash bank $_FLASHNAME w600 0x08000000 0 0 0 $_TARGETNAMEs @end example @end deffn -@deffn {Flash Driver} xmc1xxx +@deffn {Flash Driver} {xmc1xxx} All members of the XMC1xxx microcontroller family from Infineon. This driver does not require the chip and bus width to be specified. @end deffn -@deffn {Flash Driver} xmc4xxx +@deffn {Flash Driver} {xmc4xxx} All members of the XMC4xxx microcontroller family from Infineon. This driver does not require the chip and bus width to be specified. @@ -7794,7 +7794,7 @@ As noted above, the @command{nand device} command allows driver-specific options and behaviors. Some controllers also activate controller-specific commands. -@deffn {NAND Driver} at91sam9 +@deffn {NAND Driver} {at91sam9} This driver handles the NAND controllers found on AT91SAM9 family chips from Atmel. It takes two extra parameters: address of the NAND chip; address of the ECC controller. @@ -7829,7 +7829,7 @@ is the base address of the PIO controller and @var{pin} is the pin number. @end deffn @end deffn -@deffn {NAND Driver} davinci +@deffn {NAND Driver} {davinci} This driver handles the NAND controllers found on DaVinci family chips from Texas Instruments. It takes three extra parameters: @@ -7847,7 +7847,7 @@ to implement those ECC modes, unless they are disabled using the @command{nand raw_access} command. @end deffn -@deffn {NAND Driver} lpc3180 +@deffn {NAND Driver} {lpc3180} These controllers require an extra @command{nand device} parameter: the clock rate used by the controller. @deffn {Command} {lpc3180 select} num [mlc|slc] @@ -7863,12 +7863,12 @@ in the MLC controller mode, but won't change SLC behavior. @end deffn @comment current lpc3180 code won't issue 5-byte address cycles -@deffn {NAND Driver} mx3 +@deffn {NAND Driver} {mx3} This driver handles the NAND controller in i.MX31. The mxc driver should work for this chip as well. @end deffn -@deffn {NAND Driver} mxc +@deffn {NAND Driver} {mxc} This driver handles the NAND controller found in Freescale i.MX chips. It has support for v1 (i.MX27 and i.MX31) and v2 (i.MX35). The driver takes 3 extra arguments, chip (@option{mx27}, @@ -7884,7 +7884,7 @@ without parameter query status. @end deffn @end deffn -@deffn {NAND Driver} orion +@deffn {NAND Driver} {orion} These controllers require an extra @command{nand device} parameter: the address of the controller. @example @@ -7896,11 +7896,11 @@ or @code{read_page} methods, so @command{nand raw_access} won't change any behavior. @end deffn -@deffn {NAND Driver} s3c2410 -@deffnx {NAND Driver} s3c2412 -@deffnx {NAND Driver} s3c2440 -@deffnx {NAND Driver} s3c2443 -@deffnx {NAND Driver} s3c6400 +@deffn {NAND Driver} {s3c2410} +@deffnx {NAND Driver} {s3c2412} +@deffnx {NAND Driver} {s3c2440} +@deffnx {NAND Driver} {s3c2443} +@deffnx {NAND Driver} {s3c6400} These S3C family controllers don't have any special @command{nand device} options, and don't define any specialized commands. @@ -7987,7 +7987,7 @@ Drivers may support PLD-specific options to the @command{pld device} definition command, and may also define commands usable only with that particular type of PLD. -@deffn {FPGA Driver} virtex2 [no_jstart] +@deffn {FPGA Driver} {virtex2} [no_jstart] Virtex-II is a family of FPGAs sold by Xilinx. It supports the IEEE 1532 standard for In-System Configuration (ISC). @@ -8756,7 +8756,7 @@ Stops trace data collection. To use an ETM trace port it must be associated with a driver. -@deffn {Trace Port Driver} dummy +@deffn {Trace Port Driver} {dummy} Use the @option{dummy} driver if you are configuring an ETM that's not connected to anything (on-chip ETB or off-chip trace connector). @emph{This driver lets OpenOCD talk to the ETM, but it does not expose @@ -8766,7 +8766,7 @@ Associates the ETM for @var{target} with a dummy driver. @end deffn @end deffn -@deffn {Trace Port Driver} etb +@deffn {Trace Port Driver} {etb} Use the @option{etb} driver if you are configuring an ETM to use on-chip ETB memory. @deffn {Config Command} {etb config} target etb_tap From a9904ba22c6a8c9cd56c85296e80396c9e05ee9e Mon Sep 17 00:00:00 2001 From: Cheng-Shiun Tsai Date: Sat, 6 Feb 2021 23:04:14 +0000 Subject: [PATCH 05/58] Aarch64:Switch to EL1 from EL0 before manipulate MMU If current core is in EL0, it cannot use 'msr sctlr_el1, x0' Change-Id: I04e60e39e4c84f9d9de7cc87a8e438f5d2737dc3 Signed-off-by: Cheng-Shiun Tsai Reviewed-on: http://openocd.zylin.com/6051 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Matthias Welwarsky --- src/target/aarch64.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d6b12cd59..46ed49f68 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -133,6 +133,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; int retval = ERROR_OK; + enum arm_mode target_mode = ARM_MODE_ANY; uint32_t instr = 0; if (enable) { @@ -158,6 +159,8 @@ static int aarch64_mmu_modify(struct target *target, int enable) switch (armv8->arm.core_mode) { case ARMV8_64_EL0T: + target_mode = ARMV8_64_EL1H; + /* fall through */ case ARMV8_64_EL1T: case ARMV8_64_EL1H: instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); @@ -184,9 +187,15 @@ static int aarch64_mmu_modify(struct target *target, int enable) LOG_DEBUG("unknown cpu state 0x%x", armv8->arm.core_mode); break; } + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, target_mode); retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, aarch64->system_control_reg_curr); + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); + return retval; } From a510c8e23c23b7a888623faf0c4a9982489ddf83 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 12 May 2020 00:22:13 +0200 Subject: [PATCH 06/58] helper/command: always pass struct command as jim private data While registering a new command, jim accepts a pointer to command's private data that will be accessible during the command execution. Today openocd is not consistent and passes different private data depending on the command, and then even overwrites it: - "simple" commands (.handler) are registered with their own struct command pointer as command private data; - "native" commands (.jim_handler) at root level are registered with NULL command private data; - "native" commands (.jim_handler) not at root level are registered with the struct command pointer of their root command as command private data but, when executed, the command private data is overwritten by the value in field jim_handler_data taken from their struct command. Uniform the usage of command private data by always set it to the struct command pointer while registering the new commands. Note: for multi-word commands only the root command is registered, so command private data will be set to the struct command of the root command. This will change later in this series when the full- name of the command will be registered. Don't overwrite the command private data, but let the commands that needs jim_handler_data to get it directly through struct command. For sake of uniformity, let function command_set_handler_data() to set the field jim_handler_data also for "group" commands, even if such value will not be used. Now Jim_CmdPrivData() always returns a struct command pointer, so wrap it in the inline function jim_to_command() to gain compile time check on the returned type. While there, uniform the code to use the macro Jim_CmdPrivData() to access the command's private data pointer. Change-Id: Idba16242ba1f6769341b4030a49cdf35a5278695 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5664 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 8 +++----- src/helper/command.h | 9 +++++++++ src/target/arm_tpiu_swo.c | 9 ++++++--- src/target/nds32_cmd.c | 15 ++++++++++----- src/target/target.c | 39 ++++++++++++++++++++++++++------------- 5 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index e2726f258..b44e4667f 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -248,7 +248,7 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* the private data is stashed in the interp structure */ - struct command *c = interp->cmdPrivData; + struct command *c = jim_to_command(interp); assert(c); script_debug(interp, argc, argv); return script_command_run(interp, argc, argv, c); @@ -418,7 +418,7 @@ static struct command *register_command(struct command_context *context, int retval = JIM_OK; if (NULL != cr->jim_handler && NULL == parent) { retval = Jim_CreateCommand(context->interp, cr->name, - cr->jim_handler, NULL, NULL); + cr->jim_handler, c, NULL); } else if (NULL != cr->handler || NULL != parent) retval = register_command_handler(context, command_root(c)); @@ -501,8 +501,7 @@ static int unregister_command(struct command_context *context, void command_set_handler_data(struct command *c, void *p) { - if (NULL != c->handler || NULL != c->jim_handler) - c->jim_handler_data = p; + c->jim_handler_data = p; for (struct command *cc = c->children; NULL != cc; cc = cc->next) command_set_handler_data(cc, p); } @@ -1085,7 +1084,6 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (!command_can_run(cmd_ctx, c)) return JIM_ERR; - interp->cmdPrivData = c->jim_handler_data; return (*c->jim_handler)(interp, count, start); } diff --git a/src/helper/command.h b/src/helper/command.h index b0c84bb43..cb088d743 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -195,6 +195,15 @@ struct command { struct command *next; }; +/* + * Return the struct command pointer kept in private data + * Used to enforce check on data type + */ +static inline struct command *jim_to_command(Jim_Interp *interp) +{ + return Jim_CmdPrivData(interp); +} + /* * Commands should be registered by filling in one or more of these * structures and passing them to [un]register_commands(). diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 2da52e892..543b4f008 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -559,7 +559,8 @@ static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * co "missing: -option ..."); return JIM_ERR; } - struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct arm_tpiu_swo_object *obj = c->jim_handler_data; return arm_tpiu_swo_configure(&goi, obj); } @@ -583,7 +584,8 @@ static int wrap_read_u32(struct target *target, struct adiv5_ap *tpiu_ap, static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct arm_tpiu_swo_object *obj = c->jim_handler_data; struct command_context *cmd_ctx = current_command_context(interp); struct adiv5_ap *tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); uint32_t value; @@ -786,7 +788,8 @@ error_exit: static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct arm_tpiu_swo_object *obj = c->jim_handler_data; if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c index 1684ea882..89da845d3 100644 --- a/src/target/nds32_cmd.c +++ b/src/target/nds32_cmd.c @@ -722,7 +722,8 @@ static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *a return JIM_ERR; } - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; int result; result = target_write_buffer(target, address, count * 4, (const uint8_t *)data); @@ -751,7 +752,8 @@ static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const * if (e != JIM_OK) return e; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; struct aice_port_s *aice = target_to_aice(target); int result; uint32_t address; @@ -812,7 +814,8 @@ static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *ar if (goi.argc != 0) return JIM_ERR; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; uint32_t *data = malloc(count * sizeof(uint32_t)); int result; result = target_read_buffer(target, address, count * 4, (uint8_t *)data); @@ -863,7 +866,8 @@ static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const * else return ERROR_FAIL; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; struct aice_port_s *aice = target_to_aice(target); char data_str[11]; @@ -911,7 +915,8 @@ static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const else return ERROR_FAIL; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; struct aice_port_s *aice = target_to_aice(target); aice_write_debug_reg(aice, edm_sr_number, value); diff --git a/src/target/target.c b/src/target/target.c index 200368b13..e481d526c 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5206,21 +5206,24 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a "missing: -option ..."); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; return target_configure(&goi, target); } static int jim_target_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; return target_mem2array(interp, target, argc - 1, argv + 1); } static int jim_target_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; return target_array2mem(interp, target, argc - 1, argv + 1); } @@ -5252,7 +5255,8 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv allow_defer = true; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5270,7 +5274,8 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; Jim_SetResultBool(interp, target_was_examined(target)); return JIM_OK; @@ -5278,7 +5283,8 @@ static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; Jim_SetResultBool(interp, target->defer_examine); return JIM_OK; @@ -5290,7 +5296,8 @@ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *arg Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) return JIM_ERR; @@ -5304,7 +5311,8 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5341,7 +5349,8 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (e != JIM_OK) return e; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command *c = jim_to_command(goi.interp); + struct target *target = c->jim_handler_data; if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5374,7 +5383,8 @@ static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e = target->type->halt(target); @@ -5404,7 +5414,8 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5448,7 +5459,8 @@ static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; Jim_SetResultString(interp, target_state_name(target), -1); return JIM_OK; } @@ -5467,7 +5479,8 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); return e; } - struct target *target = Jim_CmdPrivData(interp); + struct command *c = jim_to_command(interp); + struct target *target = c->jim_handler_data; target_handle_event(target, n->value); return JIM_OK; } From 462323f123ede2c8da59cb4acb772dc4f98dee79 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 12 May 2020 01:59:06 +0200 Subject: [PATCH 07/58] helper/command: use one single handler for all the commands Today openocd registers the commands to jim with three methods: 1) "native" commands (.jim_handler) at root level are registered directly as jim commands; 2) "simple" commands (.handler) at root level are registered through the handler script_command(); 3) all other commands not at root level are registered through the handler command_unknown(). Apart from using different handler, other inconsistencies are present: a) command in 1) are not checked for their "mode", so are run with no check about current mode (COMMAND_CONFIG or COMMAND_EXEC); b) target_call_timer_callbacks_now() is called only for "simple" commands and not for "native" commands; c) target override is performed only for "simple" commands and not for "native" commands. Drop script_command() and extend command_unknown() to uniformly handle all the cases above, fixing all the inconsistencies already mentioned. The handler's name command_unknown() is probably not anymore appropriate, but will be renamed in a separate change. Note: today all the commands in a) have mode CONFIG_ANY, apart for "mem2array" and "array2mem" that have mode COMMAND_EXEC. But the latter commands are registered during target init, so do not exist during COMMAND_CONFIG and no issue is present. Change-Id: I67bd6e47eb2c575107251b9192c676c27d4aabae Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5665 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 120 ++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 71 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index b44e4667f..ecca75db6 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -44,9 +44,6 @@ /* nice short description of source file */ #define __THIS__FILE__ "command.c" -static int run_command(struct command_context *context, - struct command *c, const char *words[], unsigned num_words); - struct log_capture_state { Jim_Interp *interp; Jim_Obj *output; @@ -226,34 +223,6 @@ struct command_context *current_command_context(Jim_Interp *interp) return cmd_ctx; } -static int script_command_run(Jim_Interp *interp, - int argc, Jim_Obj * const *argv, struct command *c) -{ - target_call_timer_callbacks_now(); - LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ - - unsigned nwords; - char **words = script_command_args_alloc(argc, argv, &nwords); - if (NULL == words) - return JIM_ERR; - - struct command_context *cmd_ctx = current_command_context(interp); - int retval = run_command(cmd_ctx, c, (const char **)words, nwords); - - script_command_args_free(words, nwords); - return command_retval_set(interp, retval); -} - -static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - /* the private data is stashed in the interp structure */ - - struct command *c = jim_to_command(interp); - assert(c); - script_debug(interp, argc, argv); - return script_command_run(interp, argc, argv, c); -} - static struct command *command_root(struct command *c) { while (NULL != c->parent) @@ -387,10 +356,7 @@ static int register_command_handler(struct command_context *cmd_ctx, LOG_DEBUG("registering '%s'...", c->name); #endif - Jim_CmdProc *func = c->handler ? &script_command : &command_unknown; - int retval = Jim_CreateCommand(interp, c->name, func, c, NULL); - - return retval; + return Jim_CreateCommand(interp, c->name, command_unknown, c, NULL); } static struct command *register_command(struct command_context *context, @@ -415,16 +381,12 @@ static struct command *register_command(struct command_context *context, if (NULL == c) return NULL; - int retval = JIM_OK; - if (NULL != cr->jim_handler && NULL == parent) { - retval = Jim_CreateCommand(context->interp, cr->name, - cr->jim_handler, c, NULL); - } else if (NULL != cr->handler || NULL != parent) - retval = register_command_handler(context, command_root(c)); - - if (retval != JIM_OK) { - unregister_command(context, parent, name); - c = NULL; + if (cr->jim_handler || cr->handler) { + int retval = register_command_handler(context, command_root(c)); + if (retval != JIM_OK) { + unregister_command(context, parent, name); + return NULL; + } } return c; } @@ -614,11 +576,8 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c) } static int run_command(struct command_context *context, - struct command *c, const char *words[], unsigned num_words) + struct command *c, const char **words, unsigned num_words) { - if (!command_can_run(context, c)) - return ERROR_FAIL; - struct command_invocation cmd = { .ctx = context, .current = c, @@ -626,26 +585,11 @@ static int run_command(struct command_context *context, .argc = num_words - 1, .argv = words + 1, }; - /* Black magic of overridden current target: - * If the command we are going to handle has a target prefix, - * override the current target temporarily for the time - * of processing the command. - * current_target_override is used also for event handlers - * therefore we prevent touching it if command has no prefix. - * Previous override is saved and restored back to ensure - * correct work when run_command() is re-entered. */ - struct target *saved_target_override = context->current_target_override; - if (c->jim_handler_data) - context->current_target_override = c->jim_handler_data; cmd.output = Jim_NewEmptyStringObj(context->interp); Jim_IncrRefCount(cmd.output); int retval = c->handler(&cmd); - - if (c->jim_handler_data) - context->current_target_override = saved_target_override; - if (retval == ERROR_COMMAND_SYNTAX_ERROR) { /* Print help for command */ char *full_name = command_name(c, ' '); @@ -1053,6 +997,23 @@ static int run_usage(Jim_Interp *interp, int argc_valid, int argc, Jim_Obj * con return retval; } +static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, + struct command *c, int argc, Jim_Obj *const *argv) +{ + if (c->jim_handler) + return c->jim_handler(interp, argc, argv); + + /* use c->handler */ + unsigned int nwords; + char **words = script_command_args_alloc(argc, argv, &nwords); + if (!words) + return JIM_ERR; + + int retval = run_command(cmd_ctx, c, (const char **)words, nwords); + script_command_args_free(words, nwords); + return command_retval_set(interp, retval); +} + static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { script_debug(interp, argc, argv); @@ -1079,15 +1040,32 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) run_usage(interp, count, argc, start); return JIM_ERR; } - /* pass the command through to the intended handler */ - if (c->jim_handler) { - if (!command_can_run(cmd_ctx, c)) - return JIM_ERR; - return (*c->jim_handler)(interp, count, start); - } + if (!command_can_run(cmd_ctx, c)) + return JIM_ERR; - return script_command_run(interp, count, start, c); + target_call_timer_callbacks_now(); + + /* + * Black magic of overridden current target: + * If the command we are going to handle has a target prefix, + * override the current target temporarily for the time + * of processing the command. + * current_target_override is used also for event handlers + * therefore we prevent touching it if command has no prefix. + * Previous override is saved and restored back to ensure + * correct work when command_unknown() is re-entered. + */ + struct target *saved_target_override = cmd_ctx->current_target_override; + if (c->jim_handler_data) + cmd_ctx->current_target_override = c->jim_handler_data; + + int retval = exec_command(interp, cmd_ctx, c, count, start); + + if (c->jim_handler_data) + cmd_ctx->current_target_override = saved_target_override; + + return retval; } static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) From 7cd679a2de697065bbd36cde9042516ccf20f0f1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 12 May 2020 02:36:56 +0200 Subject: [PATCH 08/58] helper/command: get current target from dedicated API Now that target override is uniformly implemented for all types of commands, there is no need for target-prefixed "native" commands (.jim_handler) to sneakily extract the overridden target from the struct command. Modify the commands to use the standard API get_current_target(). Change-Id: I732a09c3261e56524edd5217634fa409eb97a8c6 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5666 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/target/nds32_cmd.c | 25 +++++++++------- src/target/target.c | 65 +++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c index 89da845d3..246dbd034 100644 --- a/src/target/nds32_cmd.c +++ b/src/target/nds32_cmd.c @@ -722,8 +722,9 @@ static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *a return JIM_ERR; } - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); int result; result = target_write_buffer(target, address, count * 4, (const uint8_t *)data); @@ -752,8 +753,9 @@ static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const * if (e != JIM_OK) return e; - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); struct aice_port_s *aice = target_to_aice(target); int result; uint32_t address; @@ -814,8 +816,9 @@ static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *ar if (goi.argc != 0) return JIM_ERR; - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); uint32_t *data = malloc(count * sizeof(uint32_t)); int result; result = target_read_buffer(target, address, count * 4, (uint8_t *)data); @@ -866,8 +869,9 @@ static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const * else return ERROR_FAIL; - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); struct aice_port_s *aice = target_to_aice(target); char data_str[11]; @@ -915,8 +919,9 @@ static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const else return ERROR_FAIL; - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); struct aice_port_s *aice = target_to_aice(target); aice_write_debug_reg(aice, edm_sr_number, value); diff --git a/src/target/target.c b/src/target/target.c index e481d526c..619a8b490 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5206,24 +5206,27 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a "missing: -option ..."); return JIM_ERR; } - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_configure(&goi, target); } static int jim_target_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_mem2array(interp, target, argc - 1, argv + 1); } static int jim_target_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_array2mem(interp, target, argc - 1, argv + 1); } @@ -5255,8 +5258,9 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv allow_defer = true; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5274,8 +5278,9 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); Jim_SetResultBool(interp, target_was_examined(target)); return JIM_OK; @@ -5283,8 +5288,9 @@ static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); Jim_SetResultBool(interp, target->defer_examine); return JIM_OK; @@ -5296,8 +5302,9 @@ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *arg Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) return JIM_ERR; @@ -5311,8 +5318,9 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5349,8 +5357,9 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (e != JIM_OK) return e; - struct command *c = jim_to_command(goi.interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5383,8 +5392,9 @@ static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e = target->type->halt(target); @@ -5414,8 +5424,9 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5459,8 +5470,9 @@ static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); Jim_SetResultString(interp, target_state_name(target), -1); return JIM_OK; } @@ -5479,8 +5491,9 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); return e; } - struct command *c = jim_to_command(interp); - struct target *target = c->jim_handler_data; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); target_handle_event(target, n->value); return JIM_OK; } From 428938993742f4f961cdc948593d9553f721c321 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 12 May 2020 11:52:56 +0200 Subject: [PATCH 09/58] helper/command: override target only on target prefixed cmds In current code the current target is overridden whenever jim_handler_data is not NULL. This happens not only with target prefixed commands, but also with cti, dap and swo/tpiu prefixed commands. While this is not causing any run-time issue, by now, the behaviour is tricky and makes the code cryptic. Add a specific field to struct command for the target override so the content of jim_handler_data can be restricted to command specific data only (today only cti, dap and swo/tpiu). Extend the API register_commands() to specify the presence of either the command data or the override target. The new API makes obsolete calling command_set_handler_data() to set jim_handler_data, so remove it. Change-Id: Icc323faf754b0546a72208f90abd9e68ff2ef52f Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5667 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 22 +++++------- src/helper/command.h | 71 +++++++++++++++++++++++++++++---------- src/target/arm_cti.c | 8 ++--- src/target/arm_dap.c | 8 ++--- src/target/arm_tpiu_swo.c | 6 +--- src/target/target.c | 6 +--- 6 files changed, 69 insertions(+), 52 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index ecca75db6..89e217382 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -391,8 +391,9 @@ static struct command *register_command(struct command_context *context, return c; } -int register_commands(struct command_context *cmd_ctx, struct command *parent, - const struct command_registration *cmds) +int __register_commands(struct command_context *cmd_ctx, struct command *parent, + const struct command_registration *cmds, void *data, + struct target *override_target) { int retval = ERROR_OK; unsigned i; @@ -406,10 +407,12 @@ int register_commands(struct command_context *cmd_ctx, struct command *parent, retval = ERROR_FAIL; break; } + c->jim_handler_data = data; + c->jim_override_target = override_target; } if (NULL != cr->chain) { struct command *p = c ? : parent; - retval = register_commands(cmd_ctx, p, cr->chain); + retval = __register_commands(cmd_ctx, p, cr->chain, data, override_target); if (ERROR_OK != retval) break; } @@ -461,13 +464,6 @@ static int unregister_command(struct command_context *context, return ERROR_OK; } -void command_set_handler_data(struct command *c, void *p) -{ - c->jim_handler_data = p; - for (struct command *cc = c->children; NULL != cc; cc = cc->next) - command_set_handler_data(cc, p); -} - void command_output_text(struct command_context *context, const char *data) { if (context && context->output_handler && data) @@ -1057,12 +1053,12 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * correct work when command_unknown() is re-entered. */ struct target *saved_target_override = cmd_ctx->current_target_override; - if (c->jim_handler_data) - cmd_ctx->current_target_override = c->jim_handler_data; + if (c->jim_override_target) + cmd_ctx->current_target_override = c->jim_override_target; int retval = exec_command(interp, cmd_ctx, c, count, start); - if (c->jim_handler_data) + if (c->jim_override_target) cmd_ctx->current_target_override = saved_target_override; return retval; diff --git a/src/helper/command.h b/src/helper/command.h index cb088d743..871c064d3 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -186,11 +186,9 @@ struct command { command_handler_t handler; Jim_CmdProc *jim_handler; void *jim_handler_data; - /* Currently used only for target of target-prefixed cmd. - * Native OpenOCD commands use jim_handler_data exclusively - * as a target override. - * Jim handlers outside of target cmd tree can use - * jim_handler_data for any handler specific data */ + /* Command handlers can use it for any handler specific data */ + struct target *jim_override_target; + /* Used only for target of target-prefixed cmd */ enum command_mode mode; struct command *next; }; @@ -242,6 +240,10 @@ struct command_registration { /** Use this as the last entry in an array of command_registration records. */ #define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL } +int __register_commands(struct command_context *cmd_ctx, struct command *parent, + const struct command_registration *cmds, void *data, + struct target *override_target); + /** * Register one or more commands in the specified context, as children * of @c parent (or top-level commends, if NULL). In a registration's @@ -257,8 +259,53 @@ struct command_registration { * NULL for all fields. * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ -int register_commands(struct command_context *cmd_ctx, struct command *parent, - const struct command_registration *cmds); +static inline int register_commands(struct command_context *cmd_ctx, struct command *parent, + const struct command_registration *cmds) +{ + return __register_commands(cmd_ctx, parent, cmds, NULL, NULL); +} + +/** + * Register one or more commands, as register_commands(), plus specify + * that command should override the current target + * + * @param cmd_ctx The command_context in which to register the command. + * @param parent Register this command as a child of this, or NULL to + * register a top-level command. + * @param cmds Pointer to an array of command_registration records that + * contains the desired command parameters. The last record must have + * NULL for all fields. + * @param target The target that has to override current target. + * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. + */ +static inline int register_commands_override_target(struct command_context *cmd_ctx, + struct command *parent, const struct command_registration *cmds, + struct target *target) +{ + return __register_commands(cmd_ctx, parent, cmds, NULL, target); +} + +/** + * Register one or more commands, as register_commands(), plus specify + * a pointer to command private data that would be accessible through + * the macro CMD_DATA. The private data will not be freed when command + * is unregistered. + * + * @param cmd_ctx The command_context in which to register the command. + * @param parent Register this command as a child of this, or NULL to + * register a top-level command. + * @param cmds Pointer to an array of command_registration records that + * contains the desired command parameters. The last record must have + * NULL for all fields. + * @param data The command private data. + * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. + */ +static inline int register_commands_with_data(struct command_context *cmd_ctx, + struct command *parent, const struct command_registration *cmds, + void *data) +{ + return __register_commands(cmd_ctx, parent, cmds, data, NULL); +} /** * Unregisters all commands from the specified context. @@ -272,16 +319,6 @@ int unregister_all_commands(struct command_context *cmd_ctx, struct command *command_find_in_context(struct command_context *cmd_ctx, const char *name); -/** - * Update the private command data field for a command and all descendents. - * This is used when creating a new hierarchy of commands that depends - * on obtaining a dynamically created context. The value will be available - * in command handlers by using the CMD_DATA macro. - * @param c The command (group) whose data pointer(s) will be updated. - * @param p The new data pointer to use for the command or its descendents. - */ -void command_set_handler_data(struct command *c, void *p); - void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv); diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 689e9df9f..ee9d8aafd 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -507,17 +507,13 @@ static int cti_create(Jim_GetOptInfo *goi) }, COMMAND_REGISTRATION_DONE }; - e = register_commands(cmd_ctx, NULL, cti_commands); + e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti); if (ERROR_OK != e) return JIM_ERR; - struct command *c = command_find_in_context(cmd_ctx, cp); - assert(c); - command_set_handler_data(c, cti); - list_add_tail(&cti->lh, &all_cti); - return (ERROR_OK == e) ? JIM_OK : JIM_ERR; + return JIM_OK; } static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 56442f183..a9277e798 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -265,17 +265,13 @@ static int dap_create(Jim_GetOptInfo *goi) if (transport_is_hla()) dap_commands[0].chain = NULL; - e = register_commands(cmd_ctx, NULL, dap_commands); + e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap); if (ERROR_OK != e) return JIM_ERR; - struct command *c = command_find_in_context(cmd_ctx, cp); - assert(c); - command_set_handler_data(c, dap); - list_add_tail(&dap->lh, &all_dap); - return (ERROR_OK == e) ? JIM_OK : JIM_ERR; + return JIM_OK; } static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 543b4f008..186ce5d0e 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -886,14 +886,10 @@ static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *o }, COMMAND_REGISTRATION_DONE }; - e = register_commands(cmd_ctx, NULL, obj_commands); + e = register_commands_with_data(cmd_ctx, NULL, obj_commands, obj); if (ERROR_OK != e) return JIM_ERR; - struct command *c = command_find_in_context(cmd_ctx, obj->name); - assert(c); - command_set_handler_data(c, obj); - list_add_tail(&obj->lh, &all_tpiu_swo); return JIM_OK; diff --git a/src/target/target.c b/src/target/target.c index 619a8b490..fa033d351 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5871,7 +5871,7 @@ static int target_create(Jim_GetOptInfo *goi) }, COMMAND_REGISTRATION_DONE }; - e = register_commands(cmd_ctx, NULL, target_commands); + e = register_commands_override_target(cmd_ctx, NULL, target_commands, target); if (e != ERROR_OK) { if (target->type->deinit_target) target->type->deinit_target(target); @@ -5884,10 +5884,6 @@ static int target_create(Jim_GetOptInfo *goi) return JIM_ERR; } - struct command *c = command_find_in_context(cmd_ctx, cp); - assert(c); - command_set_handler_data(c, target); - /* append to end of list */ append_to_list_all_targets(target); From 41c95aa4ea1506a951dad0147f6cd4b8d7043358 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 May 2020 19:35:56 +0200 Subject: [PATCH 10/58] helper/command: pass command prefix to command registration Replace the "struct command *parent" parameter with a string that contains the command prefix. This abstracts the openocd code from the knowledge of the tree of struct command. This also makes unused the function command_find_in_context(), so remove it. Change-Id: I598d60719cfdc1811ee6f6edfff8a116f82c7ed6 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5668 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nand/tcl.c | 4 ++-- src/flash/nor/esirisc_flash.c | 4 +--- src/flash/nor/tcl.c | 3 +-- src/helper/command.c | 22 ++++++++++++++-------- src/helper/command.h | 23 ++++++++++------------- src/pld/pld.c | 3 +-- src/target/etm.c | 3 +-- 7 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c index ca8b9dad4..9e0ca41ac 100644 --- a/src/flash/nand/tcl.c +++ b/src/flash/nand/tcl.c @@ -479,8 +479,8 @@ static int nand_init(struct command_context *cmd_ctx) { if (!nand_devices) return ERROR_OK; - struct command *parent = command_find_in_context(cmd_ctx, "nand"); - return register_commands(cmd_ctx, parent, nand_exec_command_handlers); + + return register_commands(cmd_ctx, "nand", nand_exec_command_handlers); } COMMAND_HANDLER(handle_nand_init_command) diff --git a/src/flash/nor/esirisc_flash.c b/src/flash/nor/esirisc_flash.c index 88f00bcca..24e811704 100644 --- a/src/flash/nor/esirisc_flash.c +++ b/src/flash/nor/esirisc_flash.c @@ -109,7 +109,6 @@ static const struct command_registration esirisc_flash_command_handlers[]; FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command) { struct esirisc_flash_bank *esirisc_info; - struct command *esirisc_cmd; if (CMD_ARGC < 9) return ERROR_COMMAND_SYNTAX_ERROR; @@ -123,8 +122,7 @@ FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command) bank->driver_priv = esirisc_info; /* register commands using existing esirisc context */ - esirisc_cmd = command_find_in_context(CMD_CTX, "esirisc"); - register_commands(CMD_CTX, esirisc_cmd, esirisc_flash_command_handlers); + register_commands(CMD_CTX, "esirisc", esirisc_flash_command_handlers); return ERROR_OK; } diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 66b9a4cb6..3f737aca3 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1248,8 +1248,7 @@ static int flash_init_drivers(struct command_context *cmd_ctx) if (!flash_bank_list()) return ERROR_OK; - struct command *parent = command_find_in_context(cmd_ctx, "flash"); - return register_commands(cmd_ctx, parent, flash_exec_command_handlers); + return register_commands(cmd_ctx, "flash", flash_exec_command_handlers); } COMMAND_HANDLER(handle_flash_bank_command) diff --git a/src/helper/command.c b/src/helper/command.c index 89e217382..114d07328 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -244,12 +244,6 @@ static struct command *command_find(struct command *head, const char *name) return NULL; } -struct command *command_find_in_context(struct command_context *cmd_ctx, - const char *name) -{ - return command_find(cmd_ctx->commands, name); -} - /** * Add the command into the linked list, sorted by name. * @param head Address to head of command list pointer, which may be @@ -391,7 +385,7 @@ static struct command *register_command(struct command_context *context, return c; } -int __register_commands(struct command_context *cmd_ctx, struct command *parent, +static int ___register_commands(struct command_context *cmd_ctx, struct command *parent, const struct command_registration *cmds, void *data, struct target *override_target) { @@ -412,7 +406,7 @@ int __register_commands(struct command_context *cmd_ctx, struct command *parent, } if (NULL != cr->chain) { struct command *p = c ? : parent; - retval = __register_commands(cmd_ctx, p, cr->chain, data, override_target); + retval = ___register_commands(cmd_ctx, p, cr->chain, data, override_target); if (ERROR_OK != retval) break; } @@ -424,6 +418,18 @@ int __register_commands(struct command_context *cmd_ctx, struct command *parent, return retval; } +int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, + const struct command_registration *cmds, void *data, + struct target *override_target) +{ + struct command *parent = NULL; + + if (cmd_prefix) + parent = command_find(cmd_ctx->commands, cmd_prefix); + + return ___register_commands(cmd_ctx, parent, cmds, data, override_target); +} + int unregister_all_commands(struct command_context *context, struct command *parent) { diff --git a/src/helper/command.h b/src/helper/command.h index 871c064d3..9a04e9fa1 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -240,7 +240,7 @@ struct command_registration { /** Use this as the last entry in an array of command_registration records. */ #define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL } -int __register_commands(struct command_context *cmd_ctx, struct command *parent, +int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds, void *data, struct target *override_target); @@ -252,17 +252,17 @@ int __register_commands(struct command_context *cmd_ctx, struct command *parent, * Otherwise, the chained commands are added as children of the command. * * @param cmd_ctx The command_context in which to register the command. - * @param parent Register this command as a child of this, or NULL to + * @param cmd_prefix Register this command as a child of this, or NULL to * register a top-level command. * @param cmds Pointer to an array of command_registration records that * contains the desired command parameters. The last record must have * NULL for all fields. * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ -static inline int register_commands(struct command_context *cmd_ctx, struct command *parent, +static inline int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds) { - return __register_commands(cmd_ctx, parent, cmds, NULL, NULL); + return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, NULL); } /** @@ -270,7 +270,7 @@ static inline int register_commands(struct command_context *cmd_ctx, struct comm * that command should override the current target * * @param cmd_ctx The command_context in which to register the command. - * @param parent Register this command as a child of this, or NULL to + * @param cmd_prefix Register this command as a child of this, or NULL to * register a top-level command. * @param cmds Pointer to an array of command_registration records that * contains the desired command parameters. The last record must have @@ -279,10 +279,10 @@ static inline int register_commands(struct command_context *cmd_ctx, struct comm * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ static inline int register_commands_override_target(struct command_context *cmd_ctx, - struct command *parent, const struct command_registration *cmds, + const char *cmd_prefix, const struct command_registration *cmds, struct target *target) { - return __register_commands(cmd_ctx, parent, cmds, NULL, target); + return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, target); } /** @@ -292,7 +292,7 @@ static inline int register_commands_override_target(struct command_context *cmd_ * is unregistered. * * @param cmd_ctx The command_context in which to register the command. - * @param parent Register this command as a child of this, or NULL to + * @param cmd_prefix Register this command as a child of this, or NULL to * register a top-level command. * @param cmds Pointer to an array of command_registration records that * contains the desired command parameters. The last record must have @@ -301,10 +301,10 @@ static inline int register_commands_override_target(struct command_context *cmd_ * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ static inline int register_commands_with_data(struct command_context *cmd_ctx, - struct command *parent, const struct command_registration *cmds, + const char *cmd_prefix, const struct command_registration *cmds, void *data) { - return __register_commands(cmd_ctx, parent, cmds, data, NULL); + return __register_commands(cmd_ctx, cmd_prefix, cmds, data, NULL); } /** @@ -316,9 +316,6 @@ static inline int register_commands_with_data(struct command_context *cmd_ctx, int unregister_all_commands(struct command_context *cmd_ctx, struct command *parent); -struct command *command_find_in_context(struct command_context *cmd_ctx, - const char *name); - void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv); diff --git a/src/pld/pld.c b/src/pld/pld.c index ef7993c5d..9e8c07d80 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -187,8 +187,7 @@ static int pld_init(struct command_context *cmd_ctx) if (!pld_devices) return ERROR_OK; - struct command *parent = command_find_in_context(cmd_ctx, "pld"); - return register_commands(cmd_ctx, parent, pld_exec_command_handlers); + return register_commands(cmd_ctx, "pld", pld_exec_command_handlers); } COMMAND_HANDLER(handle_pld_init_command) diff --git a/src/target/etm.c b/src/target/etm.c index 19f3691bd..6dc2bd48c 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -2107,6 +2107,5 @@ static const struct command_registration etm_exec_command_handlers[] = { static int etm_register_user_commands(struct command_context *cmd_ctx) { - struct command *etm_cmd = command_find_in_context(cmd_ctx, "etm"); - return register_commands(cmd_ctx, etm_cmd, etm_exec_command_handlers); + return register_commands(cmd_ctx, "etm", etm_exec_command_handlers); } From cb83bc747ce1106c50d713f6d552da8c3e476e0f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 May 2020 02:00:45 +0200 Subject: [PATCH 11/58] command mode: return "any" for tcl proc A tcl proc can be executed anytime, in any command mode. Let the command "command mode" to detect a tcl proc and return the string "any". Change-Id: I0559076c3063632ee0ea9a57a25f91060209b77f Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5669 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/helper/command.c b/src/helper/command.c index 114d07328..288ba99aa 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -53,6 +53,12 @@ static int unregister_command(struct command_context *context, struct command *parent, const char *name); static char *command_name(struct command *c, char delim); +/* wrap jimtcl internal data */ +static inline bool jimcmd_is_proc(Jim_Cmd *cmd) +{ + return cmd->isproc; +} + static void tcl_output(void *privData, const char *file, unsigned line, const char *function, const char *string) { @@ -1076,6 +1082,18 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) enum command_mode mode; if (argc > 1) { + char *full_name = alloc_concatenate_strings(argc - 1, argv + 1); + if (!full_name) + return JIM_ERR; + Jim_Obj *s = Jim_NewStringObj(interp, full_name, -1); + Jim_IncrRefCount(s); + Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); + Jim_DecrRefCount(interp, s); + free(full_name); + if (cmd && jimcmd_is_proc(cmd)) { + Jim_SetResultString(interp, "any", -1); + return JIM_OK; + } struct command *c = cmd_ctx->commands; int remaining = command_unknown_find(argc - 1, argv + 1, c, &c); /* if nothing could be consumed, then it's an unknown command */ From aacc26559e4984b649083ac046db2cbcb54e2f70 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 27 Mar 2021 16:12:11 +0100 Subject: [PATCH 12/58] help: re-implement 'help' independent from tree of struct command The current implementation of "help" related commands is tightly connected to the tree of struct command. The TCL commands 'add_usage_text' and 'add_help_text' have to add fake commands in the tree of struct command to handle the help of TCL procs. Move all the help texts in a list accessible from the struct command_context and register the commands through their full name. Keep the list sorted alphabetically by the command name, so the result of commands 'help' and 'usage' will be sorted too. Remove the associated help and usage during commands un-register, but call help_del_all_commands() for the text added through TCL commands 'add_usage_text' and 'add_help_text'. The resulting help and usage output is not changed by this patch (tested on all the help and usage strings in current master branch). Change-Id: Ifd37bb5bd374cba1a22cd7aac208505b4ae1e6fc Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5670 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 240 +++++++++++++++++++++++++------------------ src/helper/command.h | 13 ++- src/openocd.c | 1 + 3 files changed, 150 insertions(+), 104 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 288ba99aa..3b531807f 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -52,6 +52,9 @@ struct log_capture_state { static int unregister_command(struct command_context *context, struct command *parent, const char *name); static char *command_name(struct command *c, char delim); +static int help_add_command(struct command_context *cmd_ctx, + const char *cmd_name, const char *help_text, const char *usage_text); +static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name); /* wrap jimtcl internal data */ static inline bool jimcmd_is_proc(Jim_Cmd *cmd) @@ -293,8 +296,6 @@ static void command_free(struct command *c) } free(c->name); - free(c->help); - free(c->usage); free(c); } @@ -323,12 +324,7 @@ static struct command *command_new(struct command_context *cmd_ctx, return NULL; c->name = strdup(cr->name); - if (cr->help) - c->help = strdup(cr->help); - if (cr->usage) - c->usage = strdup(cr->usage); - - if (!c->name || (cr->help && !c->help) || (cr->usage && !c->usage)) + if (!c->name) goto command_new_error; c->parent = parent; @@ -338,6 +334,12 @@ static struct command *command_new(struct command_context *cmd_ctx, command_add_child(command_list_for_parent(cmd_ctx, parent), c); + if (cr->help || cr->usage) { + char *full_name = command_name(c, ' '); + help_add_command(cmd_ctx, full_name, cr->help, cr->usage); + free(full_name); + } + return c; command_new_error: @@ -464,6 +466,10 @@ static int unregister_command(struct command_context *context, if (strcmp(name, c->name) != 0) continue; + char *full_name = command_name(c, ' '); + help_del_command(context, full_name); + free(full_name); + if (p) p->next = c->next; else @@ -785,28 +791,22 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return retcode; } -static COMMAND_HELPER(command_help_find, struct command *head, - struct command **out) -{ - if (0 == CMD_ARGC) - return ERROR_COMMAND_SYNTAX_ERROR; - *out = command_find(head, CMD_ARGV[0]); - if (NULL == *out) - return ERROR_COMMAND_SYNTAX_ERROR; - if (--CMD_ARGC == 0) - return ERROR_OK; - CMD_ARGV++; - return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out); -} +struct help_entry { + struct list_head lh; + char *cmd_name; + char *help; + char *usage; +}; -static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, +static COMMAND_HELPER(command_help_show, struct help_entry *c, bool show_help, const char *cmd_match); -static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n, - bool show_help, const char *cmd_match) +static COMMAND_HELPER(command_help_show_list, bool show_help, const char *cmd_match) { - for (struct command *c = head; NULL != c; c = c->next) - CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, cmd_match); + struct help_entry *entry; + + list_for_each_entry(entry, CMD_CTX->help_list, lh) + CALL_COMMAND_HANDLER(command_help_show, entry, show_help, cmd_match); return ERROR_OK; } @@ -837,26 +837,23 @@ static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) } } -static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, +static COMMAND_HELPER(command_help_show, struct help_entry *c, bool show_help, const char *cmd_match) { - char *cmd_name = command_name(c, ' '); - if (NULL == cmd_name) - return ERROR_FAIL; + unsigned int n = 0; + for (const char *s = strchr(c->cmd_name, ' '); s; s = strchr(s + 1, ' ')) + n++; /* If the match string occurs anywhere, we print out * stuff for this command. */ - bool is_match = (strstr(cmd_name, cmd_match) != NULL) || + bool is_match = (strstr(c->cmd_name, cmd_match) != NULL) || ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) || ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL)); if (is_match) { command_help_show_indent(n); - LOG_USER_N("%s", cmd_name); - } - free(cmd_name); + LOG_USER_N("%s", c->cmd_name); - if (is_match) { if (c->usage && strlen(c->usage) > 0) { LOG_USER_N(" "); command_help_show_wrap(c->usage, 0, n + 5); @@ -867,11 +864,30 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, if (is_match && show_help) { char *msg; + /* TODO: factorize jim_command_mode() to avoid running jim command here */ + char *request = alloc_printf("command mode %s", c->cmd_name); + if (!request) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + int retval = Jim_Eval(CMD_CTX->interp, request); + free(request); + enum command_mode mode = COMMAND_UNKNOWN; + if (retval != JIM_ERR) { + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL); + if (!strcmp(result, "any")) + mode = COMMAND_ANY; + else if (!strcmp(result, "config")) + mode = COMMAND_CONFIG; + else if (!strcmp(result, "exec")) + mode = COMMAND_EXEC; + } + /* Normal commands are runtime-only; highlight exceptions */ - if (c->mode != COMMAND_EXEC) { + if (mode != COMMAND_EXEC) { const char *stage_msg = ""; - switch (c->mode) { + switch (mode) { case COMMAND_CONFIG: stage_msg = " (configuration command)"; break; @@ -893,20 +909,13 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, return -ENOMEM; } - if (++n > 5) { - LOG_ERROR("command recursion exceeded"); - return ERROR_FAIL; - } - - return CALL_COMMAND_HANDLER(command_help_show_list, - c->children, n, show_help, cmd_match); + return ERROR_OK; } COMMAND_HANDLER(handle_help_command) { bool full = strcmp(CMD_NAME, "help") == 0; int retval; - struct command *c = CMD_CTX->commands; char *cmd_match; if (CMD_ARGC <= 0) @@ -926,8 +935,7 @@ COMMAND_HANDLER(handle_help_command) LOG_ERROR("unable to build search string"); return -ENOMEM; } - retval = CALL_COMMAND_HANDLER(command_help_show_list, - c, 0, full, cmd_match); + retval = CALL_COMMAND_HANDLER(command_help_show_list, full, cmd_match); free(cmd_match); return retval; @@ -1124,81 +1132,104 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } -int help_add_command(struct command_context *cmd_ctx, struct command *parent, - const char *cmd_name, const char *help_text, const char *usage) +int help_del_all_commands(struct command_context *cmd_ctx) { - struct command **head = command_list_for_parent(cmd_ctx, parent); - struct command *nc = command_find(*head, cmd_name); - if (NULL == nc) { - /* add a new command with help text */ - struct command_registration cr = { - .name = cmd_name, - .mode = COMMAND_ANY, - .help = help_text, - .usage = usage ? : "", - }; - nc = register_command(cmd_ctx, parent, &cr); - if (NULL == nc) { - LOG_ERROR("failed to add '%s' help text", cmd_name); + struct help_entry *curr, *n; + + list_for_each_entry_safe(curr, n, cmd_ctx->help_list, lh) { + list_del(&curr->lh); + free(curr->cmd_name); + free(curr->help); + free(curr->usage); + free(curr); + } + return ERROR_OK; +} + +static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name) +{ + struct help_entry *curr; + + list_for_each_entry(curr, cmd_ctx->help_list, lh) { + if (!strcmp(cmd_name, curr->cmd_name)) { + list_del(&curr->lh); + free(curr->cmd_name); + free(curr->help); + free(curr->usage); + free(curr); + break; + } + } + + return ERROR_OK; +} + +static int help_add_command(struct command_context *cmd_ctx, + const char *cmd_name, const char *help_text, const char *usage_text) +{ + int cmp = -1; /* add after curr */ + struct help_entry *curr; + + list_for_each_entry_reverse(curr, cmd_ctx->help_list, lh) { + cmp = strcmp(cmd_name, curr->cmd_name); + if (cmp >= 0) + break; + } + + struct help_entry *entry; + if (cmp) { + entry = calloc(1, sizeof(*entry)); + if (!entry) { + LOG_ERROR("Out of memory"); return ERROR_FAIL; } - LOG_DEBUG("added '%s' help text", cmd_name); - return ERROR_OK; + entry->cmd_name = strdup(cmd_name); + if (!entry->cmd_name) { + LOG_ERROR("Out of memory"); + free(entry); + return ERROR_FAIL; + } + list_add(&entry->lh, &curr->lh); + } else { + entry = curr; } + if (help_text) { - bool replaced = false; - if (nc->help) { - free(nc->help); - replaced = true; + char *text = strdup(help_text); + if (!text) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; } - nc->help = strdup(help_text); - if (replaced) - LOG_INFO("replaced existing '%s' help", cmd_name); - else - LOG_DEBUG("added '%s' help text", cmd_name); + free(entry->help); + entry->help = text; } - if (usage) { - bool replaced = false; - if (nc->usage) { - if (*nc->usage) - replaced = true; - free(nc->usage); + + if (usage_text) { + char *text = strdup(usage_text); + if (!text) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; } - nc->usage = strdup(usage); - if (replaced) - LOG_INFO("replaced existing '%s' usage", cmd_name); - else - LOG_DEBUG("added '%s' usage text", cmd_name); + free(entry->usage); + entry->usage = text; } + return ERROR_OK; } COMMAND_HANDLER(handle_help_add_command) { - if (CMD_ARGC < 2) { - LOG_ERROR("%s: insufficient arguments", CMD_NAME); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } - /* save help text and remove it from argument list */ - const char *str = CMD_ARGV[--CMD_ARGC]; - const char *help = !strcmp(CMD_NAME, "add_help_text") ? str : NULL; - const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? str : NULL; + const char *help = !strcmp(CMD_NAME, "add_help_text") ? CMD_ARGV[1] : NULL; + const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? CMD_ARGV[1] : NULL; if (!help && !usage) { LOG_ERROR("command name '%s' is unknown", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } - /* likewise for the leaf command name */ - const char *cmd_name = CMD_ARGV[--CMD_ARGC]; - - struct command *c = NULL; - if (CMD_ARGC > 0) { - c = CMD_CTX->commands; - int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c); - if (ERROR_OK != retval) - return retval; - } - return help_add_command(CMD_CTX, c, cmd_name, help, usage); + const char *cmd_name = CMD_ARGV[0]; + return help_add_command(CMD_CTX, cmd_name, help, usage); } /* sleep command sleeps for milliseconds @@ -1329,6 +1360,10 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp context->mode = COMMAND_EXEC; + /* context can be duplicated. Put list head on separate mem-chunk to keep list consistent */ + context->help_list = malloc(sizeof(*context->help_list)); + INIT_LIST_HEAD(context->help_list); + /* Create a jim interpreter if we were not handed one */ if (interp == NULL) { /* Create an interpreter */ @@ -1393,6 +1428,7 @@ void command_exit(struct command_context *context) return; Jim_FreeInterp(context->interp); + free(context->help_list); command_done(context); } diff --git a/src/helper/command.h b/src/helper/command.h index 9a04e9fa1..db095972a 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -26,6 +26,7 @@ #include #include +#include #include /* To achieve C99 printf compatibility in MinGW, gnu_printf should be @@ -41,6 +42,7 @@ enum command_mode { COMMAND_EXEC, COMMAND_CONFIG, COMMAND_ANY, + COMMAND_UNKNOWN = -1, /* error condition */ }; struct command_context; @@ -64,6 +66,7 @@ struct command_context { */ command_output_handler_t output_handler; void *output_handler_priv; + struct list_head *help_list; }; struct command; @@ -179,8 +182,6 @@ typedef __COMMAND_HANDLER((*command_handler_t)); struct command { char *name; - char *help; - char *usage; struct command *parent; struct command *children; command_handler_t handler; @@ -316,6 +317,14 @@ static inline int register_commands_with_data(struct command_context *cmd_ctx, int unregister_all_commands(struct command_context *cmd_ctx, struct command *parent); +/** + * Unregisters the help for all commands. Used at exit to remove the help + * added through the commands 'add_help_text' and 'add_usage_text'. + * @param cmd_ctx The context that will be cleared of registered helps. + * @returns ERROR_OK on success, or an error code. + */ +int help_del_all_commands(struct command_context *cmd_ctx); + void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv); diff --git a/src/openocd.c b/src/openocd.c index fcefdbe70..32b68b6fc 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -361,6 +361,7 @@ int openocd_main(int argc, char *argv[]) server_free(); unregister_all_commands(cmd_ctx, NULL); + help_del_all_commands(cmd_ctx); /* free all DAP and CTI objects */ dap_cleanup_all(); From e216186fab59d71fdee24af926d1807a1d7fc950 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 13 May 2020 01:59:59 +0200 Subject: [PATCH 13/58] helper/command: register full-name commands in jim While still keeping the tree of struct command, stop registering commands in jim by the root "word" only. Register the full-name of the command and pass as private data the struct command of the command itself. Still use the tree of struct command to un-register the commands. Some "native" commands (.jim_handler) share the same handler, then the handler checks the command name to run the right code. Now argv[0] returns the full-name of the command, so check the name by looking in the struct command passed as private data. Change-Id: I5623c61cceee8a75f5d5a551ef3fbf5a303af6be Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5671 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 111 ++++++++++---------------------------- src/jtag/tcl.c | 6 ++- src/target/aarch64.c | 3 +- src/target/arm_tpiu_swo.c | 4 +- src/target/target.c | 3 +- 5 files changed, 39 insertions(+), 88 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 3b531807f..41b86796a 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -232,13 +232,6 @@ struct command_context *current_command_context(Jim_Interp *interp) return cmd_ctx; } -static struct command *command_root(struct command *c) -{ - while (NULL != c->parent) - c = c->parent; - return c; -} - /** * Find a command by name from a list of commands. * @returns Returns the named command if it exists in the list. @@ -349,18 +342,6 @@ command_new_error: static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -static int register_command_handler(struct command_context *cmd_ctx, - struct command *c) -{ - Jim_Interp *interp = cmd_ctx->interp; - -#if 0 - LOG_DEBUG("registering '%s'...", c->name); -#endif - - return Jim_CreateCommand(interp, c->name, command_unknown, c, NULL); -} - static struct command *register_command(struct command_context *context, struct command *parent, const struct command_registration *cr) { @@ -383,12 +364,13 @@ static struct command *register_command(struct command_context *context, if (NULL == c) return NULL; - if (cr->jim_handler || cr->handler) { - int retval = register_command_handler(context, command_root(c)); - if (retval != JIM_OK) { - unregister_command(context, parent, name); - return NULL; - } + char *full_name = command_name(c, ' '); + LOG_DEBUG("registering '%s'...", full_name); + int retval = Jim_CreateCommand(context->interp, full_name, + command_unknown, c, NULL); + if (retval != JIM_OK) { + unregister_command(context, parent, name); + return NULL; } return c; } @@ -563,7 +545,7 @@ static char *command_name(struct command *c, char delim) return __command_name(c, delim, 0); } -static bool command_can_run(struct command_context *cmd_ctx, struct command *c) +static bool command_can_run(struct command_context *cmd_ctx, struct command *c, const char *full_name) { if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode) return true; @@ -582,10 +564,8 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c) when = "if Cthulhu is summoned by"; break; } - char *full_name = command_name(c, ' '); LOG_ERROR("The '%s' command must be used %s 'init'.", full_name ? full_name : c->name, when); - free(full_name); return false; } @@ -980,41 +960,8 @@ static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv) return all; } -static int run_usage(Jim_Interp *interp, int argc_valid, int argc, Jim_Obj * const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - char *command; - int retval; - - assert(argc_valid >= 1); - assert(argc >= argc_valid); - - command = alloc_concatenate_strings(argc_valid, argv); - if (!command) - return JIM_ERR; - - retval = command_run_linef(cmd_ctx, "usage %s", command); - if (retval != ERROR_OK) { - LOG_ERROR("unable to execute command \"usage %s\"", command); - return JIM_ERR; - } - - if (argc_valid == argc) - LOG_ERROR("%s: command requires more arguments", command); - else { - free(command); - command = alloc_concatenate_strings(argc - argc_valid, argv + argc_valid); - if (!command) - return JIM_ERR; - LOG_ERROR("invalid subcommand \"%s\"", command); - } - - free(command); - return retval; -} - static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, - struct command *c, int argc, Jim_Obj *const *argv) + struct command *c, int argc, Jim_Obj * const *argv) { if (c->jim_handler) return c->jim_handler(interp, argc, argv); @@ -1034,30 +981,30 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { script_debug(interp, argc, argv); - struct command_context *cmd_ctx = current_command_context(interp); - struct command *c = cmd_ctx->commands; - int remaining = command_unknown_find(argc, argv, c, &c); - /* if nothing could be consumed, then it's really an unknown command */ - if (remaining == argc) { - const char *cmd = Jim_GetString(argv[0], NULL); - LOG_ERROR("Unknown command:\n %s", cmd); - return JIM_OK; + /* check subcommands */ + if (argc > 1) { + char *s = alloc_printf("%s %s", Jim_GetString(argv[0], NULL), Jim_GetString(argv[1], NULL)); + Jim_Obj *js = Jim_NewStringObj(interp, s, -1); + Jim_IncrRefCount(js); + free(s); + Jim_Cmd *cmd = Jim_GetCommand(interp, js, JIM_NONE); + if (cmd) { + int retval = Jim_EvalObjPrefix(interp, js, argc - 2, argv + 2); + Jim_DecrRefCount(interp, js); + return retval; + } + Jim_DecrRefCount(interp, js); } - Jim_Obj *const *start; - unsigned count; - if (c->handler || c->jim_handler) { - /* include the command name in the list */ - count = remaining + 1; - start = argv + (argc - remaining - 1); - } else { - count = argc - remaining; - start = argv; - run_usage(interp, count, argc, start); + struct command *c = jim_to_command(interp); + if (!c->jim_handler && !c->handler) { + Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv); return JIM_ERR; } - if (!command_can_run(cmd_ctx, c)) + struct command_context *cmd_ctx = current_command_context(interp); + + if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL))) return JIM_ERR; target_call_timer_callbacks_now(); @@ -1076,7 +1023,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (c->jim_override_target) cmd_ctx->current_target_override = c->jim_override_target; - int retval = exec_command(interp, cmd_ctx, c, count, start); + int retval = exec_command(interp, cmd_ctx, c, argc, argv); if (c->jim_override_target) cmd_ctx->current_target_override = saved_target_override; diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 2fa162e56..bf65e8119 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -767,7 +767,8 @@ static bool jtag_tap_disable(struct jtag_tap *t) int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - const char *cmd_name = Jim_GetString(argv[0], NULL); + struct command *c = jim_to_command(interp); + const char *cmd_name = c->name; Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); if (goi.argc != 1) { @@ -804,7 +805,8 @@ int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - const char *cmd_name = Jim_GetString(argv[0], NULL); + struct command *c = jim_to_command(interp); + const char *cmd_name = c->name; Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); goi.isconfigure = !strcmp(cmd_name, "configure"); diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 46ed49f68..4ba92c8a0 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2966,6 +2966,7 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command) static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { + struct command *c = jim_to_command(interp); struct command_context *context; struct target *target; struct arm *arm; @@ -2973,7 +2974,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) bool is_mcr = false; int arg_cnt = 0; - if (Jim_CompareStringImmediate(interp, argv[0], "mcr")) { + if (!strcmp(c->name, "mcr")) { is_mcr = true; arg_cnt = 7; } else { diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 186ce5d0e..f93508622 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -550,16 +550,16 @@ err_no_params: static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { + struct command *c = jim_to_command(interp); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); + goi.isconfigure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); return JIM_ERR; } - struct command *c = jim_to_command(interp); struct arm_tpiu_swo_object *obj = c->jim_handler_data; return arm_tpiu_swo_configure(&goi, obj); } diff --git a/src/target/target.c b/src/target/target.c index fa033d351..e9d67702e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5197,10 +5197,11 @@ no_params: static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { + struct command *c = jim_to_command(interp); Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); + goi.isconfigure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); From f238337c9c2fdabb48992487e5243d03d32e215d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 13 May 2020 02:30:11 +0200 Subject: [PATCH 14/58] helper/command: simplify run_command() Now that the commands are registered using their full-name, the full-name is in argv[0]. Don't rebuild the full-name but use directly argv[0]. Change-Id: Ic9e469ac39276367b8c47527e70791ff470fefbc Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5672 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 41b86796a..1628b6ee7 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -586,20 +586,13 @@ static int run_command(struct command_context *context, int retval = c->handler(&cmd); if (retval == ERROR_COMMAND_SYNTAX_ERROR) { /* Print help for command */ - char *full_name = command_name(c, ' '); - if (NULL != full_name) { - command_run_linef(context, "usage %s", full_name); - free(full_name); - } + command_run_linef(context, "usage %s", words[0]); } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) { /* just fall through for a shutdown request */ } else { - if (retval != ERROR_OK) { - char *full_name = command_name(c, ' '); + if (retval != ERROR_OK) LOG_DEBUG("Command '%s' failed with error code %d", - full_name ? full_name : c->name, retval); - free(full_name); - } + words[0], retval); /* Use the command output as the Tcl result */ Jim_SetResult(context->interp, cmd.output); } From d8d24f3b3696f5d2e64a67df87684132b48031d2 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 May 2020 17:48:25 +0200 Subject: [PATCH 15/58] helper/command: simplify jim_command_mode() Now that every command has struct command as private data, use jim to get access to the struct command to read the command mode, instead of running through the tree of struct command. Change-Id: Iddacdbac604714f6abe38a050daad245bdcfd20c Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5673 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 47 +++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 1628b6ee7..5cddf2150 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -52,16 +52,27 @@ struct log_capture_state { static int unregister_command(struct command_context *context, struct command *parent, const char *name); static char *command_name(struct command *c, char delim); +static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj * const *argv); static int help_add_command(struct command_context *cmd_ctx, const char *cmd_name, const char *help_text, const char *usage_text); static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name); -/* wrap jimtcl internal data */ +/* set of functions to wrap jimtcl internal data */ static inline bool jimcmd_is_proc(Jim_Cmd *cmd) { return cmd->isproc; } +static inline bool jimcmd_is_ocd_command(Jim_Cmd *cmd) +{ + return !cmd->isproc && cmd->u.native.cmdProc == command_unknown; +} + +static inline void *jimcmd_privdata(Jim_Cmd *cmd) +{ + return cmd->isproc ? NULL : cmd->u.native.privData; +} + static void tcl_output(void *privData, const char *file, unsigned line, const char *function, const char *string) { @@ -340,8 +351,6 @@ command_new_error: return NULL; } -static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv); - static struct command *register_command(struct command_context *context, struct command *parent, const struct command_registration *cr) { @@ -914,19 +923,6 @@ COMMAND_HANDLER(handle_help_command) return retval; } -static int command_unknown_find(unsigned argc, Jim_Obj *const *argv, - struct command *head, struct command **out) -{ - if (0 == argc) - return argc; - const char *cmd_name = Jim_GetString(argv[0], NULL); - struct command *c = command_find(head, cmd_name); - if (NULL == c) - return argc; - *out = c; - return command_unknown_find(--argc, ++argv, (*out)->children, out); -} - static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv) { char *prev, *all; @@ -1038,18 +1034,19 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); Jim_DecrRefCount(interp, s); free(full_name); - if (cmd && jimcmd_is_proc(cmd)) { - Jim_SetResultString(interp, "any", -1); - return JIM_OK; - } - struct command *c = cmd_ctx->commands; - int remaining = command_unknown_find(argc - 1, argv + 1, c, &c); - /* if nothing could be consumed, then it's an unknown command */ - if (remaining == argc - 1) { + if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_ocd_command(cmd))) { Jim_SetResultString(interp, "unknown", -1); return JIM_OK; } - mode = c->mode; + + if (jimcmd_is_proc(cmd)) { + /* tcl proc */ + mode = COMMAND_ANY; + } else { + struct command *c = jimcmd_privdata(cmd); + + mode = c->mode; + } } else mode = cmd_ctx->mode; From a7d68878e4ba5dfd5ca15c058980cf6c5fc55208 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 13 May 2020 15:35:19 +0200 Subject: [PATCH 16/58] helper/command: unregister commands through their full-name While keeping the struct command in place, unregister the jim commands by scanning the list of jim commands through their full-name. Change-Id: I0e903fbc31172858b703d67ccd471809c7949e86 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5674 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 100 +++++++++++++++++++++++++++++++++++++++++-- src/helper/command.h | 4 +- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 5cddf2150..d79d7f464 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -243,6 +243,26 @@ struct command_context *current_command_context(Jim_Interp *interp) return cmd_ctx; } +/** + * Find a openocd command from fullname. + * @returns Returns the named command if it is registred in interp. + * Returns NULL otherwise. + */ +static struct command *command_find_from_name(Jim_Interp *interp, const char *name) +{ + if (!name) + return NULL; + + Jim_Obj *jim_name = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(jim_name); + Jim_Cmd *cmd = Jim_GetCommand(interp, jim_name, JIM_NONE); + Jim_DecrRefCount(interp, jim_name); + if (!cmd || jimcmd_is_proc(cmd) || !jimcmd_is_ocd_command(cmd)) + return NULL; + + return jimcmd_privdata(cmd); +} + /** * Find a command by name from a list of commands. * @returns Returns the named command if it exists in the list. @@ -429,12 +449,80 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, return ___register_commands(cmd_ctx, parent, cmds, data, override_target); } -int unregister_all_commands(struct command_context *context, - struct command *parent) +static __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))) +int unregister_commands_match(struct command_context *cmd_ctx, const char *format, ...) { - if (context == NULL) + Jim_Interp *interp = cmd_ctx->interp; + va_list ap; + + va_start(ap, format); + char *query = alloc_vprintf(format, ap); + va_end(ap); + if (!query) + return ERROR_FAIL; + + char *query_cmd = alloc_printf("info commands {%s}", query); + free(query); + if (!query_cmd) + return ERROR_FAIL; + + int retval = Jim_EvalSource(interp, __THIS__FILE__, __LINE__, query_cmd); + free(query_cmd); + if (retval != JIM_OK) + return ERROR_FAIL; + + Jim_Obj *list = Jim_GetResult(interp); + Jim_IncrRefCount(list); + + int len = Jim_ListLength(interp, list); + for (int i = 0; i < len; i++) { + Jim_Obj *elem = Jim_ListGetIndex(interp, list, i); + Jim_IncrRefCount(elem); + + const char *name = Jim_GetString(elem, NULL); + struct command *c = command_find_from_name(interp, name); + if (!c) { + /* not openocd command */ + Jim_DecrRefCount(interp, elem); + continue; + } + LOG_DEBUG("delete command \"%s\"", name); + Jim_DeleteCommand(interp, elem); + + help_del_command(cmd_ctx, name); + + Jim_DecrRefCount(interp, elem); + } + + Jim_DecrRefCount(interp, list); + return ERROR_OK; +} + +int unregister_all_commands(struct command_context *context, + const char *cmd_prefix) +{ + struct command *parent = NULL; + + if (!context) return ERROR_OK; + if (!cmd_prefix || !*cmd_prefix) { + int retval = unregister_commands_match(context, "*"); + if (retval != ERROR_OK) + return retval; + } else { + Jim_Cmd *cmd = Jim_GetCommand(context->interp, Jim_NewStringObj(context->interp, cmd_prefix, -1), JIM_NONE); + if (cmd && jimcmd_is_ocd_command(cmd)) + parent = jimcmd_privdata(cmd); + + int retval = unregister_commands_match(context, "%s *", cmd_prefix); + if (retval != ERROR_OK) + return retval; + retval = unregister_commands_match(context, "%s", cmd_prefix); + if (retval != ERROR_OK) + return retval; + } + struct command **head = command_list_for_parent(context, parent); while (NULL != *head) { struct command *tmp = *head; @@ -458,7 +546,11 @@ static int unregister_command(struct command_context *context, continue; char *full_name = command_name(c, ' '); - help_del_command(context, full_name); + + int retval = unregister_commands_match(context, "%s", full_name); + if (retval != ERROR_OK) + return retval; + free(full_name); if (p) diff --git a/src/helper/command.h b/src/helper/command.h index db095972a..4d1928c5a 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -311,11 +311,11 @@ static inline int register_commands_with_data(struct command_context *cmd_ctx, /** * Unregisters all commands from the specified context. * @param cmd_ctx The context that will be cleared of registered commands. - * @param parent If given, only clear commands from under this one command. + * @param cmd_prefix If given, only clear commands from under this one command. * @returns ERROR_OK on success, or an error code. */ int unregister_all_commands(struct command_context *cmd_ctx, - struct command *parent); + const char *cmd_prefix); /** * Unregisters the help for all commands. Used at exit to remove the help From fa23b1a71e4f1974791e90055c301f9bf124e835 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 25 May 2020 16:09:12 +0200 Subject: [PATCH 17/58] helper/command: get rid of the tree of struct command There is no need anymore to keep alive the tree of struct command. Remove it and let jim to free() the command's struct command that is referenced through command's private data. Change-Id: I2cd84e0274a969ce200320e3a177ac20c7823da0 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5675 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 268 ++++++++++++------------------------------- src/helper/command.h | 4 - 2 files changed, 76 insertions(+), 196 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index d79d7f464..630630f38 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -50,8 +50,7 @@ struct log_capture_state { }; static int unregister_command(struct command_context *context, - struct command *parent, const char *name); -static char *command_name(struct command *c, char delim); + const char *cmd_prefix, const char *name); static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj * const *argv); static int help_add_command(struct command_context *cmd_ctx, const char *cmd_name, const char *help_text, const char *usage_text); @@ -263,68 +262,8 @@ static struct command *command_find_from_name(Jim_Interp *interp, const char *na return jimcmd_privdata(cmd); } -/** - * Find a command by name from a list of commands. - * @returns Returns the named command if it exists in the list. - * Returns NULL otherwise. - */ -static struct command *command_find(struct command *head, const char *name) -{ - for (struct command *cc = head; cc; cc = cc->next) { - if (strcmp(cc->name, name) == 0) - return cc; - } - return NULL; -} - -/** - * Add the command into the linked list, sorted by name. - * @param head Address to head of command list pointer, which may be - * updated if @c c gets inserted at the beginning of the list. - * @param c The command to add to the list pointed to by @c head. - */ -static void command_add_child(struct command **head, struct command *c) -{ - assert(head); - if (NULL == *head) { - *head = c; - return; - } - - while ((*head)->next && (strcmp(c->name, (*head)->name) > 0)) - head = &(*head)->next; - - if (strcmp(c->name, (*head)->name) > 0) { - c->next = (*head)->next; - (*head)->next = c; - } else { - c->next = *head; - *head = c; - } -} - -static struct command **command_list_for_parent( - struct command_context *cmd_ctx, struct command *parent) -{ - return parent ? &parent->children : &cmd_ctx->commands; -} - -static void command_free(struct command *c) -{ - /** @todo if command has a handler, unregister its jim command! */ - - while (NULL != c->children) { - struct command *tmp = c->children; - c->children = tmp->next; - command_free(tmp); - } - - free(c->name); - free(c); -} - static struct command *command_new(struct command_context *cmd_ctx, - struct command *parent, const struct command_registration *cr) + const char *full_name, const struct command_registration *cr) { assert(cr->name); @@ -335,76 +274,86 @@ static struct command *command_new(struct command_context *cmd_ctx, * strlen(.usage) == 0 means that the command takes no * arguments. */ - if ((cr->jim_handler == NULL) && (cr->usage == NULL)) { - LOG_ERROR("BUG: command '%s%s%s' does not have the " + if (!cr->jim_handler && !cr->usage) + LOG_ERROR("BUG: command '%s' does not have the " "'.usage' field filled out", - parent && parent->name ? parent->name : "", - parent && parent->name ? " " : "", - cr->name); - } + full_name); struct command *c = calloc(1, sizeof(struct command)); if (NULL == c) return NULL; c->name = strdup(cr->name); - if (!c->name) - goto command_new_error; + if (!c->name) { + free(c); + return NULL; + } - c->parent = parent; c->handler = cr->handler; c->jim_handler = cr->jim_handler; c->mode = cr->mode; - command_add_child(command_list_for_parent(cmd_ctx, parent), c); - - if (cr->help || cr->usage) { - char *full_name = command_name(c, ' '); + if (cr->help || cr->usage) help_add_command(cmd_ctx, full_name, cr->help, cr->usage); - free(full_name); - } return c; +} -command_new_error: - command_free(c); - return NULL; +static void command_free(struct Jim_Interp *interp, void *priv) +{ + struct command *c = priv; + + free(c->name); + free(c); } static struct command *register_command(struct command_context *context, - struct command *parent, const struct command_registration *cr) + const char *cmd_prefix, const struct command_registration *cr) { + char *full_name; + if (!context || !cr->name) return NULL; - const char *name = cr->name; - struct command **head = command_list_for_parent(context, parent); - struct command *c = command_find(*head, name); - if (NULL != c) { + if (cmd_prefix) + full_name = alloc_printf("%s %s", cmd_prefix, cr->name); + else + full_name = strdup(cr->name); + if (!full_name) + return NULL; + + struct command *c = command_find_from_name(context->interp, full_name); + if (c) { /* TODO: originally we treated attempting to register a cmd twice as an error * Sometimes we need this behaviour, such as with flash banks. * http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */ - LOG_DEBUG("command '%s' is already registered in '%s' context", - name, parent ? parent->name : ""); + LOG_DEBUG("command '%s' is already registered", full_name); + free(full_name); return c; } - c = command_new(context, parent, cr); - if (NULL == c) - return NULL; - - char *full_name = command_name(c, ' '); - LOG_DEBUG("registering '%s'...", full_name); - int retval = Jim_CreateCommand(context->interp, full_name, - command_unknown, c, NULL); - if (retval != JIM_OK) { - unregister_command(context, parent, name); + c = command_new(context, full_name, cr); + if (!c) { + free(full_name); return NULL; } + + LOG_DEBUG("registering '%s'...", full_name); + int retval = Jim_CreateCommand(context->interp, full_name, + command_unknown, c, command_free); + if (retval != JIM_OK) { + command_run_linef(context, "del_help_text {%s}", full_name); + command_run_linef(context, "del_usage_text {%s}", full_name); + free(c); + free(full_name); + return NULL; + } + + free(full_name); return c; } -static int ___register_commands(struct command_context *cmd_ctx, struct command *parent, +int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds, void *data, struct target *override_target) { @@ -415,7 +364,7 @@ static int ___register_commands(struct command_context *cmd_ctx, struct command struct command *c = NULL; if (NULL != cr->name) { - c = register_command(cmd_ctx, parent, cr); + c = register_command(cmd_ctx, cmd_prefix, cr); if (NULL == c) { retval = ERROR_FAIL; break; @@ -424,31 +373,32 @@ static int ___register_commands(struct command_context *cmd_ctx, struct command c->jim_override_target = override_target; } if (NULL != cr->chain) { - struct command *p = c ? : parent; - retval = ___register_commands(cmd_ctx, p, cr->chain, data, override_target); + if (cr->name) { + if (cmd_prefix) { + char *new_prefix = alloc_printf("%s %s", cmd_prefix, cr->name); + if (!new_prefix) { + retval = ERROR_FAIL; + break; + } + retval = __register_commands(cmd_ctx, new_prefix, cr->chain, data, override_target); + free(new_prefix); + } else { + retval = __register_commands(cmd_ctx, cr->name, cr->chain, data, override_target); + } + } else { + retval = __register_commands(cmd_ctx, cmd_prefix, cr->chain, data, override_target); + } if (ERROR_OK != retval) break; } } if (ERROR_OK != retval) { for (unsigned j = 0; j < i; j++) - unregister_command(cmd_ctx, parent, cmds[j].name); + unregister_command(cmd_ctx, cmd_prefix, cmds[j].name); } return retval; } -int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, - const struct command_registration *cmds, void *data, - struct target *override_target) -{ - struct command *parent = NULL; - - if (cmd_prefix) - parent = command_find(cmd_ctx->commands, cmd_prefix); - - return ___register_commands(cmd_ctx, parent, cmds, data, override_target); -} - static __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))) int unregister_commands_match(struct command_context *cmd_ctx, const char *format, ...) { @@ -501,68 +451,29 @@ int unregister_commands_match(struct command_context *cmd_ctx, const char *forma int unregister_all_commands(struct command_context *context, const char *cmd_prefix) { - struct command *parent = NULL; - if (!context) return ERROR_OK; - if (!cmd_prefix || !*cmd_prefix) { - int retval = unregister_commands_match(context, "*"); - if (retval != ERROR_OK) - return retval; - } else { - Jim_Cmd *cmd = Jim_GetCommand(context->interp, Jim_NewStringObj(context->interp, cmd_prefix, -1), JIM_NONE); - if (cmd && jimcmd_is_ocd_command(cmd)) - parent = jimcmd_privdata(cmd); + if (!cmd_prefix || !*cmd_prefix) + return unregister_commands_match(context, "*"); - int retval = unregister_commands_match(context, "%s *", cmd_prefix); - if (retval != ERROR_OK) - return retval; - retval = unregister_commands_match(context, "%s", cmd_prefix); - if (retval != ERROR_OK) - return retval; - } + int retval = unregister_commands_match(context, "%s *", cmd_prefix); + if (retval != ERROR_OK) + return retval; - struct command **head = command_list_for_parent(context, parent); - while (NULL != *head) { - struct command *tmp = *head; - *head = tmp->next; - command_free(tmp); - } - - return ERROR_OK; + return unregister_commands_match(context, "%s", cmd_prefix); } static int unregister_command(struct command_context *context, - struct command *parent, const char *name) + const char *cmd_prefix, const char *name) { - if ((!context) || (!name)) + if (!context || !name) return ERROR_COMMAND_SYNTAX_ERROR; - struct command *p = NULL; - struct command **head = command_list_for_parent(context, parent); - for (struct command *c = *head; NULL != c; p = c, c = c->next) { - if (strcmp(name, c->name) != 0) - continue; + if (!cmd_prefix || !*cmd_prefix) + return unregister_commands_match(context, "%s", name); - char *full_name = command_name(c, ' '); - - int retval = unregister_commands_match(context, "%s", full_name); - if (retval != ERROR_OK) - return retval; - - free(full_name); - - if (p) - p->next = c->next; - else - *head = c->next; - - command_free(c); - return ERROR_OK; - } - - return ERROR_OK; + return unregister_commands_match(context, "%s %s", cmd_prefix, name); } void command_output_text(struct command_context *context, const char *data) @@ -619,33 +530,6 @@ void command_print(struct command_invocation *cmd, const char *format, ...) va_end(ap); } -static char *__command_name(struct command *c, char delim, unsigned extra) -{ - char *name; - unsigned len = strlen(c->name); - if (NULL == c->parent) { - /* allocate enough for the name, child names, and '\0' */ - name = malloc(len + extra + 1); - if (!name) { - LOG_ERROR("Out of memory"); - return NULL; - } - strcpy(name, c->name); - } else { - /* parent's extra must include both the space and name */ - name = __command_name(c->parent, delim, 1 + len + extra); - char dstr[2] = { delim, 0 }; - strcat(name, dstr); - strcat(name, c->name); - } - return name; -} - -static char *command_name(struct command *c, char delim) -{ - return __command_name(c, delim, 0); -} - static bool command_can_run(struct command_context *cmd_ctx, struct command *c, const char *full_name) { if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode) diff --git a/src/helper/command.h b/src/helper/command.h index 4d1928c5a..1f2dc5b59 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -54,7 +54,6 @@ typedef int (*command_output_handler_t)(struct command_context *context, struct command_context { Jim_Interp *interp; enum command_mode mode; - struct command *commands; struct target *current_target; /* The target set by 'targets xx' command or the latest created */ struct target *current_target_override; @@ -182,8 +181,6 @@ typedef __COMMAND_HANDLER((*command_handler_t)); struct command { char *name; - struct command *parent; - struct command *children; command_handler_t handler; Jim_CmdProc *jim_handler; void *jim_handler_data; @@ -191,7 +188,6 @@ struct command { struct target *jim_override_target; /* Used only for target of target-prefixed cmd */ enum command_mode mode; - struct command *next; }; /* From 6b5e77ada6520398f9a2135e43e60067bc072e27 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 13 May 2020 16:51:00 +0200 Subject: [PATCH 18/58] helper/command: make script_debug() static Now that all commands are executed through the common handler command_unknown(), the message about command execution is logged by command_unknown(). There is no need, for "native" commands (.jim_handler) at root level to log the message (again) by itself. Remove calls to script_debug() apart from command_unknown(). Make script_debug() static as only used in command.c. Change-Id: I9b2728b69e7643d6121c4b35a96bc825bcb5488d Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5676 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 2 +- src/helper/command.h | 2 -- src/jtag/tcl.c | 6 ------ 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 630630f38..a7990d4f8 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -180,7 +180,7 @@ extern struct command_context *global_cmd_ctx; /* dump a single line to the log for the command. * Do nothing in case we are not at debug level 3 */ -void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv) +static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv) { if (debug_level < LOG_LVL_DEBUG) return; diff --git a/src/helper/command.h b/src/helper/command.h index 1f2dc5b59..68f4c14fe 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -456,6 +456,4 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); #define COMMAND_PARSE_ENABLE(in, out) \ COMMAND_PARSE_BOOL(in, out, "enable", "disable") -void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv); - #endif /* OPENOCD_HELPER_COMMAND_H */ diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index bf65e8119..3e7333515 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -108,8 +108,6 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args endstate = TAP_IDLE; - script_debug(interp, argc, args); - /* validate arguments as numbers */ e = JIM_OK; for (i = 2; i < argc; i += 2) { @@ -234,8 +232,6 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar return JIM_ERR; } - script_debug(interp, argc, args); - int i; for (i = 0; i < argc-1; i++) { const char *cp; @@ -266,8 +262,6 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args) { - script_debug(interp, argc, args); - Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count())); return JIM_OK; From d3a687432f96d90fdaa7c1264cf2c17df3ad58c1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 3 Aug 2020 23:03:46 +0200 Subject: [PATCH 19/58] helper/command: rename s/command_unknown/jim_command_dispatch/ The function's name was consistent with its purpose to handle commands that were not at root level, thus not directly 'known' by jimtcl. Rename it as jim_command_dispatch() to highlight that now it is a jim_handler and its purpose is to dispatch the call to the proper command handler. Change-Id: I9491a6d6459b8eb37a6c402abcae08388c693764 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5791 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/helper/command.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index a7990d4f8..80e297b1f 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -51,7 +51,7 @@ struct log_capture_state { static int unregister_command(struct command_context *context, const char *cmd_prefix, const char *name); -static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj * const *argv); +static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *argv); static int help_add_command(struct command_context *cmd_ctx, const char *cmd_name, const char *help_text, const char *usage_text); static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name); @@ -64,7 +64,7 @@ static inline bool jimcmd_is_proc(Jim_Cmd *cmd) static inline bool jimcmd_is_ocd_command(Jim_Cmd *cmd) { - return !cmd->isproc && cmd->u.native.cmdProc == command_unknown; + return !cmd->isproc && cmd->u.native.cmdProc == jim_command_dispatch; } static inline void *jimcmd_privdata(Jim_Cmd *cmd) @@ -340,7 +340,7 @@ static struct command *register_command(struct command_context *context, LOG_DEBUG("registering '%s'...", full_name); int retval = Jim_CreateCommand(context->interp, full_name, - command_unknown, c, command_free); + jim_command_dispatch, c, command_free); if (retval != JIM_OK) { command_run_linef(context, "del_help_text {%s}", full_name); command_run_linef(context, "del_usage_text {%s}", full_name); @@ -942,7 +942,7 @@ static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, return command_retval_set(interp, retval); } -static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { script_debug(interp, argc, argv); @@ -982,7 +982,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * current_target_override is used also for event handlers * therefore we prevent touching it if command has no prefix. * Previous override is saved and restored back to ensure - * correct work when command_unknown() is re-entered. + * correct work when jim_command_dispatch() is re-entered. */ struct target *saved_target_override = cmd_ctx->current_target_override; if (c->jim_override_target) From 80970811f4558b610792b01d37740be8af4258f6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 20 Mar 2021 19:04:15 +0100 Subject: [PATCH 20/58] drivers/cmsis-dap: improve error checking Check returned HID report number (or the first byte of returned bulk packet) which should be equal to the issued command or 0xff in case of the command is not implemented. Fix error return paths in cmsis_dap_init() to clean up the adapter connection. Don't fail cmsis_dap_init() when an unimportant function fails (for the case the adapter doesn't implement some parts of protocol). Change-Id: Ief8382aabe9915346b2273702fb2ff17bbb5eb1b Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6121 Tested-by: jenkins Reviewed-by: Peter Lawrence --- src/jtag/drivers/cmsis_dap.c | 63 ++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index eb973642c..b5ceb6cef 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -221,6 +221,8 @@ static uint8_t output_pins = SWJ_PIN_SRST | SWJ_PIN_TRST; static struct cmsis_dap *cmsis_dap_handle; +static int cmsis_dap_quit(void); + static int cmsis_dap_open(void) { const struct cmsis_dap_backend *backend = NULL; @@ -292,6 +294,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) pending_fifo_get_idx = 0; } + uint8_t current_cmd = cmsis_dap_handle->command[0]; int retval = dap->backend->write(dap, txlen, USB_TIMEOUT); if (retval < 0) return retval; @@ -301,6 +304,18 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) if (retval < 0) return retval; + uint8_t *resp = cmsis_dap_handle->response; + if (resp[0] == DAP_ERROR) { + LOG_ERROR("CMSIS-DAP command 0x%" PRIx8 " not implemented", current_cmd); + return ERROR_NOT_IMPLEMENTED; + } + + if (resp[0] != current_cmd) { + LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8 + " received 0x%" PRIx8, current_cmd, resp[0]); + return ERROR_FAIL; + } + return ERROR_OK; } @@ -605,6 +620,13 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) } uint8_t *resp = dap->response; + if (resp[0] != CMD_DAP_TFER) { + LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%" PRIx8 + " received 0x%" PRIx8, CMD_DAP_TFER, resp[0]); + queued_retval = ERROR_FAIL; + goto skip; + } + uint8_t transfer_count = resp[1]; uint8_t ack = resp[2] & 0x07; if (resp[2] & 0x08) { @@ -616,6 +638,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count, ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + /* TODO: use results of transfers completed before the error occurred? */ goto skip; } @@ -900,7 +923,7 @@ static int cmsis_dap_init(void) /* INFO_ID_PKT_SZ - short */ retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data); if (retval != ERROR_OK) - return retval; + goto init_err; if (data[0] == 2) { /* short */ uint16_t pkt_sz = data[1] + (data[2] << 8); @@ -914,7 +937,7 @@ static int cmsis_dap_init(void) free(cmsis_dap_handle->packet_buffer); retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz); if (retval != ERROR_OK) - return retval; + goto init_err; LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRIu16, pkt_sz); } @@ -923,7 +946,7 @@ static int cmsis_dap_init(void) /* INFO_ID_PKT_CNT - byte */ retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_CNT, &data); if (retval != ERROR_OK) - return retval; + goto init_err; if (data[0] == 1) { /* byte */ int pkt_cnt = data[1]; @@ -938,43 +961,40 @@ static int cmsis_dap_init(void) pending_fifo[i].transfers = malloc(pending_queue_len * sizeof(struct pending_transfer_result)); if (!pending_fifo[i].transfers) { LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue"); - return ERROR_FAIL; + retval = ERROR_FAIL; + goto init_err; } } - - retval = cmsis_dap_get_status(); - if (retval != ERROR_OK) - return ERROR_FAIL; + /* Intentionally not checked for error, just logs an info message + * not vital for further debugging */ + (void)cmsis_dap_get_status(); /* Now try to connect to the target * TODO: This is all SWD only @ present */ retval = cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); if (retval != ERROR_OK) - return ERROR_FAIL; + goto init_err; /* Ask CMSIS-DAP to automatically retry on receiving WAIT for * up to 64 times. This must be changed to 0 if sticky * overrun detection is enabled. */ retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0); if (retval != ERROR_OK) - return ERROR_FAIL; + goto init_err; if (swd_mode) { /* Data Phase (bit 2) must be set to 1 if sticky overrun * detection is enabled */ retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */ if (retval != ERROR_OK) - return ERROR_FAIL; + goto init_err; } /* Both LEDs on */ - retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON); - if (retval != ERROR_OK) - return ERROR_FAIL; - - retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON); - if (retval != ERROR_OK) - return ERROR_FAIL; + /* Intentionally not checked for error, debugging will work + * without LEDs */ + (void)cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON); + (void)cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON); /* support connecting with srst asserted */ enum reset_types jtag_reset_config = jtag_get_reset_config(); @@ -983,13 +1003,16 @@ static int cmsis_dap_init(void) if (jtag_reset_config & RESET_SRST_NO_GATING) { retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, SWJ_PIN_SRST, 0, NULL); if (retval != ERROR_OK) - return ERROR_FAIL; + goto init_err; LOG_INFO("Connecting under reset"); } } LOG_INFO("CMSIS-DAP: Interface ready"); - return ERROR_OK; + +init_err: + cmsis_dap_quit(); + return retval; } static int cmsis_dap_swd_init(void) From ff755a575ebf0218c2eb8745eff8050f8f02a53d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 6 Apr 2021 18:55:22 +0200 Subject: [PATCH 21/58] drivers/cmsis-dap: flush read Some CMSIS-DAP adapters keep buffered packets over USB close/open so we need to flush up to 64 old packets to be sure all buffers are empty. Flush just after cmsis_dap_open() and in the case of command mismatch. Change-Id: If21a118639e64d90635b4ecf81013d29a7b9f78d Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6135 Tested-by: jenkins Reviewed-by: Adrian M Negreanu --- src/jtag/drivers/cmsis_dap.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index b5ceb6cef..6ab087598 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -281,6 +281,21 @@ static void cmsis_dap_close(struct cmsis_dap *dap) } } +static void cmsis_dap_flush_read(struct cmsis_dap *dap) +{ + unsigned int i; + /* Some CMSIS-DAP adapters keep buffered packets over + * USB close/open so we need to flush up to 64 old packets + * to be sure all buffers are empty */ + for (i = 0; i < 64; i++) { + int retval = dap->backend->read(dap, 10); + if (retval == ERROR_TIMEOUT_REACHED) + break; + } + if (i) + LOG_DEBUG("Flushed %u packets", i); +} + /* Send a message and receive the reply */ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) { @@ -313,6 +328,8 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) if (resp[0] != current_cmd) { LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8 " received 0x%" PRIx8, current_cmd, resp[0]); + + cmsis_dap_flush_read(dap); return ERROR_FAIL; } @@ -885,6 +902,8 @@ static int cmsis_dap_init(void) if (retval != ERROR_OK) return retval; + cmsis_dap_flush_read(cmsis_dap_handle); + retval = cmsis_dap_get_caps_info(); if (retval != ERROR_OK) return retval; From dc277057f57780354278cdc4876d393735f49369 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 11 Apr 2021 21:36:00 +0200 Subject: [PATCH 22/58] flash/nor/numicro: Use 'bool' data type Change-Id: Ib4ee64dec9c1253ae45bc58e9f175ab36964180a Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/6162 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/numicro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c index 1971daa24..d9ea16d27 100644 --- a/src/flash/nor/numicro.c +++ b/src/flash/nor/numicro.c @@ -1132,7 +1132,7 @@ static const struct numicro_cpu_type NuMicroParts[] = { /* Private bank information for NuMicro. */ struct numicro_flash_bank { struct working_area *write_algorithm; - int probed; + bool probed; const struct numicro_cpu_type *cpu; }; From 41a6089504823433817ea67d9af3d2d85f402336 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 Apr 2021 18:54:16 +0200 Subject: [PATCH 23/58] flash/nor/nrf5: Fix data types and const correctness Change-Id: I8c5bac7098d92e9b3bd1b045735879cf32ac218d Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/6163 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/flash/nor/nrf5.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 1784bcde5..12bbac64f 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -289,7 +289,7 @@ static const struct nrf5_device_package nrf5_packages_table[] = { const struct flash_driver nrf5_flash, nrf51_flash; -static int nrf5_bank_is_probed(struct flash_bank *bank) +static bool nrf5_bank_is_probed(const struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; @@ -309,13 +309,10 @@ static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf5_i struct nrf5_bank *nbank = bank->driver_priv; *chip = nbank->chip; - int probed = nrf5_bank_is_probed(bank); - if (probed < 0) - return probed; - else if (!probed) - return nrf5_probe(bank); - else + if (nrf5_bank_is_probed(bank)) return ERROR_OK; + + return nrf5_probe(bank); } static int nrf5_wait_for_nvmc(struct nrf5_info *chip) @@ -872,14 +869,10 @@ static int nrf5_probe(struct flash_bank *bank) static int nrf5_auto_probe(struct flash_bank *bank) { - int probed = nrf5_bank_is_probed(bank); - - if (probed < 0) - return probed; - else if (probed) + if (nrf5_bank_is_probed(bank)) return ERROR_OK; - else - return nrf5_probe(bank); + + return nrf5_probe(bank); } static int nrf5_erase_all(struct nrf5_info *chip) From 29af9040436a9bb0a937c25c122018494bd3fe08 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 4 Apr 2019 15:44:25 +0300 Subject: [PATCH 24/58] target/imx8qm: Initial support Chip is similar to imx8x series but has different cores at different addresses. Support for reduced versions is not yet available. Tested on imx8qm-mek board Change-Id: Ia34a80d561ab2849a570d8c375b936a45cbf45ca Signed-off-by: Leonard Crestez Reviewed-by: Oliver Graute Reviewed-on: http://openocd.zylin.com/5042 Reviewed-by: Oleksij Rempel Tested-by: jenkins Reviewed-by: Tomas Vanek --- tcl/target/imx8qm.cfg | 89 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tcl/target/imx8qm.cfg diff --git a/tcl/target/imx8qm.cfg b/tcl/target/imx8qm.cfg new file mode 100644 index 000000000..08cb8137d --- /dev/null +++ b/tcl/target/imx8qm.cfg @@ -0,0 +1,89 @@ +# +# NXP i.MX8QuadMax +# + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME imx8qm +} + +# CoreSight Debug Access Port (DAP) +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + # TAPID is from FreeScale! + set _DAP_TAPID 0x1890101d +} + +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f \ + -expected-id $_DAP_TAPID + +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +# AXI: Main SOC bus on AP #0 +target create ${_CHIPNAME}.axi mem_ap -dap ${_CHIPNAME}.dap -ap-num 0 + +# 4x Cortex-A53 on AP #6 +set _A53_DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000} +set _A53_CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} + +cti create $_CHIPNAME.a53_cti.0 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A53_CTIBASE 0] +cti create $_CHIPNAME.a53_cti.1 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A53_CTIBASE 1] +cti create $_CHIPNAME.a53_cti.2 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A53_CTIBASE 2] +cti create $_CHIPNAME.a53_cti.3 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A53_CTIBASE 3] +target create $_CHIPNAME.a53.0 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a53_cti.0 -dbgbase [lindex $_A53_DBGBASE 0] +target create $_CHIPNAME.a53.1 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a53_cti.1 -dbgbase [lindex $_A53_DBGBASE 1] -defer-examine +target create $_CHIPNAME.a53.2 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a53_cti.2 -dbgbase [lindex $_A53_DBGBASE 2] -defer-examine +target create $_CHIPNAME.a53.3 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a53_cti.3 -dbgbase [lindex $_A53_DBGBASE 3] -defer-examine + +# 2x Cortex-A72 on AP #6 +set _A72_DBGBASE {0x80210000 0x80310000} +set _A72_CTIBASE {0x80220000 0x80220000} + +cti create $_CHIPNAME.a72_cti.0 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A72_CTIBASE 0] +cti create $_CHIPNAME.a72_cti.1 -dap $_CHIPNAME.dap \ + -ap-num 6 -baseaddr [lindex $_A72_CTIBASE 1] +target create $_CHIPNAME.a72.0 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a72_cti.0 -dbgbase [lindex $_A72_DBGBASE 0] -defer-examine +target create $_CHIPNAME.a72.1 aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.a72_cti.1 -dbgbase [lindex $_A72_DBGBASE 1] -defer-examine + +# All Cortex-A in SMP +target smp \ + $_CHIPNAME.a53.0 \ + $_CHIPNAME.a53.1 \ + $_CHIPNAME.a53.2 \ + $_CHIPNAME.a53.3 \ + $_CHIPNAME.a72.0 \ + $_CHIPNAME.a72.1 + +# SCU: Cortex-M4 core +# always running imx SC firmware +target create ${_CHIPNAME}.scu cortex_m -dap ${_CHIPNAME}.dap -ap-num 1 + +# AHB from SCU perspective +target create ${_CHIPNAME}.scu_ahb mem_ap -dap ${_CHIPNAME}.dap -ap-num 4 + +# Cortex-M4 M4_0 core on AP #2 (default off) +target create ${_CHIPNAME}.m4_0 cortex_m -dap ${_CHIPNAME}.dap -ap-num 2 \ + -defer-examine + +# Cortex-M4 M4_1 core on AP #3 (default off) +target create ${_CHIPNAME}.m4_1 cortex_m -dap ${_CHIPNAME}.dap -ap-num 3 \ + -defer-examine + +# Debug APB bus +target create ${_CHIPNAME}.apb mem_ap -dap ${_CHIPNAME}.dap -ap-num 6 + +# Default target is boot core a53.0 +targets $_CHIPNAME.a53.0 From 7dd323b26d93e49e409e02053e30f53ac8138cd5 Mon Sep 17 00:00:00 2001 From: Yun Liu Date: Fri, 12 Mar 2021 15:07:13 +0800 Subject: [PATCH 25/58] remote_bitbang: Add Windows support Windows socket descriptor is not file descriptor, so when using remote_bitbang on Windows, it fails with "fdopen: failed to open write stream". This patch removes the file write stream, replaces it with socket write calls. Change-Id: Ifd7c8a4139a5ac51ecd2846835a7a947a90fe16c Signed-off-by: Yun Liu Reviewed-on: http://openocd.zylin.com/6096 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/jtag/drivers/remote_bitbang.c | 55 +++++++++++-------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 663795296..114e018b7 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -33,7 +33,6 @@ static char *remote_bitbang_host; static char *remote_bitbang_port; -static FILE *remote_bitbang_file; static int remote_bitbang_fd; /* Circular buffer. When start == end, the buffer is empty. */ @@ -63,7 +62,7 @@ static int remote_bitbang_fill_buf(void) contiguous_available_space = remote_bitbang_start - remote_bitbang_end - 1; } - ssize_t count = read(remote_bitbang_fd, + ssize_t count = read_socket(remote_bitbang_fd, remote_bitbang_buf + remote_bitbang_end, contiguous_available_space); if (count > 0) { @@ -73,11 +72,14 @@ static int remote_bitbang_fill_buf(void) } else if (count == 0) { return ERROR_OK; } else if (count < 0) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAEWOULDBLOCK) { +#else if (errno == EAGAIN) { +#endif return ERROR_OK; } else { - LOG_ERROR("remote_bitbang_fill_buf: %s (%d)", - strerror(errno), errno); + log_socket_error("remote_bitbang_fill_buf"); return ERROR_FAIL; } } @@ -88,8 +90,10 @@ static int remote_bitbang_fill_buf(void) static int remote_bitbang_putc(int c) { - if (EOF == fputc(c, remote_bitbang_file)) { - LOG_ERROR("remote_bitbang_putc: %s", strerror(errno)); + char buf = c; + ssize_t count = write_socket(remote_bitbang_fd, &buf, sizeof(buf)); + if (count < 0) { + log_socket_error("remote_bitbang_putc"); return ERROR_FAIL; } return ERROR_OK; @@ -97,20 +101,11 @@ static int remote_bitbang_putc(int c) static int remote_bitbang_quit(void) { - if (EOF == fputc('Q', remote_bitbang_file)) { - LOG_ERROR("fputs: %s", strerror(errno)); + if (remote_bitbang_putc('Q') == ERROR_FAIL) return ERROR_FAIL; - } - if (EOF == fflush(remote_bitbang_file)) { - LOG_ERROR("fflush: %s", strerror(errno)); - return ERROR_FAIL; - } - - /* We only need to close one of the FILE*s, because they both use the same */ - /* underlying file descriptor. */ - if (EOF == fclose(remote_bitbang_file)) { - LOG_ERROR("fclose: %s", strerror(errno)); + if (close_socket(remote_bitbang_fd) != 0) { + log_socket_error("close_socket"); return ERROR_FAIL; } @@ -138,21 +133,16 @@ static bb_value_t char_to_int(int c) /* Get the next read response. */ static bb_value_t remote_bitbang_rread(void) { - if (EOF == fflush(remote_bitbang_file)) { - remote_bitbang_quit(); - LOG_ERROR("fflush: %s", strerror(errno)); - return BB_ERROR; - } - /* Enable blocking access. */ socket_block(remote_bitbang_fd); char c; - ssize_t count = read(remote_bitbang_fd, &c, 1); + ssize_t count = read_socket(remote_bitbang_fd, &c, 1); if (count == 1) { return char_to_int(c); } else { remote_bitbang_quit(); - LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno)); + LOG_ERROR("read_socket: count=%d", (int) count); + log_socket_error("read_socket"); return BB_ERROR; } } @@ -238,7 +228,7 @@ static int remote_bitbang_init_tcp(void) freeaddrinfo(result); /* No longer needed */ if (rp == NULL) { /* No address succeeded */ - LOG_ERROR("Failed to connect: %s", strerror(errno)); + log_socket_error("Failed to connect"); return ERROR_FAIL; } @@ -255,7 +245,7 @@ static int remote_bitbang_init_unix(void) LOG_INFO("Connecting to unix socket %s", remote_bitbang_host); int fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - LOG_ERROR("socket: %s", strerror(errno)); + log_socket_error("socket"); return ERROR_FAIL; } @@ -265,7 +255,7 @@ static int remote_bitbang_init_unix(void) addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { - LOG_ERROR("connect: %s", strerror(errno)); + log_socket_error("connect"); return ERROR_FAIL; } @@ -288,13 +278,6 @@ static int remote_bitbang_init(void) if (remote_bitbang_fd < 0) return remote_bitbang_fd; - remote_bitbang_file = fdopen(remote_bitbang_fd, "w+"); - if (remote_bitbang_file == NULL) { - LOG_ERROR("fdopen: failed to open write stream"); - close(remote_bitbang_fd); - return ERROR_FAIL; - } - LOG_INFO("remote_bitbang driver initialized"); return ERROR_OK; } From 3cacfd86ab208a99c91b25f54a79528227d6ea50 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 13 May 2020 17:22:12 +0200 Subject: [PATCH 26/58] smp: move command deprecation to startup.tcl Commit 246782229f8f ("smp: replace commands smp_on/smp_off with "smp [on|off]"") deprecates some multi-word comments, when openocd was unable to properly handle mixes of multi-word commands and tcl procedures having a common initial word. This limitation is over, so move in startup.tcl the multi-word commands deprecation, making it easy to remove them after a grace period. Change-Id: Icb550d1fa7559b95692d2a1244880da6c90ec0b2 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5677 Tested-by: jenkins --- src/target/smp.c | 34 ---------------------------------- src/target/startup.tcl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/target/smp.c b/src/target/smp.c index acd4628e2..6501dc08a 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -131,26 +131,6 @@ COMMAND_HANDLER(default_handle_smp_command) return ERROR_COMMAND_SYNTAX_ERROR; } -COMMAND_HANDLER(deprecated_handle_smp_on_command) -{ - const char *argv[] = {"on", NULL}; - - LOG_WARNING("\'smp_on\' is deprecated, please use \'smp on\' instead."); - CMD_ARGC = 1; - CMD_ARGV = argv; - return CALL_COMMAND_HANDLER(default_handle_smp_command); -} - -COMMAND_HANDLER(deprecated_handle_smp_off_command) -{ - const char *argv[] = {"off", NULL}; - - LOG_WARNING("\'smp_off\' is deprecated, please use \'smp off\' instead."); - CMD_ARGC = 1; - CMD_ARGV = argv; - return CALL_COMMAND_HANDLER(default_handle_smp_command); -} - COMMAND_HANDLER(handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); @@ -180,20 +160,6 @@ const struct command_registration smp_command_handlers[] = { .help = "smp handling", .usage = "[on|off]", }, - { - .name = "smp_on", - .handler = deprecated_handle_smp_on_command, - .mode = COMMAND_EXEC, - .help = "Restart smp handling", - .usage = "", - }, - { - .name = "smp_off", - .handler = deprecated_handle_smp_off_command, - .mode = COMMAND_EXEC, - .help = "Stop smp handling", - .usage = "", - }, { .name = "smp_gdb", .handler = handle_smp_gdb_command, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index a8f78ab49..f128d3b5e 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -206,3 +206,34 @@ proc init_target_events {} { # Additionally board config scripts can define a procedure init_board that will be executed after init and init_targets proc init_board {} { } + +# smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615 +proc "aarch64 smp_on" {args} { + echo "DEPRECATED! use 'aarch64 smp on' not 'aarch64 smp_on'" + eval aarch64 smp on $args +} + +proc "aarch64 smp_off" {args} { + echo "DEPRECATED! use 'aarch64 smp off' not 'aarch64 smp_off'" + eval aarch64 smp off $args +} + +proc "cortex_a smp_on" {args} { + echo "DEPRECATED! use 'cortex_a smp on' not 'cortex_a smp_on'" + eval cortex_a smp on $args +} + +proc "cortex_a smp_off" {args} { + echo "DEPRECATED! use 'cortex_a smp off' not 'cortex_a smp_off'" + eval cortex_a smp off $args +} + +proc "mips_m4k smp_on" {args} { + echo "DEPRECATED! use 'mips_m4k smp on' not 'mips_m4k smp_on'" + eval mips_m4k smp on $args +} + +proc "mips_m4k smp_off" {args} { + echo "DEPRECATED! use 'mips_m4k smp off' not 'mips_m4k smp_off'" + eval mips_m4k smp off $args +} From 3ebcb62f9ff2f1c7a99a6207b158219b9892e72a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 7 Apr 2021 14:42:36 +0200 Subject: [PATCH 27/58] doc: annotate configuration commands Some command that is only valid during configuration is documented as generic command. Annotate them as {Config Command} in the documentation. Change-Id: Ifdbb6ec89b945e3d7adce94af379d94f511a64b6 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6153 Tested-by: jenkins Reviewed-by: Jonathan McDowell --- doc/openocd.texi | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index fdef3309d..44dcbdb8a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2115,7 +2115,7 @@ If you disable all access through TCP/IP, you will need to use the command line @option{-pipe} option. @anchor{gdb_port} -@deffn {Command} {gdb_port} [number] +@deffn {Config Command} {gdb_port} [number] @cindex GDB server Normally gdb listens to a TCP/IP port, but GDB can also communicate via pipes(stdin/out or named pipes). The name @@ -2148,7 +2148,7 @@ gdb (with 'set remotetimeout') is recommended. An insufficient timeout may cause initialization to fail with "Unknown remote qXfer reply: OK". @end deffn -@deffn {Command} {tcl_port} [number] +@deffn {Config Command} {tcl_port} [number] Specify or query the port used for a simplified RPC connection that can be used by clients to issue TCL commands and get the output from the Tcl engine. @@ -2158,7 +2158,7 @@ the port @var{number} defaults to 6666. When specified as "disabled", this service is not activated. @end deffn -@deffn {Command} {telnet_port} [number] +@deffn {Config Command} {telnet_port} [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. @@ -2343,7 +2343,7 @@ target. List the debug adapter drivers that have been built into the running copy of OpenOCD. @end deffn -@deffn {Command} {adapter transports} transport_name+ +@deffn {Config 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 @@ -2357,7 +2357,7 @@ Returns the name of the debug adapter driver being used. @end deffn @anchor{adapter_usb_location} -@deffn {Command} {adapter usb location} [-[.]...] +@deffn {Config Command} {adapter usb location} [-[.]...] Displays or specifies the physical USB port of the adapter to use. The path roots at @var{bus} and walks down the physical ports, with each @var{port} option specifying a deeper level in the bus topology, the last @@ -2775,13 +2775,13 @@ reset_config srst_only @end example @end deffn -@deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ublast2}) +@deffn {Config Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ublast2}) Chooses the low level access method for the adapter. If not specified, @option{ftdi} is selected unless it wasn't enabled during the configure stage. USB-Blaster II needs @option{ublast2}. @end deffn -@deffn {Command} {usb_blaster_firmware} @var{path} +@deffn {Config Command} {usb_blaster_firmware} @var{path} This command specifies @var{path} to access USB-Blaster II firmware image. To be used with USB-Blaster II only. @end deffn @@ -2873,7 +2873,7 @@ The following example shows how to read 4 bytes from the EMUCOM channel 0x0: 77a90000 @end example @end deffn -@deffn {Config} {jlink usb} <@option{0} to @option{3}> +@deffn {Config Command} {jlink usb} <@option{0} to @option{3}> Set the USB address of the interface, in case more than one adapter is connected to the host. If not specified, USB addresses are not considered. Device selection via USB address is not always unambiguous. It is recommended to use @@ -2881,7 +2881,7 @@ the serial number instead, if possible. As a configuration command, it can be used only before 'init'. @end deffn -@deffn {Config} {jlink serial} +@deffn {Config Command} {jlink serial} Set the serial number of the interface, in case more than one adapter is connected to the host. If not specified, serial numbers are not considered. @@ -2992,7 +2992,7 @@ When using PPDEV to access the parallel port, use the number of the parallel por you may encounter a problem. @end deffn -@deffn {Command} {parport_toggling_time} [nanoseconds] +@deffn {Config 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 speed} configuration. @@ -3335,7 +3335,7 @@ 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} ... +@deffn {Config Command} {swd newdap} ... Declares a single DAP which uses SWD transport. Parameters are currently the same as "jtag newtap" but this is expected to change. @@ -3933,8 +3933,7 @@ and underscores are OK; while others (including dots!) are not. @section TAP Declaration Commands -@c shouldn't this be(come) a {Config Command}? -@deffn {Command} {jtag newtap} chipname tapname configparams... +@deffn {Config Command} {jtag newtap} chipname tapname configparams... Declares a new TAP with the dotted name @var{chipname}.@var{tapname}, and configured according to the various @var{configparams}. @@ -4381,7 +4380,7 @@ xxx.dap apcsw default @end example @end deffn -@deffn {Command} {$dap_name ti_be_32_quirks} [@option{enable}] +@deffn {Config Command} {$dap_name ti_be_32_quirks} [@option{enable}] Set/get quirks mode for TI TMS450/TMS570 processors Disabled by default @end deffn @@ -4612,7 +4611,7 @@ That may be needed to let you write the boot loader into flash, in order to ``de-brick'' your board; or to load programs into external DDR memory without having run the boot loader. -@deffn {Command} {target create} target_name type configparams... +@deffn {Config Command} {target create} target_name type configparams... This command creates a GDB debug target that refers to a specific JTAG tap. It enters that target into a list, and creates a new command (@command{@var{target_name}}) which is used for various @@ -6238,7 +6237,7 @@ The @var{kinetis} driver defines option: flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME @end example -@deffn {Command} {kinetis create_banks} +@deffn {Config Command} {kinetis create_banks} Configuration command enables automatic creation of additional flash banks based on real flash layout of device. Banks are created during device probe. Use 'flash probe 0' to force probe. @@ -7806,23 +7805,23 @@ AT91SAM9 chips support single-bit ECC hardware. The @code{write_page} and disabled by using the @command{nand raw_access} command. There are four additional commands that are needed to fully configure the AT91SAM9 NAND controller. Two are optional; most boards use the same wiring for ALE/CLE: -@deffn {Command} {at91sam9 cle} num addr_line +@deffn {Config Command} {at91sam9 cle} num addr_line Configure the address line used for latching commands. The @var{num} parameter is the value shown by @command{nand list}. @end deffn -@deffn {Command} {at91sam9 ale} num addr_line +@deffn {Config Command} {at91sam9 ale} num addr_line Configure the address line used for latching addresses. The @var{num} parameter is the value shown by @command{nand list}. @end deffn For the next two commands, it is assumed that the pins have already been properly configured for input or output. -@deffn {Command} {at91sam9 rdy_busy} num pio_base_addr pin +@deffn {Config Command} {at91sam9 rdy_busy} num pio_base_addr pin Configure the RDY/nBUSY input from the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @end deffn -@deffn {Command} {at91sam9 ce} num pio_base_addr pin +@deffn {Config Command} {at91sam9 ce} num pio_base_addr pin Configure the chip enable input to the NAND device. The @var{num} parameter is the value shown by @command{nand list}. @var{pio_base_addr} is the base address of the PIO controller and @var{pin} is the pin number. @@ -8109,7 +8108,7 @@ the default log output channel is stderr. Add @var{directory} to the file/script search path. @end deffn -@deffn {Command} {bindto} [@var{name}] +@deffn {Config Command} {bindto} [@var{name}] Specify hostname or IPv4 address on which to listen for incoming TCP/IP connections. By default, OpenOCD will listen on the loopback interface only. If your network environment is safe, @code{bindto From 833a2a56f4649d4a59738d902405f1093adf4e58 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 7 Apr 2021 15:18:04 +0200 Subject: [PATCH 28/58] doc: do not document commands that are already deprecated The command 'ftdi_location' is deprecated and a TCL procedure is in place to direct the user to the replacement command. There is no need to document the deprecated command. Remove 'ftdi_location' from the documentation. Change-Id: Ia431c6b0e7444d3f3288c088429bfb47089ff1b5 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6154 Tested-by: jenkins Reviewed-by: Marc Schink --- doc/openocd.texi | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 44dcbdb8a..3523a222a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2517,19 +2517,6 @@ If not specified, serial numbers are not considered. and are not restricted to containing only decimal digits.) @end deffn -@deffn {Config Command} {ftdi_location} -[.]... -@emph{DEPRECATED -- avoid using this. -Use the command @ref{adapter_usb_location,,adapter usb location} instead.} - -Specifies the physical USB port of the adapter to use. The path -roots at @var{bus} and walks down the physical ports, with each -@var{port} option specifying a deeper level in the bus topology, the last -@var{port} denoting where the target adapter is actually plugged. -The USB bus topology can be queried with the command @emph{lsusb -t}. - -This command is only available if your libusb1 is at least version 1.0.16. -@end deffn - @deffn {Config Command} {ftdi_channel} channel Selects the channel of the FTDI device to use for MPSSE operations. Most adapters use the default, channel 0, but there are exceptions. From 642cdae32167df80d4dc757f0da5f204e0298088 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 7 Apr 2021 15:25:37 +0200 Subject: [PATCH 29/58] doc: command 'ftdi_layout_signal' can run after config The mode of command 'ftdi_layout_signal' is set to COMMAND_ANY in [1] and the command has no constraints that limits its use to the config phase only. But [2] documents it as '{Config Command}'. Update the documentation to report the correct mode '{Command}'. [1] commit f5e97b5e1b62 ("Add FTDI JTAG driver using MPSSE layer") [2] commit 76afadeb7b4e ("doc: Add documentation for the ftdi driver") Change-Id: I6b14aebb98e48f7080c585f3df881714bb188af0 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6155 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 3523a222a..4dd3a3389 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2531,7 +2531,7 @@ minimal impact on the target system. Avoid floating inputs, conflicting outputs and initially asserted reset signals. @end deffn -@deffn {Config Command} {ftdi_layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-input}|@option{-ninput} input_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name] +@deffn {Command} {ftdi_layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-input}|@option{-ninput} input_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name] Creates a signal with the specified @var{name}, controlled by one or more FTDI GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO register bitmasks to tell the driver the connection and type of the output From df443551a8d4cf74cea695ebf16b05db684f3d4e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 10 Apr 2021 15:31:39 +0200 Subject: [PATCH 30/58] board: imx53: fix l2 cache initialization Both http://openocd.zylin.com/542/ and http://openocd.zylin.com/543/ introduce the same typo in the bitfield for initializing the l2 cache of imx53. One year later, http://openocd.zylin.com/1461/ copy-pastes the same typo. The comment above the code show that it's really an error and not the expected behaviour. Fix the typo replacing the incorrect comparison '<' with a left shift. Change-Id: I43725731a2228e28a676215f76936fa289d9395e Signed-off-by: Antonio Borneo Fixes: e3b327343394 ("cfg: add imx53loco board config") Fixes: 108a458ab888 ("cfg: add icnova_imx53_sodimm board config") Fixes: e608ced33001 ("ftdi/board: Add support for DENX M53EVK") Reviewed-on: http://openocd.zylin.com/6156 Tested-by: jenkins Reviewed-by: Adrian M Negreanu Reviewed-by: Oleksij Rempel --- tcl/board/icnova_imx53_sodimm.cfg | 2 +- tcl/board/imx53-m53evk.cfg | 2 +- tcl/board/imx53loco.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tcl/board/icnova_imx53_sodimm.cfg b/tcl/board/icnova_imx53_sodimm.cfg index dce9c470e..af9818814 100644 --- a/tcl/board/icnova_imx53_sodimm.cfg +++ b/tcl/board/icnova_imx53_sodimm.cfg @@ -79,7 +79,7 @@ proc init_l2cc { } { ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 - arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] + arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)] } diff --git a/tcl/board/imx53-m53evk.cfg b/tcl/board/imx53-m53evk.cfg index baeb3cd9d..b529c4940 100644 --- a/tcl/board/imx53-m53evk.cfg +++ b/tcl/board/imx53-m53evk.cfg @@ -75,7 +75,7 @@ proc init_l2cc { } { ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 - arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] + arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)] } diff --git a/tcl/board/imx53loco.cfg b/tcl/board/imx53loco.cfg index 18caca574..91c260138 100644 --- a/tcl/board/imx53loco.cfg +++ b/tcl/board/imx53loco.cfg @@ -80,7 +80,7 @@ proc init_l2cc { } { ; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #mcr 15, 1, r0, c9, c0, 2 - arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] + arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)] } From 6f1252373ba3ff584011ad9568da117ce7ecdc35 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 10 Apr 2021 15:58:22 +0200 Subject: [PATCH 31/58] tcl/at91/sam9_smc: fix syntax errors This file has been added to OpenOCD 0.5.0 in 2011, before gerrit gets in use, with commit ba71e8c521a7 ("at91: add chip register definition and generic init support"). The only procedure in the file has never been referenced in any other part of OpenOCD. This procedure has syntax errors while uses its argument 'cs' and several unmatched parenthesis, which clearly highlights that it has never been used so far. Gerrit does not report any patch aimed at fixing it. Even if the file seems unused and could be removed, let's fix it in the hope it could get used. While there, remove some useless parenthesis and format it using the new simplified syntax required by jimtcl 0.81. Change-Id: Ied26456262e7b99de37667a8ce418f4f12e237bd Signed-off-by: Antonio Borneo Fixes: ba71e8c521a7 ("at91: add chip register definition and generic init support") Reviewed-on: http://openocd.zylin.com/6157 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- tcl/chip/atmel/at91/sam9_smc.cfg | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tcl/chip/atmel/at91/sam9_smc.cfg b/tcl/chip/atmel/at91/sam9_smc.cfg index db943cb24..0628d4d18 100644 --- a/tcl/chip/atmel/at91/sam9_smc.cfg +++ b/tcl/chip/atmel/at91/sam9_smc.cfg @@ -26,30 +26,30 @@ # tdf_cycles proc sam9_smc_config { cs smc_config } { ;# Setup Register for CS n - set AT91_SMC_SETUP [expr ($::AT91_SMC + 0x00 + ((cs)*0x10))] - set val [expr ($smc_config(nwe_setup) << 0)] - set val [expr ($val | $smc_config(ncs_write_setup) << 8] - set val [expr ($val | $smc_config(nrd_setup)) << 16] - set val [expr ($val | $smc_config(ncs_read_setup) << 24] + set AT91_SMC_SETUP [expr {$::AT91_SMC + 0x00 + $cs * 0x10}] + set val [expr {$smc_config(nwe_setup) << 0}] + set val [expr {$val | $smc_config(ncs_write_setup) << 8}] + set val [expr {$val | $smc_config(nrd_setup)) << 16}] + set val [expr {$val | $smc_config(ncs_read_setup) << 24}] mww $AT91_SMC_SETUP $val ;# Pulse Register for CS n - set AT91_SMC_PULSE [expr ($::AT91_SMC + 0x04 + ((cs)*0x10))] - set val [expr ($smc_config(nwe_pulse) << 0)] - set val [expr ($val | $smc_config(ncs_write_pulse) << 8] - set val [expr ($val | $smc_config(nrd_pulse) << 16] - set val [expr ($val | $smc_config(ncs_read_pulse) << 24] + set AT91_SMC_PULSE [expr {$::AT91_SMC + 0x04 + $cs * 0x10}] + set val [expr {$smc_config(nwe_pulse) << 0}] + set val [expr {$val | $smc_config(ncs_write_pulse) << 8}] + set val [expr {$val | $smc_config(nrd_pulse) << 16}] + set val [expr {$val | $smc_config(ncs_read_pulse) << 24}] mww $AT91_SMC_PULSE $val ;# Cycle Register for CS n - set AT91_SMC_CYCLE [expr ($::AT91_SMC + 0x08 + ((cs)*0x10))] - set val [expr ($smc_config(write_cycle) << 0)] - set val [expr ($val | $smc_config(read_cycle) << 16] + set AT91_SMC_CYCLE [expr {$::AT91_SMC + 0x08 + $cs * 0x10}] + set val [expr {$smc_config(write_cycle) << 0}] + set val [expr {$val | $smc_config(read_cycle) << 16}] mww $AT91_SMC_CYCLE $val ;# Mode Register for CS n - set AT91_SMC_MODE [expr ($::AT91_SMC + 0x0c + ((cs)*0x10))] - set val [expr ($smc_config(mode) << 0)] - set val [expr ($val | $smc_config(tdf_cycles) << 16] + set AT91_SMC_MODE [expr {$::AT91_SMC + 0x0c + $cs * 0x10}] + set val [expr {$smc_config(mode) << 0}] + set val [expr {$val | $smc_config(tdf_cycles) << 16}] mww $AT91_SMC_MODE $val } From 45eff3a8069dd95a6614f6c6482c7b21f2a84ad6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 5 Apr 2021 08:44:39 +0200 Subject: [PATCH 32/58] target/arm_adi_v5: add JTAG_TO_DORMANT sequence Change-Id: Ie9e32e42a84cf88bf779e691a67c114eef1bb457 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6136 Tested-by: jenkins --- src/target/arm_adi_v5.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 8edfaa816..047606c43 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -162,6 +162,7 @@ enum swd_special_seq { LINE_RESET, JTAG_TO_SWD, + JTAG_TO_DORMANT, SWD_TO_JTAG, SWD_TO_DORMANT, DORMANT_TO_SWD, From a5471b1b2c5675fa0caa462e742916c54f9a08e2 Mon Sep 17 00:00:00 2001 From: Peter Lawrence Date: Fri, 19 Mar 2021 16:26:52 +0100 Subject: [PATCH 33/58] drivers/cmsis-dap: add multidrop capability Uses CMSIS-DAP v 1.2 or higher protocol command DAP_SWD_Sequence to write to DP TARGETSEL register. This write is not acknowledged by device so we cannot use standard DAP_Transfer Change-Id: Ib252d09570bcc2282be5f854e0ab9a0dfda06189 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6117 Tested-by: jenkins Reviewed-by: Peter Lawrence --- src/jtag/drivers/cmsis_dap.c | 67 ++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 6ab087598..fb5c86aec 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -136,6 +136,7 @@ static bool swd_mode; /* CMSIS-DAP SWD Commands */ #define CMD_DAP_SWD_CONFIGURE 0x13 +#define CMD_DAP_SWD_SEQUENCE 0x1D /* CMSIS-DAP JTAG Commands */ #define CMD_DAP_JTAG_SEQ 0x14 @@ -542,6 +543,45 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us) } #endif +static int cmsis_dap_metacmd_targetsel(uint32_t instance_id) +{ + int retval; + uint8_t *command = cmsis_dap_handle->command; + const uint32_t SEQ_RD = 0x80, SEQ_WR = 0x00; + + /* SWD multi-drop requires a transfer ala CMD_DAP_TFER, + but with no expectation of an SWD ACK response. In + CMSIS-DAP v1.20 and v2.00, CMD_DAP_SWD_SEQUENCE was + added to allow this special sequence to be generated. + The purpose of this operation is to select the target + corresponding to the instance_id that is written */ + + size_t idx = 0; + command[idx++] = CMD_DAP_SWD_SEQUENCE; + command[idx++] = 3; /* sequence count */ + + /* sequence 0: packet request for TARGETSEL */ + command[idx++] = SEQ_WR | 8; + command[idx++] = SWD_CMD_START | swd_cmd(false, false, DP_TARGETSEL) | SWD_CMD_STOP | SWD_CMD_PARK; + + /* sequence 1: read Trn ACK Trn, no expectation for target to ACK */ + command[idx++] = SEQ_RD | 5; + + /* sequence 2: WDATA plus parity */ + command[idx++] = SEQ_WR | (32 + 1); + h_u32_to_le(command + idx, instance_id); + idx += 4; + command[idx++] = parity_u32(instance_id); + + retval = cmsis_dap_xfer(cmsis_dap_handle, idx); + + if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) { + LOG_ERROR("CMSIS-DAP command SWD_Sequence failed."); + return ERROR_JTAG_DEVICE_ERROR; + } + return ERROR_OK; +} + static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) { uint8_t *command = cmsis_dap_handle->command; @@ -715,7 +755,10 @@ static int cmsis_dap_swd_run_queue(void) static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) { - if (pending_fifo[pending_fifo_put_idx].transfer_count == pending_queue_len) { + bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd; + + if (pending_fifo[pending_fifo_put_idx].transfer_count == pending_queue_len + || targetsel_cmd) { if (pending_fifo_block_count) cmsis_dap_swd_read_process(cmsis_dap_handle, 0); @@ -729,6 +772,11 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) if (queued_retval != ERROR_OK) return; + if (targetsel_cmd) { + cmsis_dap_metacmd_targetsel(data); + return; + } + struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx]; struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]); transfer->data = data; @@ -846,7 +894,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) switch (seq) { case LINE_RESET: - LOG_DEBUG("SWD line reset"); + LOG_DEBUG_IO("SWD line reset"); s = swd_seq_line_reset; s_len = swd_seq_line_reset_len; break; @@ -855,11 +903,26 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) s = swd_seq_jtag_to_swd; s_len = swd_seq_jtag_to_swd_len; break; + case JTAG_TO_DORMANT: + LOG_DEBUG("JTAG-to-DORMANT"); + s = swd_seq_jtag_to_dormant; + s_len = swd_seq_jtag_to_dormant_len; + break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); s = swd_seq_swd_to_jtag; s_len = swd_seq_swd_to_jtag_len; break; + case SWD_TO_DORMANT: + LOG_DEBUG("SWD-to-DORMANT"); + s = swd_seq_swd_to_dormant; + s_len = swd_seq_swd_to_dormant_len; + break; + case DORMANT_TO_SWD: + LOG_DEBUG("DORMANT-to-SWD"); + s = swd_seq_dormant_to_swd; + s_len = swd_seq_dormant_to_swd_len; + break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; From 44554698472aae5b02620eb91837118ada4d2bfe Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 5 Apr 2021 06:32:47 +0200 Subject: [PATCH 34/58] target/adi_v5_swd: remove double space from swd_cmd() parameters Change-Id: I6b68868947010512c4de76e5d37142f067e27b06 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6137 Tested-by: jenkins --- src/target/adi_v5_swd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index b25181e21..f1fca40ae 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -74,7 +74,7 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap) const struct swd_driver *swd = adiv5_dap_swd_driver(dap); assert(swd); - swd->write_reg(swd_cmd(false, false, DP_ABORT), + swd->write_reg(swd_cmd(false, false, DP_ABORT), STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); } @@ -174,7 +174,7 @@ static int swd_connect(struct adiv5_dap *dap) dap->do_reconnect = false; - swd->write_reg(swd_cmd(false, false, DP_ABORT), + swd->write_reg(swd_cmd(false, false, DP_ABORT), DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); status = swd_run_inner(dap); } @@ -325,7 +325,7 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, if (retval != ERROR_OK) return retval; - swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck); + swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck); dap->last_read = data; return check_sync(dap); @@ -347,7 +347,7 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, if (retval != ERROR_OK) return retval; - swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck); + swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck); return check_sync(dap); } From ab337d05f432465fdfedb694ac862fb22f80d7a6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 6 Apr 2021 13:46:07 +0200 Subject: [PATCH 35/58] target/arm_adi_v5: move DP register definitions to one block DP and MEM-AP definitions were mixed. Change-Id: I2f691b2274c01e9090c1e5160c6903d3207e35c2 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6138 Tested-by: jenkins --- src/target/arm_adi_v5.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 047606c43..00e4ea2b2 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -85,6 +85,15 @@ #define CSYSPWRUPREQ (1UL << 30) #define CSYSPWRUPACK (1UL << 31) +#define DP_SELECT_APSEL 0xFF000000 +#define DP_SELECT_APBANK 0x000000F0 +#define DP_SELECT_DPBANK 0x0000000F +#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */ + +#define DP_APSEL_MAX (255) +#define DP_APSEL_INVALID (-1) + + /* MEM-AP register addresses */ #define MEM_AP_REG_CSW 0x00 #define MEM_AP_REG_TAR 0x04 @@ -150,14 +159,6 @@ #define IDR_JEP106_ARM 0x04760000 -#define DP_SELECT_APSEL 0xFF000000 -#define DP_SELECT_APBANK 0x000000F0 -#define DP_SELECT_DPBANK 0x0000000F -#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */ - -#define DP_APSEL_MAX (255) -#define DP_APSEL_INVALID (-1) - /* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */ enum swd_special_seq { LINE_RESET, From ef0aa38c108be536deff73c299ba542e215a892f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 22 Apr 2021 08:40:02 +0200 Subject: [PATCH 36/58] target/armv7m: change FPv4_SP and FPv5_SP/DP identifiers to uppercase Change-Id: Ia421a973e5fb4767715c9f95c91745f8ca1de1da Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/6177 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/FreeRTOS.c | 2 +- src/rtos/nuttx.c | 2 +- src/target/armv7m.h | 6 +++--- src/target/cortex_m.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 4d520b9b4..f04b0a268 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -438,7 +438,7 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, int cm4_fpu_enabled = 0; struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); if (is_armv7m(armv7m_target)) { - if (armv7m_target->fp_feature == FPv4_SP) { + if (armv7m_target->fp_feature == FPV4_SP) { /* Found ARM v7m target which includes a FPU */ uint32_t cpacr; diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 6569e38f2..0705b17b3 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -352,7 +352,7 @@ static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, bool cm4_fpu_enabled = false; struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); if (is_armv7m(armv7m_target)) { - if (armv7m_target->fp_feature == FPv4_SP) { + if (armv7m_target->fp_feature == FPV4_SP) { /* Found ARM v7m target which includes a FPU */ uint32_t cpacr; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index db6f8bc52..f5679b91d 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -169,9 +169,9 @@ enum { enum { FP_NONE = 0, - FPv4_SP, - FPv5_SP, - FPv5_DP, + FPV4_SP, + FPV5_SP, + FPV5_DP, }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 6dc33c867..e7a2fadda 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2019,7 +2019,7 @@ int cortex_m_examine(struct target *target) /* test for floating point feature on Cortex-M4 */ if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i); - armv7m->fp_feature = FPv4_SP; + armv7m->fp_feature = FPV4_SP; } } else if (i == 7 || i == 33 || i == 35 || i == 55) { target_read_u32(target, MVFR0, &mvfr0); @@ -2028,10 +2028,10 @@ int cortex_m_examine(struct target *target) /* test for floating point features on Cortex-M7 */ if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i); - armv7m->fp_feature = FPv5_SP; + armv7m->fp_feature = FPV5_SP; } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i); - armv7m->fp_feature = FPv5_DP; + armv7m->fp_feature = FPV5_DP; } } else if (i == 0) { /* Cortex-M0 does not support unaligned memory access */ From 2c4f7efbf6ca467121e96dd044b9fdf373774550 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Wed, 21 Apr 2021 10:18:04 +0100 Subject: [PATCH 37/58] doc/openocd.texi: fix warning fix the warning below by adding a '.' after xref in line 4517: ../code/doc/openocd.texi:4517: warning: `.' or `,' must follow @xref, not ) Change-Id: I6e529c7e83c9f912e1dd899abf5f630c90b583d9 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/6174 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 4dd3a3389..21b6e952a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4500,7 +4500,7 @@ a CPU, through which bus read and write cycles can be generated; it may be useful for working with non-CPU hardware behind an AP or during development of support for new CPUs. It's possible to connect a GDB client to this target (the GDB port has to be -specified, @xref{gdbportoverride,,option -gdb-port}), and a fake ARM core will +specified, @xref{gdbportoverride,,option -gdb-port}.), and a fake ARM core will be emulated to comply to GDB remote protocol. @item @code{mips_m4k} -- a MIPS core. @item @code{mips_mips64} -- a MIPS64 core. From fd40d0967607f8ee7d0aabf7ea7fd93cfc419bf1 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 22 Apr 2021 14:34:14 +0100 Subject: [PATCH 38/58] doc/openocd.texi: fix warning fix the warning below by adding a '.' after xref in line 10184: ./doc/openocd.texi:10184: warning: `.' or `,' must follow @xref, not c Change-Id: Ibd976ae61cf6845e925b839321444dcb25a3c04a Reported-by: Tomas Vanek Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/6179 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 21b6e952a..c39e7c168 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10167,7 +10167,7 @@ startbit endbit}. @deffn {Command} {arc get-reg-field} reg-name field-name Returns value of bit-field in a register. Register must be ``struct'' register -type, @xref{add-reg-type-struct} command definition. +type, @xref{add-reg-type-struct}. command definition. @end deffn @deffn {Command} {arc set-reg-exists} reg-names... From ef0da7944886466bc09386616fa089925be5ac62 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 12 Jan 2021 20:10:23 +0100 Subject: [PATCH 39/58] cortex_m: mark FPU register as non-existent instead of playing with num_regs Change-Id: Iac7c5bfbb95c8d9a8c6d65104d138692a44eca78 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/6015 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/armv7m.h | 8 ++++++-- src/target/cortex_m.c | 16 ++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/target/armv7m.h b/src/target/armv7m.h index f5679b91d..652dbe798 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -164,7 +164,12 @@ enum { /* Floating-point status register */ ARMV7M_FPSCR, + /* for convenience add registers' block delimiters */ ARMV7M_LAST_REG, + ARMV7M_CORE_FIRST_REG = ARMV7M_R0, + ARMV7M_CORE_LAST_REG = ARMV7M_xPSR, + ARMV7M_FPU_FIRST_REG = ARMV7M_D0, + ARMV7M_FPU_LAST_REG = ARMV7M_FPSCR, }; enum { @@ -174,8 +179,7 @@ enum { FPV5_DP, }; -#define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) -#define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_CONTROL + 1) +#define ARMV7M_NUM_CORE_REGS (ARMV7M_CORE_LAST_REG - ARMV7M_CORE_FIRST_REG + 1) #define ARMV7M_COMMON_MAGIC 0x2A452A45 diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index e7a2fadda..46b0e3c2a 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2038,19 +2038,11 @@ int cortex_m_examine(struct target *target) armv7m->arm.is_armv6m = true; } - if (armv7m->fp_feature == FP_NONE && - armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { - /* free unavailable FPU registers */ - size_t idx; + /* Check for FPU, otherwise mark FPU register as non-existent */ + if (armv7m->fp_feature == FP_NONE) + for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++) + armv7m->arm.core_cache->reg_list[idx].exist = false; - for (idx = ARMV7M_NUM_CORE_REGS_NOFP; - idx < armv7m->arm.core_cache->num_regs; - idx++) { - free(armv7m->arm.core_cache->reg_list[idx].feature); - free(armv7m->arm.core_cache->reg_list[idx].reg_data_type); - } - armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; - } if (!armv7m->stlink) { if (i == 3 || i == 4) From a60979b069b5964639d87ce268a37078c0fb57bb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 26 Apr 2021 09:48:25 +0200 Subject: [PATCH 40/58] helper/command: fix build with jimtcl 0.79 or older Commit a7d68878e4ba ("helper/command: unregister commands through their full-name") introduces for the first time in OpenOCD the use of jimtcl API Jim_DeleteCommand(). The prototype of Jim_DeleteCommand() has changed with jimtcl 0.80 and the current code doesn't build with jimtcl 0.79 or older. This is an issue for those distributions, like Debian, that provide jimtcl as a separate package/library and have not switched yet to the new jimtcl version. Add a compile-time condition to cope with the jimtcl API change. Change-Id: Ic813ab7c0ebd3c8772f27775ba3912a47d5c275c Signed-off-by: Antonio Borneo Fixes: a7d68878e4ba ("helper/command: unregister commands through their full-name") Reviewed-on: http://openocd.zylin.com/6191 Tested-by: jenkins --- src/helper/command.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helper/command.c b/src/helper/command.c index 80e297b1f..e703be400 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -437,7 +437,11 @@ int unregister_commands_match(struct command_context *cmd_ctx, const char *forma continue; } LOG_DEBUG("delete command \"%s\"", name); +#if JIM_VERSION >= 80 Jim_DeleteCommand(interp, elem); +#else + Jim_DeleteCommand(interp, name); +#endif help_del_command(cmd_ctx, name); From 11d918d9c1f7cb637a525a92521b747d2d4c840f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 14 Apr 2021 23:44:57 +0200 Subject: [PATCH 41/58] libusb: don't use typedef's Libusb defines both the struct and a typedef to the struct using the same struct name. It's then possible to use either 'struct x' and 'x'. E.g.: typedef struct libusb_device libusb_device; OpenOCD is not consistent and uses a mix of 'struct x' and 'x'. To make OpenOCD code uniform, stick at project's coding style and use 'struct x' in place of the typedef'd name. Change-Id: I901458b680e42830d3f371e47997157f91b7f675 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6165 Tested-by: jenkins Reviewed-by: Jonathan McDowell Reviewed-by: Marc Schink Reviewed-by: Tomas Vanek --- src/jtag/aice/aice_usb.c | 8 ++++---- src/jtag/drivers/cmsis_dap_usb_bulk.c | 12 ++++++------ src/jtag/drivers/libusb_helper.c | 10 +++++----- src/jtag/drivers/libusb_helper.h | 2 +- src/jtag/drivers/mpsse.c | 12 ++++++------ src/jtag/drivers/rlink.c | 14 +++++++------- src/jtag/drivers/stlink_usb.c | 2 +- src/jtag/drivers/ulink.c | 2 +- src/jtag/drivers/versaloon/versaloon.c | 2 +- src/jtag/drivers/versaloon/versaloon.h | 2 +- src/jtag/drivers/vsllink.c | 4 ++-- src/jtag/drivers/xds110.c | 10 +++++----- 12 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 7688aeaab..0c219805f 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -349,8 +349,8 @@ 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)(libusb_device_handle *, int, char *, int, int, int *), - libusb_device_handle *dev, int ep, + int (*f)(struct libusb_device_handle *, int, char *, int, int, int *), + struct libusb_device_handle *dev, int ep, char *bytes, int size, int timeout, int *transferred) { int tries = 3, count = 0; @@ -369,7 +369,7 @@ static int usb_bulk_with_retries( return ERROR_OK; } -static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep, +static int wrap_usb_bulk_write(struct libusb_device_handle *dev, int ep, char *buff, int size, int timeout, int *transferred) { @@ -379,7 +379,7 @@ static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep, return 0; } -static inline int usb_bulk_write_ex(libusb_device_handle *dev, int ep, +static inline int usb_bulk_write_ex(struct libusb_device_handle *dev, int ep, char *bytes, int size, int timeout) { int tr = 0; diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index c9ee53d2e..f535119f3 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -41,8 +41,8 @@ #include "cmsis_dap.h" struct cmsis_dap_backend_data { - libusb_context *usb_ctx; - libusb_device_handle *dev_handle; + struct libusb_context *usb_ctx; + struct libusb_device_handle *dev_handle; unsigned int ep_out; unsigned int ep_in; int interface; @@ -56,8 +56,8 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial) { int err; - libusb_context *ctx; - libusb_device **device_list; + struct libusb_context *ctx; + struct libusb_device **device_list; err = libusb_init(&ctx); if (err) { @@ -73,7 +73,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p } for (int i = 0; i < num_devices; i++) { - libusb_device *dev = device_list[i]; + struct libusb_device *dev = device_list[i]; struct libusb_device_descriptor dev_desc; err = libusb_get_device_descriptor(dev, &dev_desc); @@ -101,7 +101,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p if (dev_desc.iSerialNumber == 0 && serial && serial[0]) continue; - libusb_device_handle *dev_handle = NULL; + struct libusb_device_handle *dev_handle = NULL; err = libusb_open(dev, &dev_handle); if (err) { /* It's to be expected that most USB devices can't be opened diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 184882abc..f0122d534 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -31,7 +31,7 @@ #define MAX_USB_PORTS 7 static struct libusb_context *jtag_libusb_context; /**< Libusb context **/ -static libusb_device **devs; /**< The usb device list **/ +static struct libusb_device **devs; /**< The usb device list **/ static int jtag_libusb_error(int err) { @@ -71,7 +71,7 @@ static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, } #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS -static bool jtag_libusb_location_equal(libusb_device *device) +static bool jtag_libusb_location_equal(struct libusb_device *device) { uint8_t port_path[MAX_USB_PORTS]; uint8_t dev_bus; @@ -88,7 +88,7 @@ static bool jtag_libusb_location_equal(libusb_device *device) return jtag_usb_location_equal(dev_bus, port_path, path_len); } #else /* HAVE_LIBUSB_GET_PORT_NUMBERS */ -static bool jtag_libusb_location_equal(libusb_device *device) +static bool jtag_libusb_location_equal(struct libusb_device *device) { return true; } @@ -96,7 +96,7 @@ static bool jtag_libusb_location_equal(libusb_device *device) /* Returns true if the string descriptor indexed by str_index in device matches string */ -static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, +static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index, const char *string) { int retval; @@ -123,7 +123,7 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in return matched; } -static bool jtag_libusb_match_serial(libusb_device_handle *device, +static bool jtag_libusb_match_serial(struct libusb_device_handle *device, struct libusb_device_descriptor *dev_desc, const char *serial, adapter_get_alternate_serial_fn adapter_get_alternate_serial) { diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h index 74bb23c52..fa7d06e28 100644 --- a/src/jtag/drivers/libusb_helper.h +++ b/src/jtag/drivers/libusb_helper.h @@ -24,7 +24,7 @@ /* this callback should return a non NULL value only when the serial could not * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */ -typedef char * (*adapter_get_alternate_serial_fn)(libusb_device_handle *device, +typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device, struct libusb_device_descriptor *dev_desc); int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index fe8b6b82c..7cda3b816 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -62,8 +62,8 @@ #define SIO_RESET_PURGE_TX 2 struct mpsse_ctx { - libusb_context *usb_ctx; - libusb_device_handle *usb_dev; + struct libusb_context *usb_ctx; + struct libusb_device_handle *usb_dev; unsigned int usb_write_timeout; unsigned int usb_read_timeout; uint8_t in_ep; @@ -85,7 +85,7 @@ struct mpsse_ctx { }; /* Returns true if the string descriptor indexed by str_index in device matches string */ -static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, +static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index, const char *string) { int retval; @@ -99,7 +99,7 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in return strncmp(string, desc_string, sizeof(desc_string)) == 0; } -static bool device_location_equal(libusb_device *device, const char *location) +static bool device_location_equal(struct libusb_device *device, const char *location) { bool result = false; #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS @@ -161,7 +161,7 @@ static bool device_location_equal(libusb_device *device, const char *location) static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid, const char *product, const char *serial, const char *location) { - libusb_device **list; + struct libusb_device **list; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config0; int err; @@ -171,7 +171,7 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con LOG_ERROR("libusb_get_device_list() failed with %s", libusb_error_name(cnt)); for (ssize_t i = 0; i < cnt; i++) { - libusb_device *device = list[i]; + struct libusb_device *device = list[i]; err = libusb_get_device_descriptor(device, &desc); if (err != LIBUSB_SUCCESS) { diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index 006e7c5c7..ad629ca68 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -96,14 +96,14 @@ #define ST7_PC_TDO ST7_PC_IO9 #define ST7_PA_DBGACK ST7_PA_IO10 -static libusb_device_handle *pHDev; +static struct libusb_device_handle *pHDev; /* * ep1 commands are up to USB_EP1OUT_SIZE bytes in length. * This function takes care of zeroing the unused bytes before sending the packet. * Any reply packet is not handled by this function. */ -static int ep1_generic_commandl(libusb_device_handle *pHDev_param, size_t length, ...) +static int ep1_generic_commandl(struct libusb_device_handle *pHDev_param, size_t length, ...) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t *usb_buffer_p; @@ -143,7 +143,7 @@ static int ep1_generic_commandl(libusb_device_handle *pHDev_param, size_t length #if 0 static ssize_t ep1_memory_read( - libusb_device_handle *pHDev_param, uint16_t addr, + struct libusb_device_handle *pHDev_param, uint16_t addr, size_t length, uint8_t *buffer) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; @@ -202,7 +202,7 @@ static ssize_t ep1_memory_read( } #endif -static ssize_t ep1_memory_write(libusb_device_handle *pHDev_param, uint16_t addr, +static ssize_t ep1_memory_write(struct libusb_device_handle *pHDev_param, uint16_t addr, size_t length, uint8_t const *buffer) { uint8_t usb_buffer[USB_EP1OUT_SIZE]; @@ -258,7 +258,7 @@ static ssize_t ep1_memory_write(libusb_device_handle *pHDev_param, uint16_t addr #if 0 -static ssize_t ep1_memory_writel(libusb_device_handle *pHDev_param, uint16_t addr, +static ssize_t ep1_memory_writel(struct libusb_device_handle *pHDev_param, uint16_t addr, size_t length, ...) { uint8_t buffer[USB_EP1OUT_SIZE - 4]; @@ -295,7 +295,7 @@ static ssize_t ep1_memory_writel(libusb_device_handle *pHDev_param, uint16_t add static uint8_t dtc_entry_download; /* The buffer is specially formatted to represent a valid image to load into the DTC. */ -static int dtc_load_from_buffer(libusb_device_handle *pHDev_param, const uint8_t *buffer, +static int dtc_load_from_buffer(struct libusb_device_handle *pHDev_param, const uint8_t *buffer, size_t length) { struct header_s { @@ -469,7 +469,7 @@ static int dtc_start_download(void) } static int dtc_run_download( - libusb_device_handle *pHDev_param, + struct libusb_device_handle *pHDev_param, uint8_t *command_buffer, int command_buffer_size, uint8_t *reply_buffer, diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a5f8bdff1..a088a83ee 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -3016,7 +3016,7 @@ static int stlink_close(void *handle) * based on the length (0x1a = 26) we could easily decide if we have to fixup the serial * and then we have just to convert the raw data into printable characters using sprintf */ -static char *stlink_usb_get_alternate_serial(libusb_device_handle *device, +static char *stlink_usb_get_alternate_serial(struct libusb_device_handle *device, struct libusb_device_descriptor *dev_desc) { int usb_retval; diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index ccc023fb8..096e254fa 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -266,7 +266,7 @@ static int ulink_usb_open(struct ulink **device) { ssize_t num_devices, i; bool found; - libusb_device **usb_devices; + struct libusb_device **usb_devices; struct libusb_device_descriptor usb_desc; struct libusb_device_handle *usb_device_handle; diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c index b51779500..194a3751c 100644 --- a/src/jtag/drivers/versaloon/versaloon.c +++ b/src/jtag/drivers/versaloon/versaloon.c @@ -35,7 +35,7 @@ uint16_t versaloon_buf_size; struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; uint16_t versaloon_pending_idx; -libusb_device_handle *versaloon_usb_device_handle; +struct libusb_device_handle *versaloon_usb_device_handle; static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT; static RESULT versaloon_init(void); diff --git a/src/jtag/drivers/versaloon/versaloon.h b/src/jtag/drivers/versaloon/versaloon.h index 9d92bcaa1..fcf223574 100644 --- a/src/jtag/drivers/versaloon/versaloon.h +++ b/src/jtag/drivers/versaloon/versaloon.h @@ -107,6 +107,6 @@ struct versaloon_interface_t { }; extern struct versaloon_interface_t versaloon_interface; -extern libusb_device_handle *versaloon_usb_device_handle; +extern struct libusb_device_handle *versaloon_usb_device_handle; #endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H */ diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 9aaed36b7..f08fa9165 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -812,7 +812,7 @@ static int vsllink_check_usb_strings( static int vsllink_usb_open(struct vsllink *vsllink) { ssize_t num_devices, i; - libusb_device **usb_devices; + struct libusb_device **usb_devices; struct libusb_device_descriptor usb_desc; struct libusb_device_handle *usb_device_handle; int retval; @@ -823,7 +823,7 @@ static int vsllink_usb_open(struct vsllink *vsllink) return ERROR_FAIL; for (i = 0; i < num_devices; i++) { - libusb_device *device = usb_devices[i]; + struct libusb_device *device = usb_devices[i]; retval = libusb_get_device_descriptor(device, &usb_desc); if (retval != 0) diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index df1ab6529..c49280743 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -213,8 +213,8 @@ struct scan_result { struct xds110_info { /* USB connection handles and data buffers */ - libusb_context *ctx; - libusb_device_handle *dev; + struct libusb_context *ctx; + struct libusb_device_handle *dev; unsigned char read_payload[USB_PAYLOAD_SIZE]; unsigned char write_packet[3]; unsigned char write_payload[USB_PAYLOAD_SIZE]; @@ -317,9 +317,9 @@ static inline uint16_t xds110_get_u16(uint8_t *buffer) static bool usb_connect(void) { - libusb_context *ctx = NULL; - libusb_device **list = NULL; - libusb_device_handle *dev = NULL; + struct libusb_context *ctx = NULL; + struct libusb_device **list = NULL; + struct libusb_device_handle *dev = NULL; struct libusb_device_descriptor desc; From 9206bd243b0b594821ca96b37517b2e3de80dc39 Mon Sep 17 00:00:00 2001 From: Florian Meister Date: Wed, 5 Jun 2019 10:19:52 +0200 Subject: [PATCH 42/58] target/image: allow loading of 64-bit ELF files Change-Id: I9b88edacf5ffcc3c1caeab8c426693de0d92a695 Signed-off-by: Florian Meister Signed-off-by: Christian Hoff Reviewed-on: http://openocd.zylin.com/5204 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Ooi, Cinly Reviewed-by: Tomas Vanek --- configure.ac | 3 + src/helper/replacements.h | 42 ++++- src/target/image.c | 349 ++++++++++++++++++++++++++++++++------ src/target/image.h | 18 +- 4 files changed, 351 insertions(+), 61 deletions(-) diff --git a/configure.ac b/configure.ac index 5c7dab570..979bb161b 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,9 @@ AC_SEARCH_LIBS([openpty], [util]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([elf.h]) +AC_EGREP_HEADER(Elf64_Ehdr, [elf.h], [ + AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type `Elf64_Ehdr'.]) +]) AC_CHECK_HEADERS([dirent.h]) AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([malloc.h]) diff --git a/src/helper/replacements.h b/src/helper/replacements.h index ac5009549..fff2dde0e 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -246,8 +246,10 @@ typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Size; typedef Elf32_Off Elf32_Hashelt; +#define EI_NIDENT 16 + typedef struct { - unsigned char e_ident[16]; /* Magic number and other info */ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf32_Half e_type; /* Object file type */ Elf32_Half e_machine; /* Architecture */ Elf32_Word e_version; /* Object file version */ @@ -289,6 +291,44 @@ typedef struct { #endif /* HAVE_ELF_H */ +#ifndef HAVE_ELF64 + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +typedef struct { + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +#endif /* HAVE_ELF64 */ + #if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME const char *libusb_error_name(int error_code); #endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */ diff --git a/src/target/image.c b/src/target/image.c index e63cd0f9c..9608375a5 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -11,6 +11,9 @@ * Copyright (C) 2009 by Franck Hereson * * franck.hereson@secad.fr * * * + * Copyright (C) 2018 by Advantest * + * florian.meister@advantest.com * + * * * 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 * @@ -42,6 +45,10 @@ ((elf->endianness == ELFDATA2LSB) ? \ le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field)) +#define field64(elf, field) \ + ((elf->endianness == ELFDATA2LSB) ? \ + le_to_h_u64((uint8_t *)&field) : be_to_h_u64((uint8_t *)&field)) + static int autodetect_image_type(struct image *image, const char *url) { int retval; @@ -49,7 +56,7 @@ static int autodetect_image_type(struct image *image, const char *url) size_t read_bytes; uint8_t buffer[9]; - /* read the first 4 bytes of image */ + /* read the first 9 bytes of image */ retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) return retval; @@ -350,22 +357,29 @@ static int image_ihex_buffer_complete(struct image *image) return retval; } -static int image_elf_read_headers(struct image *image) +static int image_elf32_read_headers(struct image *image) { struct image_elf *elf = image->type_private; size_t read_bytes; uint32_t i, j; int retval; - uint32_t nload, load_to_vaddr = 0; + uint32_t nload; + bool load_to_vaddr = false; - elf->header = malloc(sizeof(Elf32_Ehdr)); + retval = fileio_seek(elf->fileio, 0); + if (retval != ERROR_OK) { + LOG_ERROR("cannot seek to ELF file header, read failed"); + return retval; + } - if (elf->header == NULL) { - LOG_ERROR("insufficient memory to perform operation "); + elf->header32 = malloc(sizeof(Elf32_Ehdr)); + + if (elf->header32 == NULL) { + LOG_ERROR("insufficient memory to perform operation"); return ERROR_FILEIO_OPERATION_FAILED; } - retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); + retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header32, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF file header, read failed"); return ERROR_FILEIO_OPERATION_FAILED; @@ -375,42 +389,26 @@ static int image_elf_read_headers(struct image *image) return ERROR_FILEIO_OPERATION_FAILED; } - if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) { - LOG_ERROR("invalid ELF file, bad magic number"); - return ERROR_IMAGE_FORMAT_ERROR; - } - if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) { - LOG_ERROR("invalid ELF file, only 32bits files are supported"); - return ERROR_IMAGE_FORMAT_ERROR; - } - - elf->endianness = elf->header->e_ident[EI_DATA]; - if ((elf->endianness != ELFDATA2LSB) - && (elf->endianness != ELFDATA2MSB)) { - LOG_ERROR("invalid ELF file, unknown endianness setting"); - return ERROR_IMAGE_FORMAT_ERROR; - } - - elf->segment_count = field16(elf, elf->header->e_phnum); + elf->segment_count = field16(elf, elf->header32->e_phnum); if (elf->segment_count == 0) { LOG_ERROR("invalid ELF file, no program headers"); return ERROR_IMAGE_FORMAT_ERROR; } - retval = fileio_seek(elf->fileio, field32(elf, elf->header->e_phoff)); + retval = fileio_seek(elf->fileio, field32(elf, elf->header32->e_phoff)); if (retval != ERROR_OK) { LOG_ERROR("cannot seek to ELF program header table, read failed"); return retval; } - elf->segments = malloc(elf->segment_count*sizeof(Elf32_Phdr)); - if (elf->segments == NULL) { - LOG_ERROR("insufficient memory to perform operation "); + elf->segments32 = malloc(elf->segment_count*sizeof(Elf32_Phdr)); + if (elf->segments32 == NULL) { + LOG_ERROR("insufficient memory to perform operation"); return ERROR_FILEIO_OPERATION_FAILED; } retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), - (uint8_t *)elf->segments, &read_bytes); + (uint8_t *)elf->segments32, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF segment headers, read failed"); return retval; @@ -424,8 +422,8 @@ static int image_elf_read_headers(struct image *image) image->num_sections = 0; for (i = 0; i < elf->segment_count; i++) if ((field32(elf, - elf->segments[i].p_type) == PT_LOAD) && - (field32(elf, elf->segments[i].p_filesz) != 0)) + elf->segments32[i].p_type) == PT_LOAD) && + (field32(elf, elf->segments32[i].p_filesz) != 0)) image->num_sections++; assert(image->num_sections > 0); @@ -441,44 +439,217 @@ static int image_elf_read_headers(struct image *image) * when obtaining lma - look at elf.c of BDF) */ for (nload = 0, i = 0; i < elf->segment_count; i++) - if (elf->segments[i].p_paddr != 0) + if (elf->segments32[i].p_paddr != 0) break; else if ((field32(elf, - elf->segments[i].p_type) == PT_LOAD) && - (field32(elf, elf->segments[i].p_memsz) != 0)) + elf->segments32[i].p_type) == PT_LOAD) && + (field32(elf, elf->segments32[i].p_memsz) != 0)) ++nload; if (i >= elf->segment_count && nload > 1) - load_to_vaddr = 1; + load_to_vaddr = true; /* alloc and fill sections array with loadable segments */ image->sections = malloc(image->num_sections * sizeof(struct imagesection)); + if (image->sections == NULL) { + LOG_ERROR("insufficient memory to perform operation"); + return ERROR_FILEIO_OPERATION_FAILED; + } + for (i = 0, j = 0; i < elf->segment_count; i++) { if ((field32(elf, - elf->segments[i].p_type) == PT_LOAD) && - (field32(elf, elf->segments[i].p_filesz) != 0)) { - image->sections[j].size = field32(elf, elf->segments[i].p_filesz); + elf->segments32[i].p_type) == PT_LOAD) && + (field32(elf, elf->segments32[i].p_filesz) != 0)) { + image->sections[j].size = field32(elf, elf->segments32[i].p_filesz); if (load_to_vaddr) image->sections[j].base_address = field32(elf, - elf->segments[i].p_vaddr); + elf->segments32[i].p_vaddr); else image->sections[j].base_address = field32(elf, - elf->segments[i].p_paddr); - image->sections[j].private = &elf->segments[i]; - image->sections[j].flags = field32(elf, elf->segments[i].p_flags); + elf->segments32[i].p_paddr); + image->sections[j].private = &elf->segments32[i]; + image->sections[j].flags = field32(elf, elf->segments32[i].p_flags); j++; } } image->start_address_set = true; - image->start_address = field32(elf, elf->header->e_entry); + image->start_address = field32(elf, elf->header32->e_entry); return ERROR_OK; } -static int image_elf_read_section(struct image *image, +static int image_elf64_read_headers(struct image *image) +{ + struct image_elf *elf = image->type_private; + size_t read_bytes; + uint32_t i, j; + int retval; + uint32_t nload; + bool load_to_vaddr = false; + + retval = fileio_seek(elf->fileio, 0); + if (retval != ERROR_OK) { + LOG_ERROR("cannot seek to ELF file header, read failed"); + return retval; + } + + elf->header64 = malloc(sizeof(Elf64_Ehdr)); + + if (elf->header64 == NULL) { + LOG_ERROR("insufficient memory to perform operation"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + retval = fileio_read(elf->fileio, sizeof(Elf64_Ehdr), (uint8_t *)elf->header64, &read_bytes); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF file header, read failed"); + return ERROR_FILEIO_OPERATION_FAILED; + } + if (read_bytes != sizeof(Elf64_Ehdr)) { + LOG_ERROR("cannot read ELF file header, only partially read"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + elf->segment_count = field16(elf, elf->header64->e_phnum); + if (elf->segment_count == 0) { + LOG_ERROR("invalid ELF file, no program headers"); + return ERROR_IMAGE_FORMAT_ERROR; + } + + retval = fileio_seek(elf->fileio, field64(elf, elf->header64->e_phoff)); + if (retval != ERROR_OK) { + LOG_ERROR("cannot seek to ELF program header table, read failed"); + return retval; + } + + elf->segments64 = malloc(elf->segment_count*sizeof(Elf64_Phdr)); + if (elf->segments64 == NULL) { + LOG_ERROR("insufficient memory to perform operation"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf64_Phdr), + (uint8_t *)elf->segments64, &read_bytes); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF segment headers, read failed"); + return retval; + } + if (read_bytes != elf->segment_count*sizeof(Elf64_Phdr)) { + LOG_ERROR("cannot read ELF segment headers, only partially read"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + /* count useful segments (loadable), ignore BSS section */ + image->num_sections = 0; + for (i = 0; i < elf->segment_count; i++) + if ((field32(elf, + elf->segments64[i].p_type) == PT_LOAD) && + (field64(elf, elf->segments64[i].p_filesz) != 0)) + image->num_sections++; + + assert(image->num_sections > 0); + + /** + * some ELF linkers produce binaries with *all* the program header + * p_paddr fields zero (there can be however one loadable segment + * that has valid physical address 0x0). + * If we have such a binary with more than + * one PT_LOAD header, then use p_vaddr instead of p_paddr + * (ARM ELF standard demands p_paddr = 0 anyway, and BFD + * library uses this approach to workaround zero-initialized p_paddrs + * when obtaining lma - look at elf.c of BDF) + */ + for (nload = 0, i = 0; i < elf->segment_count; i++) + if (elf->segments64[i].p_paddr != 0) + break; + else if ((field32(elf, + elf->segments64[i].p_type) == PT_LOAD) && + (field64(elf, elf->segments64[i].p_memsz) != 0)) + ++nload; + + if (i >= elf->segment_count && nload > 1) + load_to_vaddr = true; + + /* alloc and fill sections array with loadable segments */ + image->sections = malloc(image->num_sections * sizeof(struct imagesection)); + if (image->sections == NULL) { + LOG_ERROR("insufficient memory to perform operation"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + for (i = 0, j = 0; i < elf->segment_count; i++) { + if ((field32(elf, + elf->segments64[i].p_type) == PT_LOAD) && + (field64(elf, elf->segments64[i].p_filesz) != 0)) { + image->sections[j].size = field64(elf, elf->segments64[i].p_filesz); + if (load_to_vaddr) + image->sections[j].base_address = field64(elf, + elf->segments64[i].p_vaddr); + else + image->sections[j].base_address = field64(elf, + elf->segments64[i].p_paddr); + image->sections[j].private = &elf->segments64[i]; + image->sections[j].flags = field32(elf, elf->segments64[i].p_flags); + j++; + } + } + + image->start_address_set = true; + image->start_address = field64(elf, elf->header64->e_entry); + + return ERROR_OK; +} + +static int image_elf_read_headers(struct image *image) +{ + struct image_elf *elf = image->type_private; + size_t read_bytes; + unsigned char e_ident[EI_NIDENT]; + int retval; + + retval = fileio_read(elf->fileio, EI_NIDENT, e_ident, &read_bytes); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF file header, read failed"); + return ERROR_FILEIO_OPERATION_FAILED; + } + if (read_bytes != EI_NIDENT) { + LOG_ERROR("cannot read ELF file header, only partially read"); + return ERROR_FILEIO_OPERATION_FAILED; + } + + if (strncmp((char *)e_ident, ELFMAG, SELFMAG) != 0) { + LOG_ERROR("invalid ELF file, bad magic number"); + return ERROR_IMAGE_FORMAT_ERROR; + } + + elf->endianness = e_ident[EI_DATA]; + if ((elf->endianness != ELFDATA2LSB) + && (elf->endianness != ELFDATA2MSB)) { + LOG_ERROR("invalid ELF file, unknown endianness setting"); + return ERROR_IMAGE_FORMAT_ERROR; + } + + switch (e_ident[EI_CLASS]) { + case ELFCLASS32: + LOG_DEBUG("ELF32 image detected."); + elf->is_64_bit = false; + return image_elf32_read_headers(image); + + case ELFCLASS64: + LOG_DEBUG("ELF64 image detected."); + elf->is_64_bit = true; + return image_elf64_read_headers(image); + + default: + LOG_ERROR("invalid ELF file, only 32/64 bit ELF files are supported"); + return ERROR_IMAGE_FORMAT_ERROR; + } +} + +static int image_elf32_read_section(struct image *image, int section, - uint32_t offset, + target_addr_t offset, uint32_t size, uint8_t *buffer, size_t *size_read) @@ -490,13 +661,13 @@ static int image_elf_read_section(struct image *image, *size_read = 0; - LOG_DEBUG("load segment %d at 0x%" PRIx32 " (sz = 0x%" PRIx32 ")", section, offset, size); + LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size); /* read initialized data in current segment if any */ if (offset < field32(elf, segment->p_filesz)) { /* maximal size present in file for the current segment */ read_size = MIN(size, field32(elf, segment->p_filesz) - offset); - LOG_DEBUG("read elf: size = 0x%zx at 0x%" PRIx32 "", read_size, + LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size, field32(elf, segment->p_offset) + offset); /* read initialized area of the segment */ retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset); @@ -519,6 +690,64 @@ static int image_elf_read_section(struct image *image, return ERROR_OK; } +static int image_elf64_read_section(struct image *image, + int section, + target_addr_t offset, + uint32_t size, + uint8_t *buffer, + size_t *size_read) +{ + struct image_elf *elf = image->type_private; + Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private; + size_t read_size, really_read; + int retval; + + *size_read = 0; + + LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size); + + /* read initialized data in current segment if any */ + if (offset < field64(elf, segment->p_filesz)) { + /* maximal size present in file for the current segment */ + read_size = MIN(size, field64(elf, segment->p_filesz) - offset); + LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size, + field64(elf, segment->p_offset) + offset); + /* read initialized area of the segment */ + retval = fileio_seek(elf->fileio, field64(elf, segment->p_offset) + offset); + if (retval != ERROR_OK) { + LOG_ERROR("cannot find ELF segment content, seek failed"); + return retval; + } + retval = fileio_read(elf->fileio, read_size, buffer, &really_read); + if (retval != ERROR_OK) { + LOG_ERROR("cannot read ELF segment content, read failed"); + return retval; + } + size -= read_size; + *size_read += read_size; + /* need more data ? */ + if (!size) + return ERROR_OK; + } + + return ERROR_OK; +} + +static int image_elf_read_section(struct image *image, + int section, + target_addr_t offset, + uint32_t size, + uint8_t *buffer, + size_t *size_read) +{ + struct image_elf *elf = image->type_private; + + if (elf->is_64_bit) + return image_elf64_read_section(image, section, offset, size, buffer, size_read); + else + return image_elf32_read_section(image, section, offset, size, buffer, size_read); +} + static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section) @@ -840,7 +1069,7 @@ int image_open(struct image *image, const char *url, const char *type_string) int image_read_section(struct image *image, int section, - uint32_t offset, + target_addr_t offset, uint32_t size, uint8_t *buffer, size_t *size_read) @@ -850,7 +1079,7 @@ int image_read_section(struct image *image, /* don't read past the end of a section */ if (offset + size > image->sections[section].size) { LOG_DEBUG( - "read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "", + "read past end of section: 0x%8.8" TARGET_PRIxADDR " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "", offset, size, image->sections[section].size); @@ -878,9 +1107,9 @@ int image_read_section(struct image *image, *size_read = size; return ERROR_OK; - } else if (image->type == IMAGE_ELF) + } else if (image->type == IMAGE_ELF) { return image_elf_read_section(image, section, offset, size, buffer, size_read); - else if (image->type == IMAGE_MEMORY) { + } else if (image->type == IMAGE_MEMORY) { struct image_memory *image_memory = image->type_private; uint32_t address = image->sections[section].base_address + offset; @@ -933,7 +1162,7 @@ int image_read_section(struct image *image, return ERROR_OK; } -int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t const *data) +int image_add_section(struct image *image, target_addr_t base, uint32_t size, int flags, uint8_t const *data) { struct imagesection *section; @@ -988,11 +1217,19 @@ void image_close(struct image *image) fileio_close(image_elf->fileio); - free(image_elf->header); - image_elf->header = NULL; + if (image_elf->is_64_bit) { + free(image_elf->header64); + image_elf->header64 = NULL; - free(image_elf->segments); - image_elf->segments = NULL; + free(image_elf->segments64); + image_elf->segments64 = NULL; + } else { + free(image_elf->header32); + image_elf->header32 = NULL; + + free(image_elf->segments32); + image_elf->segments32 = NULL; + } } else if (image->type == IMAGE_MEMORY) { struct image_memory *image_memory = image->type_private; diff --git a/src/target/image.h b/src/target/image.h index 53c27d812..c8d00d1d7 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -8,6 +8,9 @@ * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * + * Copyright (C) 2018 by Advantest * + * florian.meister@advantest.com * + * * * 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 * @@ -80,8 +83,15 @@ struct image_memory { struct image_elf { struct fileio *fileio; - Elf32_Ehdr *header; - Elf32_Phdr *segments; + bool is_64_bit; + union { + Elf32_Ehdr *header32; + Elf64_Ehdr *header64; + }; + union { + Elf32_Phdr *segments32; + Elf64_Phdr *segments64; + }; uint32_t segment_count; uint8_t endianness; }; @@ -92,11 +102,11 @@ struct image_mot { }; int image_open(struct image *image, const char *url, const char *type_string); -int image_read_section(struct image *image, int section, uint32_t offset, +int image_read_section(struct image *image, int section, target_addr_t offset, uint32_t size, uint8_t *buffer, size_t *size_read); void image_close(struct image *image); -int image_add_section(struct image *image, uint32_t base, uint32_t size, +int image_add_section(struct image *image, target_addr_t base, uint32_t size, int flags, uint8_t const *data); int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, From 565129119f0dc345a6e7d16bb468ff15cb3b828d Mon Sep 17 00:00:00 2001 From: Christian Hoff Date: Tue, 20 Apr 2021 19:14:30 +0200 Subject: [PATCH 43/58] target/image: report error if ELF file contains no loadable sections The existing code asserted in that case, which is not correct. This would allow the user to crash OpenOCD with a bad ELF file, which is not what we want. A proper error should be reported in that case and OpenOCD should not crash. Change-Id: Ied5a6a6fd4ee0fd163f3fe850d304a121ecbe33a Signed-off-by: Christian Hoff Reviewed-on: http://openocd.zylin.com/6172 Reviewed-by: Jonathan McDowell Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/target/image.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/target/image.c b/src/target/image.c index 9608375a5..8f72329bd 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -426,7 +426,10 @@ static int image_elf32_read_headers(struct image *image) (field32(elf, elf->segments32[i].p_filesz) != 0)) image->num_sections++; - assert(image->num_sections > 0); + if (image->num_sections == 0) { + LOG_ERROR("invalid ELF file, no loadable segments"); + return ERROR_IMAGE_FORMAT_ERROR; + } /** * some ELF linkers produce binaries with *all* the program header @@ -548,7 +551,10 @@ static int image_elf64_read_headers(struct image *image) (field64(elf, elf->segments64[i].p_filesz) != 0)) image->num_sections++; - assert(image->num_sections > 0); + if (image->num_sections == 0) { + LOG_ERROR("invalid ELF file, no loadable segments"); + return ERROR_IMAGE_FORMAT_ERROR; + } /** * some ELF linkers produce binaries with *all* the program header From ae86bd8e18047ab586e9ac4ca2eafd0bb008ae87 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 22 Apr 2021 12:06:04 +0200 Subject: [PATCH 44/58] helper/replacements: remove unused typedef's The ELF typedef's 'Elf32_Sword' and 'Elf32_Hashelt' are not used within OpenOCD. Plus, being their name in CamelCase require extra effort to include them in the exceptions for checkpatch. Remove the unused typedef's. Change-Id: I18f039567edd5b24dbb41df5406c154f31022ae7 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6178 Tested-by: jenkins Reviewed-by: Christian Hoff --- src/helper/replacements.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/helper/replacements.h b/src/helper/replacements.h index fff2dde0e..a0c59a79e 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -241,10 +241,8 @@ static inline int socket_select(int max_fd, typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Size; -typedef Elf32_Off Elf32_Hashelt; #define EI_NIDENT 16 From 3c73cca1e09c92b13c77b903fb39ef9386e07fd9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Apr 2021 15:47:28 +0200 Subject: [PATCH 45/58] helper/types: remove type '_Bool' Accordingly to OpenOCD coding style, both typedef and Camelcase symbols are forbidden. The type '_Bool' is not used in the code, having 'bool' as preferred choice. Remove the definition of '_Bool' from 'types.h'. Change-Id: I8863f9836ccd9166e0c69fa5d75d6fef79ae7bfb Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6186 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/types.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/helper/types.h b/src/helper/types.h index f3d5e04a3..010529ffc 100644 --- a/src/helper/types.h +++ b/src/helper/types.h @@ -47,16 +47,10 @@ #ifndef __cplusplus #define false 0 -#define true 1 +#define true 1 -typedef int _Bool; -#else -typedef bool _Bool; #endif /* __cplusplus */ #endif /* HAVE__BOOL */ - -#define bool _Bool - #endif /* HAVE_STDBOOL_H */ /// turns a macro argument into a string constant From f18a801e03e50274676544d10029c05e1f219246 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Apr 2021 20:07:35 +0200 Subject: [PATCH 46/58] helper/jim-nvp: remove unused function Jim_nvpInit() The files jim-nvp.[ch] were originally inside jimtcl, then in 2011 they were dropped by jimtcl and integrated in OpenOCD. The initial purpose was to make them as an independent library, thus the presence of an 'init' function. Being now part of OpenOCD do not require the 'init' function anymore, that is still empty and unused, plus its name is in violation of the coding style. Drop the function Jim_nvpInit(). Change-Id: I429e10444c86a26dbdc22aa071315324dc5edc3e Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6187 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/jim-nvp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index d13bdfba4..2caf18bce 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -333,9 +333,3 @@ const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *a return Jim_String(debug_string_obj); } - -int Jim_nvpInit(Jim_Interp *interp) -{ - /* This is really a helper library, not an extension, but this is the easy way */ - return JIM_OK; -} From 89c6b93ba278e26113aadcc3b7d357e05264beba Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Apr 2021 20:38:58 +0200 Subject: [PATCH 47/58] helper/command: fix memory leak on malloc() fail If malloc() fails, the just allocated Jim_Obj will leaks. Move Jim_IncrRefCount() before the malloc() and deallocate the Jim object with Jim_DecrRefCount() on malloc() fail. While there, add the 'out of memory' log and fix the CamelCase name of the symbol tclOutput. Change-Id: Ic733db229d5aa5d477d758ea9cb88cd81d7542cd Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6188 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/command.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index e703be400..08d14b47f 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -83,17 +83,21 @@ static struct log_capture_state *command_log_capture_start(Jim_Interp *interp) { /* capture log output and return it. A garbage collect can * happen, so we need a reference count to this object */ - Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); - if (NULL == tclOutput) + Jim_Obj *jim_output = Jim_NewStringObj(interp, "", 0); + if (!jim_output) return NULL; + Jim_IncrRefCount(jim_output); + struct log_capture_state *state = malloc(sizeof(*state)); - if (NULL == state) + if (!state) { + LOG_ERROR("Out of memory"); + Jim_DecrRefCount(interp, jim_output); return NULL; + } state->interp = interp; - Jim_IncrRefCount(tclOutput); - state->output = tclOutput; + state->output = jim_output; log_add_callback(tcl_output, state); From 4622a95fcc470d0c1a086ba046abe1f63b139750 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Apr 2021 20:44:27 +0200 Subject: [PATCH 48/58] helper/command: drop the TCL variable 'ocd_HOSTOS' Commit 7a731eb63731 ("Added HostOS variable"), merged in 2009, adds a TCL global variable 'ocd_HostOS' that reports in a string the OS of the host. This was proposed as a workaround for jimtcl that didn't define the standard TCL variable 'tcl_platform(os)'. With commit 42f3fb7b7f46 ("Determine platform_tcl() settings with configure"), merged in 2010 and part of jimtcl 0.70 issued in early 2011, jimtcl provides the requires TCL standard variable 'tcl_platform(os)'. The variable 'ocd_HostOS' has never been used by any TCL script distributed with OpenOCD. Drop the TCL variable 'ocd_HostOS'. Change-Id: I27858de35cc9d30df97145ca1ccd24877be4af11 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6189 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 28 ---------------------------- src/helper/command.c | 34 ---------------------------------- 2 files changed, 62 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index c39e7c168..d71731138 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11087,34 +11087,6 @@ OpenOCD commands can consist of two words, e.g. "flash banks". The @file{startup.tcl} "unknown" proc will translate this into a Tcl proc called "flash_banks". -@section OpenOCD specific Global Variables - -Real Tcl has ::tcl_platform(), and platform::identify, and many other -variables. JimTCL, as implemented in OpenOCD creates $ocd_HOSTOS which -holds one of the following values: - -@itemize @bullet -@item @b{cygwin} Running under Cygwin -@item @b{darwin} Darwin (Mac-OS) is the underlying operating system. -@item @b{freebsd} Running under FreeBSD -@item @b{openbsd} Running under OpenBSD -@item @b{netbsd} Running under NetBSD -@item @b{linux} Linux is the underlying operating system -@item @b{mingw32} Running under MingW32 -@item @b{winxx} Built using Microsoft Visual Studio -@item @b{ecos} Running under eCos -@item @b{other} Unknown, none of the above. -@end itemize - -Note: 'winxx' was chosen because today (March-2009) no distinction is made between Win32 and Win64. - -@quotation Note -We should add support for a variable like Tcl variable -@code{tcl_platform(platform)}, it should be called -@code{jim_platform} (because it -is jim, not real tcl). -@end quotation - @section Tcl RPC server @cindex RPC diff --git a/src/helper/command.c b/src/helper/command.c index 08d14b47f..0c6e785f2 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1277,7 +1277,6 @@ static const struct command_registration command_builtin_handlers[] = { struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp) { struct command_context *context = calloc(1, sizeof(struct command_context)); - const char *HostOs; context->mode = COMMAND_EXEC; @@ -1296,39 +1295,6 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp context->interp = interp; - /* Stick to lowercase for HostOS strings. */ -#if defined(_MSC_VER) - /* WinXX - is generic, the forward - * looking problem is this: - * - * "win32" or "win64" - * - * "winxx" is generic. - */ - HostOs = "winxx"; -#elif defined(__linux__) - HostOs = "linux"; -#elif defined(__APPLE__) || defined(__DARWIN__) - HostOs = "darwin"; -#elif defined(__CYGWIN__) - HostOs = "cygwin"; -#elif defined(__MINGW32__) - HostOs = "mingw32"; -#elif defined(__ECOS) - HostOs = "ecos"; -#elif defined(__FreeBSD__) - HostOs = "freebsd"; -#elif defined(__NetBSD__) - HostOs = "netbsd"; -#elif defined(__OpenBSD__) - HostOs = "openbsd"; -#else -#warning "Unrecognized host OS..." - HostOs = "other"; -#endif - Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS", - Jim_NewStringObj(interp, HostOs, strlen(HostOs))); - register_commands(context, NULL, command_builtin_handlers); Jim_SetAssocData(interp, "context", NULL, context); From 1e5782a09a149fe106fa2e574482108f730e4beb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Apr 2021 23:15:36 +0200 Subject: [PATCH 49/58] jtag: simplify the calls to Jim_SetResultFormatted() The documentation of Jim_SetResultFormatted() reports that the jim objects passed as arguments would be freed if have zero refcount. Remove the useless Jim_IncrRefCount()/Jim_DecrRefCount(). Remove the dangerous Jim_FreeNewObj() that should trigger a double free(). Not tested due to lack of aice adapter. While there, rename some CamelCase symbol. Change-Id: Ic56704c83d6391c38f6b0efa6566784d453bc0fb Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/6190 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/aice/aice_transport.c | 5 ++--- src/jtag/tcl.c | 12 ++++-------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c index ea710ad25..e3d431b2e 100644 --- a/src/jtag/aice/aice_transport.c +++ b/src/jtag/aice/aice_transport.c @@ -255,9 +255,8 @@ static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const e = aice_init_reset(context); if (e != ERROR_OK) { - Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); - Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); - Jim_FreeNewObj(goi.interp, eObj); + Jim_Obj *obj = Jim_NewIntObj(goi.interp, e); + Jim_SetResultFormatted(goi.interp, "error: %#s", obj); return JIM_ERR; } return JIM_OK; diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 3e7333515..8a52c0f18 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -687,10 +687,8 @@ static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct command_context *context = current_command_context(interp); int e = jtag_init_inner(context); if (e != ERROR_OK) { - Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); - Jim_IncrRefCount(eObj); - Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); - Jim_DecrRefCount(goi.interp, eObj); + Jim_Obj *obj = Jim_NewIntObj(goi.interp, e); + Jim_SetResultFormatted(goi.interp, "error: %#s", obj); return JIM_ERR; } return JIM_OK; @@ -712,10 +710,8 @@ static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const e = swd_init_reset(context); if (e != ERROR_OK) { - Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); - Jim_IncrRefCount(eObj); - Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); - Jim_DecrRefCount(goi.interp, eObj); + Jim_Obj *obj = Jim_NewIntObj(goi.interp, e); + Jim_SetResultFormatted(goi.interp, "error: %#s", obj); return JIM_ERR; } return JIM_OK; From ffdb2f3d1ac99dc5c7558fa1e0f1528a756ebda4 Mon Sep 17 00:00:00 2001 From: Jiri Kastner Date: Fri, 30 Apr 2021 07:43:36 +0200 Subject: [PATCH 50/58] udev rules: add OSBDM device Change-Id: I7221a6b3fe6fcd4f17ea664c10fd32c645e21d7c Signed-off-by: Jiri Kastner Reviewed-on: http://openocd.zylin.com/6198 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/60-openocd.rules | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index a3046be8f..1829f076c 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -154,6 +154,11 @@ ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev", # Debug Board for Neo1973 ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess" +# OSBDM +ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0042", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0058", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="005e", MODE="660", GROUP="plugdev", TAG+="uaccess" + # Olimex ARM-USB-OCD ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess" From d10141ef07644fc6a39211d60e811a868d91c575 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 11 Mar 2021 03:38:54 +0100 Subject: [PATCH 51/58] telnet: auto-completion of "registered" commands auto-completion behavior: - if there is only one matched command complete the user-command - else if multiple matches add the common part then in second step list all matched commands - sub-commands are handled in the same way - auto-completion restarts after these characters ';', '[', '{' Change-Id: I1b81dd19191a5785e68d0bb5cd244e01a4dd0587 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/6095 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/telnet_server.c | 248 +++++++++++++++++++++++++++++++++---- 1 file changed, 223 insertions(+), 25 deletions(-) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index e9de4f033..d5e0353c8 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -29,6 +29,7 @@ #include "telnet_server.h" #include #include +#include static char *telnet_port; @@ -58,6 +59,13 @@ static int telnet_write(struct connection *connection, const void *data, return ERROR_SERVER_REMOTE_CLOSED; } +/* output an audible bell */ +static int telnet_bell(struct connection *connection) +{ + /* ("\a" does not work, at least on windows) */ + return telnet_write(connection, "\x07", 1); +} + static int telnet_prompt(struct connection *connection) { struct telnet_connection *t_con = connection->priv; @@ -366,6 +374,217 @@ static void telnet_move_cursor(struct connection *connection, size_t pos) tc->line_cursor = pos; } +/* check buffer size leaving one spare character for string null termination */ +static inline bool telnet_can_insert(struct connection *connection, size_t len) +{ + struct telnet_connection *t_con = connection->priv; + + return t_con->line_size + len < TELNET_LINE_MAX_SIZE; +} + +/* write to telnet console, and update the telnet_connection members + * this function is capable of inserting in the middle of a line + * please ensure that data does not contain special characters (\n, \r, \t, \b ...) + * + * returns false when it fails to insert the requested data + */ +static bool telnet_insert(struct connection *connection, const void *data, size_t len) +{ + struct telnet_connection *t_con = connection->priv; + + if (!telnet_can_insert(connection, len)) { + telnet_bell(connection); + return false; + } + + if (t_con->line_cursor < t_con->line_size) { + /* we have some content after the cursor */ + memmove(t_con->line + t_con->line_cursor + len, + t_con->line + t_con->line_cursor, + t_con->line_size - t_con->line_cursor); + } + + strncpy(t_con->line + t_con->line_cursor, data, len); + + telnet_write(connection, + t_con->line + t_con->line_cursor, + t_con->line_size + len - t_con->line_cursor); + + t_con->line_size += len; + t_con->line_cursor += len; + + for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, "\b", 1); + + return true; +} + +static void telnet_auto_complete(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + struct command_context *command_context = connection->cmd_ctx; + + struct cmd_match { + char *cmd; + struct list_head lh; + }; + + LIST_HEAD(matches); + + /* user command sequence, either at line beginning + * or we start over after these characters ';', '[', '{' */ + size_t seq_start = (t_con->line_cursor == 0) ? 0 : (t_con->line_cursor - 1); + while (seq_start > 0) { + char c = t_con->line[seq_start]; + if (c == ';' || c == '[' || c == '{') { + seq_start++; + break; + } + + seq_start--; + } + + /* user command position in the line, ignore leading spaces */ + size_t usr_cmd_pos = seq_start; + while ((usr_cmd_pos < t_con->line_cursor) && isspace(t_con->line[usr_cmd_pos])) + usr_cmd_pos++; + + /* user command length */ + size_t usr_cmd_len = t_con->line_cursor - usr_cmd_pos; + + /* optimize multiple spaces in the user command, + * because info commands does not tolerate multiple spaces */ + size_t optimized_spaces = 0; + char query[usr_cmd_len + 1]; + for (size_t i = 0; i < usr_cmd_len; i++) { + if ((i < usr_cmd_len - 1) && isspace(t_con->line[usr_cmd_pos + i]) + && isspace(t_con->line[usr_cmd_pos + i + 1])) { + optimized_spaces++; + continue; + } + + query[i - optimized_spaces] = t_con->line[usr_cmd_pos + i]; + } + + usr_cmd_len -= optimized_spaces; + query[usr_cmd_len] = '\0'; + + /* filter commands */ + char *query_cmd = alloc_printf("lsort [info commands {%s*}]", query); + + if (!query_cmd) { + LOG_ERROR("Out of memory"); + return; + } + + int retval = Jim_EvalSource(command_context->interp, __FILE__, __LINE__, query_cmd); + free(query_cmd); + if (retval != JIM_OK) + return; + + Jim_Obj *list = Jim_GetResult(command_context->interp); + Jim_IncrRefCount(list); + + /* common prefix length of the matched commands */ + size_t common_len = 0; + char *first_match = NULL; /* used to compute the common prefix length */ + + int len = Jim_ListLength(command_context->interp, list); + for (int i = 0; i < len; i++) { + Jim_Obj *elem = Jim_ListGetIndex(command_context->interp, list, i); + Jim_IncrRefCount(elem); + + char *name = (char *)Jim_GetString(elem, NULL); + + /* validate the command */ + bool ignore_cmd = false; + Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE); + + if (!jim_cmd) + ignore_cmd = true; + else { + if (!jim_cmd->isproc) { + /* ignore commands without handler + * and those with COMMAND_CONFIG mode */ + /* FIXME it's better to use jimcmd_is_ocd_command(jim_cmd) + * or command_find_from_name(command_context->interp, name) */ + struct command *cmd = jim_cmd->u.native.privData; + if (!cmd) + ignore_cmd = true; + /* make Valgrind happy by checking that cmd is not NULL */ + else if (cmd != NULL && !cmd->handler && !cmd->jim_handler) + ignore_cmd = true; + else if (cmd != NULL && cmd->mode == COMMAND_CONFIG) + ignore_cmd = true; + } + } + + /* save the command in the prediction list */ + if (!ignore_cmd) { + struct cmd_match *match = calloc(1, sizeof(struct cmd_match)); + if (!match) { + LOG_ERROR("Out of memory"); + Jim_DecrRefCount(command_context->interp, elem); + break; /* break the for loop */ + } + + if (list_empty(&matches)) { + common_len = strlen(name); + first_match = name; + } else { + size_t new_common_len = usr_cmd_len; /* save some loops */ + + while (new_common_len < common_len && first_match[new_common_len] == name[new_common_len]) + new_common_len++; + + common_len = new_common_len; + } + + match->cmd = name; + list_add_tail(&match->lh, &matches); + } + + Jim_DecrRefCount(command_context->interp, elem); + } + /* end of command filtering */ + + /* proceed with auto-completion */ + if (list_empty(&matches)) + telnet_bell(connection); + else if (common_len == usr_cmd_len && list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) + telnet_insert(connection, " ", 1); + else if (common_len > usr_cmd_len) { + int completion_size = common_len - usr_cmd_len; + if (telnet_insert(connection, first_match + usr_cmd_len, completion_size)) { + /* in bash this extra space is only added when the cursor in at the end of line */ + if (list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) + telnet_insert(connection, " ", 1); + } + } else if (!list_is_singular(&matches)) { + telnet_write(connection, "\n\r", 2); + + struct cmd_match *match; + list_for_each_entry(match, &matches, lh) { + telnet_write(connection, match->cmd, strlen(match->cmd)); + telnet_write(connection, "\n\r", 2); + } + + telnet_prompt(connection); + telnet_write(connection, t_con->line, t_con->line_size); + + /* restore the terminal visible cursor location */ + for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, "\b", 1); + } + + /* destroy the command_list */ + struct cmd_match *tmp, *match; + list_for_each_entry_safe(match, tmp, &matches, lh) + free(match); + + Jim_DecrRefCount(command_context->interp, list); +} + static int telnet_input(struct connection *connection) { int bytes_read; @@ -391,30 +610,7 @@ static int telnet_input(struct connection *connection) t_con->state = TELNET_STATE_IAC; else { if (isprint(*buf_p)) { /* printable character */ - /* watch buffer size leaving one spare character for - * string null termination */ - if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) { - /* output audible bell if buffer is full - * "\a" does not work, at least on windows */ - telnet_write(connection, "\x07", 1); - } else if (t_con->line_cursor == t_con->line_size) { - telnet_write(connection, buf_p, 1); - t_con->line[t_con->line_size++] = *buf_p; - t_con->line_cursor++; - } else { - size_t i; - memmove(t_con->line + t_con->line_cursor + 1, - t_con->line + t_con->line_cursor, - t_con->line_size - t_con->line_cursor); - t_con->line[t_con->line_cursor] = *buf_p; - t_con->line_size++; - telnet_write(connection, - t_con->line + t_con->line_cursor, - t_con->line_size - t_con->line_cursor); - t_con->line_cursor++; - for (i = t_con->line_cursor; i < t_con->line_size; i++) - telnet_write(connection, "\b", 1); - } + telnet_insert(connection, buf_p, 1); } else { /* non-printable */ if (*buf_p == 0x1b) { /* escape */ t_con->state = TELNET_STATE_ESCAPE; @@ -548,7 +744,9 @@ static int telnet_input(struct connection *connection) t_con->line[t_con->line_cursor] = '\0'; t_con->line_size = t_con->line_cursor; } - } else + } else if (*buf_p == '\t') + telnet_auto_complete(connection); + else LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p); } } From b44948985f080df55adeb9377596432fff3c50d6 Mon Sep 17 00:00:00 2001 From: Luis de Arquer Date: Wed, 24 Mar 2021 17:12:14 +0100 Subject: [PATCH 52/58] drivers/ftdi: drscan: Skip DR-PAUSE when endstate == IDLE Currently, all drscan commands will cycle through DR-PAUSE before reaching TAP-IDLE. This patch provides a different path on FTDI driver. This change is required for the ST On Chip Emulator (OnCE), to avoid re-enabling the OnCE tap after every DRSCAN. This is because the OnCE TAP (see ST Application Note AN4035) gets disabled if DR-PAUSE is entered before DR-UPDATE. With this commit, the current path: DR-SHIFT -> DR-EXIT1 -> DR-PAUSE -> DR-EXIT2 -> DR-UPDATE -> IDLE is changed to: DR-SHIFT -> DR-EXIT1 -> DR-UPDATE -> IDLE only if IDLE is the endstate (which is the driver default). Before this patch, once the SHIFT sequence is complete, the driver would normally move to the nearest stable state, which is DR-PAUSE, by clocking out a '10' binary sequence. Then it would follow the path provided by tap_get_tms_path() to reach endstate. It is done this way because tap_get_tms_path() only supports stable states. After this patch, the strategy is mostly the same, with the exception that, if TAP_IDLE is the endstate, a '110' binary sequence is output after completing the SHIFT sequence. This takes the TAP directly to IDLE, with no further action required. A scheme of the DR chain is shown below. A * character is used to mark the stable states. ---------------------------------------------------------------------- | | 0 v 1 0 0 1 0 1 1 | IDLE* -> SEL-DR -> CAPTURE -> SHIFT* -> EXIT1 -> PAUSE* -> EXIT2 -> UPDATE | ^ 1 | | ----------------------------- Change-Id: Ib413e5c4c0bbf75dae0b4672119bae4ef03d0258 Signed-off-by: Luis de Arquer Reviewed-on: http://openocd.zylin.com/6123 Tested-by: jenkins Reviewed-by: Christopher Head Reviewed-by: Oleksij Rempel Reviewed-by: Andreas Fritiofson --- src/jtag/drivers/ftdi.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 9e47d3cad..8c83d459d 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -482,7 +482,11 @@ static void ftdi_execute_scan(struct jtag_command *cmd) uint8_t last_bit = 0; if (field->out_value) bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); - uint8_t tms_bits = 0x01; + + /* If endstate is TAP_IDLE, clock out 1-1-0 (->EXIT1 ->UPDATE ->IDLE) + * Otherwise, clock out 1-0 (->EXIT1 ->PAUSE) + */ + uint8_t tms_bits = 0x03; mpsse_clock_tms_cs(mpsse_ctx, &tms_bits, 0, @@ -492,13 +496,24 @@ static void ftdi_execute_scan(struct jtag_command *cmd) last_bit, ftdi_jtag_mode); tap_set_state(tap_state_transition(tap_get_state(), 1)); - mpsse_clock_tms_cs_out(mpsse_ctx, - &tms_bits, - 1, - 1, - last_bit, - ftdi_jtag_mode); - tap_set_state(tap_state_transition(tap_get_state(), 0)); + if (tap_get_end_state() == TAP_IDLE) { + mpsse_clock_tms_cs_out(mpsse_ctx, + &tms_bits, + 1, + 2, + last_bit, + ftdi_jtag_mode); + tap_set_state(tap_state_transition(tap_get_state(), 1)); + tap_set_state(tap_state_transition(tap_get_state(), 0)); + } else { + mpsse_clock_tms_cs_out(mpsse_ctx, + &tms_bits, + 2, + 1, + last_bit, + ftdi_jtag_mode); + tap_set_state(tap_state_transition(tap_get_state(), 0)); + } } else mpsse_clock_data(mpsse_ctx, field->out_value, From 87c90393fedc8bb278d189aa53bcd93f4892012b Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 19 Apr 2021 13:04:30 -0700 Subject: [PATCH 53/58] Cleanup of config/includes. Remove a use of AH_BOTTOM from configure.ac. This macro is used by autoheader to add '#include' of some include file to the end of config.h.in and then to config.h. OpenOCD can be built with a custom config.h, so it's preferable to move these '#include' statement directly in the C files that need them dropping this unneeded dependency. It also causes problems when I want to use the gnulib library (which comes with its own Makefile, and does not have the same include path as the top-level Makefile). So this change touches a lot of files, but is actually really simple. It does not affect functionality at all. Change-Id: I52c70bf15eb2edc1dd10e0fde23b2bcd4caec000 Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/6171 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 5 ----- src/flash/common.h | 1 + src/flash/nor/bluenrg-x.c | 1 + src/helper/binarybuffer.c | 1 + src/helper/bits.h | 1 + src/helper/configuration.c | 2 ++ src/helper/fileio.c | 1 + src/helper/fileio.h | 2 ++ src/helper/log.c | 1 + src/helper/options.c | 1 + src/helper/replacements.c | 1 + src/helper/replacements.h | 1 + src/helper/system.h | 18 +++++++++--------- src/helper/time_support.h | 1 + src/jtag/aice/aice_pipe.c | 2 ++ src/jtag/aice/aice_transport.c | 1 + src/jtag/aice/aice_usb.c | 1 + src/jtag/core.c | 1 + src/jtag/drivers/arm-jtag-ew.c | 1 + src/jtag/drivers/cmsis_dap.c | 1 + src/jtag/drivers/cmsis_dap_usb_bulk.c | 2 ++ src/jtag/drivers/cmsis_dap_usb_hid.c | 1 + src/jtag/drivers/ftdi.c | 1 + src/jtag/drivers/jlink.c | 1 + src/jtag/drivers/jtag_usb_common.c | 1 + src/jtag/drivers/jtag_usb_common.h | 3 +++ src/jtag/drivers/jtag_vpi.c | 2 +- src/jtag/drivers/mpsse.c | 1 + src/jtag/drivers/remote_bitbang.c | 2 ++ src/jtag/drivers/rlink.c | 1 + src/jtag/drivers/rlink.h | 1 + src/jtag/drivers/stlink_usb.c | 1 + src/jtag/drivers/ulink.c | 1 + .../usb_blaster/ublast2_access_libusb.c | 1 + src/jtag/drivers/usb_blaster/usb_blaster.c | 1 + src/jtag/drivers/versaloon/versaloon.c | 3 ++- src/jtag/drivers/versaloon/versaloon_include.h | 1 + src/jtag/jtag.h | 1 + src/main.c | 1 + src/pld/pld.c | 1 + src/pld/xilinx_bit.c | 2 +- src/pld/xilinx_bit.h | 2 ++ src/server/server.c | 1 + src/server/server.h | 1 + src/svf/svf.c | 1 + src/target/algorithm.h | 3 +++ src/target/armv4_5_cache.h | 2 ++ src/target/breakpoints.h | 2 ++ src/target/image.h | 1 + src/target/nds32_edm.h | 2 ++ src/target/register.h | 3 +++ src/target/semihosting_common.h | 1 + src/target/target.h | 2 ++ src/target/trace.h | 2 ++ src/transport/transport.c | 1 + src/xsvf/xsvf.c | 1 + 56 files changed, 81 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 979bb161b..58be79039 100644 --- a/configure.ac +++ b/configure.ac @@ -17,11 +17,6 @@ AC_SUBST([MAKEINFO]) AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip subdir-objects]) AC_CONFIG_HEADERS([config.h]) -AH_BOTTOM([ -#include -#include -#include -]) AC_LANG([C]) AC_PROG_CC diff --git a/src/flash/common.h b/src/flash/common.h index 4244f1360..69f60d9a3 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -19,6 +19,7 @@ #define OPENOCD_FLASH_COMMON_H #include +#include /** * Parses the optional '.index' portion of a flash bank identifier. diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index 57aebc597..cf968cb8c 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include "helper/types.h" #include #include #include diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 44d139f58..3d35702ac 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -23,6 +23,7 @@ #include "config.h" #endif +#include "helper/replacements.h" #include "log.h" #include "binarybuffer.h" diff --git a/src/helper/bits.h b/src/helper/bits.h index cdcac9eaf..00d3c0270 100644 --- a/src/helper/bits.h +++ b/src/helper/bits.h @@ -24,6 +24,7 @@ #ifndef OPENOCD_HELPER_BITS_H #define OPENOCD_HELPER_BITS_H +#include #include #define BIT(nr) (1UL << (nr)) diff --git a/src/helper/configuration.c b/src/helper/configuration.c index 114ad2c6c..8f4f11833 100644 --- a/src/helper/configuration.c +++ b/src/helper/configuration.c @@ -18,12 +18,14 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "configuration.h" #include "log.h" +#include "replacements.h" static size_t num_config_files; static char **config_file_names; diff --git a/src/helper/fileio.c b/src/helper/fileio.c index 9dd57e72a..b6f1f4e2c 100644 --- a/src/helper/fileio.c +++ b/src/helper/fileio.c @@ -29,6 +29,7 @@ #include "log.h" #include "configuration.h" #include "fileio.h" +#include "replacements.h" struct fileio { char *url; diff --git a/src/helper/fileio.h b/src/helper/fileio.h index 02592e28d..16c104657 100644 --- a/src/helper/fileio.h +++ b/src/helper/fileio.h @@ -25,6 +25,8 @@ #ifndef OPENOCD_HELPER_FILEIO_H #define OPENOCD_HELPER_FILEIO_H +#include "types.h" + #define FILEIO_MAX_ERROR_STRING (128) enum fileio_type { diff --git a/src/helper/log.c b/src/helper/log.c index 7440b70f6..f5a80623f 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -28,6 +28,7 @@ #include "log.h" #include "command.h" +#include "replacements.h" #include "time_support.h" #include diff --git a/src/helper/options.c b/src/helper/options.c index 477d7b303..f996749ea 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -31,6 +31,7 @@ #include #include +#include #if IS_DARWIN #include #endif diff --git a/src/helper/replacements.c b/src/helper/replacements.c index b4bb94f06..f4ecb8dfc 100644 --- a/src/helper/replacements.c +++ b/src/helper/replacements.c @@ -62,6 +62,7 @@ void *fill_malloc(size_t size) #ifdef _WIN32 #include +#include #endif /* replacements for gettimeofday */ diff --git a/src/helper/replacements.h b/src/helper/replacements.h index a0c59a79e..5aecf4182 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -26,6 +26,7 @@ #define OPENOCD_HELPER_REPLACEMENTS_H #include +#include /* MIN,MAX macros */ #ifndef MIN diff --git a/src/helper/system.h b/src/helper/system.h index 1aaca3b33..0d8be648c 100644 --- a/src/helper/system.h +++ b/src/helper/system.h @@ -21,6 +21,15 @@ #ifndef OPENOCD_HELPER_SYSTEM_H #define OPENOCD_HELPER_SYSTEM_H +/* +++ platform specific headers +++ */ +#ifdef _WIN32 +#include +#include +#include +#include +#endif +/* --- platform specific headers --- */ + /* standard C library header files */ #include #include @@ -34,15 +43,6 @@ #include #endif -/* +++ platform specific headers +++ */ -#ifdef _WIN32 -#include -#include -#include -#include -#endif -/* --- platform specific headers --- */ - #ifdef HAVE_SYS_SOCKET_H #include #endif diff --git a/src/helper/time_support.h b/src/helper/time_support.h index a9f2dffad..3c7d4255b 100644 --- a/src/helper/time_support.h +++ b/src/helper/time_support.h @@ -26,6 +26,7 @@ #define OPENOCD_HELPER_TIME_SUPPORT_H #include +#include "types.h" #ifdef HAVE_SYS_TIME_H #include diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c index c0e532c9d..5a8cbab78 100644 --- a/src/jtag/aice/aice_pipe.c +++ b/src/jtag/aice/aice_pipe.c @@ -19,6 +19,8 @@ #include "config.h" #endif +#include + #ifdef _WIN32 #include #else diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c index e3d431b2e..c02a42f3b 100644 --- a/src/jtag/aice/aice_transport.c +++ b/src/jtag/aice/aice_transport.c @@ -27,6 +27,7 @@ #include #include #include +#include /* */ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 0c219805f..6c452a327 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -19,6 +19,7 @@ #include "config.h" #endif +#include #include #include #include diff --git a/src/jtag/core.c b/src/jtag/core.c index 6604c5ae8..37924aad0 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -35,6 +35,7 @@ #include "interface.h" #include #include +#include "helper/system.h" #ifdef HAVE_STRINGS_H #include diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index d7afbe24d..62d863191 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -22,6 +22,7 @@ #include #include +#include "helper/system.h" #include "libusb_helper.h" #define USB_VID 0x15ba diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index fb5c86aec..26e576b8e 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -36,6 +36,7 @@ #endif #include +#include "helper/replacements.h" #include #include #include diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index f535119f3..a588b1bd8 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -35,8 +35,10 @@ #include "config.h" #endif +#include #include #include +#include #include "cmsis_dap.h" diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index e83ad1feb..38069f840 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -35,6 +35,7 @@ #include "config.h" #endif +#include #include #include diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 8c83d459d..e13977fb0 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -74,6 +74,7 @@ #include #include #include +#include #if IS_CYGWIN == 1 #include diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 15d252cfb..8c1a8116d 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/jtag/drivers/jtag_usb_common.c b/src/jtag/drivers/jtag_usb_common.c index 309f8c462..fdd713783 100644 --- a/src/jtag/drivers/jtag_usb_common.c +++ b/src/jtag/drivers/jtag_usb_common.c @@ -4,6 +4,7 @@ */ #include +#include #include "jtag_usb_common.h" diff --git a/src/jtag/drivers/jtag_usb_common.h b/src/jtag/drivers/jtag_usb_common.h index 8c03742e9..c4c28cc91 100644 --- a/src/jtag/drivers/jtag_usb_common.h +++ b/src/jtag/drivers/jtag_usb_common.h @@ -6,6 +6,9 @@ #ifndef OPENOCD_JTAG_USB_COMMON_H #define OPENOCD_JTAG_USB_COMMON_H +#include +#include + void jtag_usb_set_location(const char *location); const char *jtag_usb_get_location(void); bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index c5ffe83ba..aeed6a56c 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -33,7 +33,7 @@ #include #endif -#include +#include "helper/replacements.h" #define NO_TAP_SHIFT 0 #define TAP_SHIFT 1 diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 7cda3b816..9ba1e2502 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -22,6 +22,7 @@ #include "mpsse.h" #include "helper/log.h" +#include "helper/replacements.h" #include "helper/time_support.h" #include diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 114e018b7..f7b88303b 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -24,6 +24,8 @@ #include #include #endif +#include "helper/system.h" +#include "helper/replacements.h" #include #include "bitbang.h" diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index ad629ca68..a88731f4a 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -29,6 +29,7 @@ /* project specific includes */ #include #include +#include "helper/replacements.h" #include "rlink.h" #include "rlink_st7.h" #include "rlink_ep1_cmd.h" diff --git a/src/jtag/drivers/rlink.h b/src/jtag/drivers/rlink.h index 74b62580c..0c15a3223 100644 --- a/src/jtag/drivers/rlink.h +++ b/src/jtag/drivers/rlink.h @@ -19,6 +19,7 @@ #ifndef OPENOCD_JTAG_DRIVERS_RLINK_H #define OPENOCD_JTAG_DRIVERS_RLINK_H +#include "helper/types.h" struct rlink_speed_table { uint8_t const *dtc; uint16_t dtc_size; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a088a83ee..60a2c319f 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -35,6 +35,7 @@ /* project specific includes */ #include #include +#include #include #include #include diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 096e254fa..fe95e7d18 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -21,6 +21,7 @@ #endif #include +#include "helper/system.h" #include #include #include diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index 4dec89b11..d55bf85cd 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -23,6 +23,7 @@ #endif #include #include +#include "helper/system.h" #include #include diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 5002a5f53..c312468b4 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -77,6 +77,7 @@ #include #include #include +#include #include "ublast_access.h" /* system includes */ diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c index 194a3751c..6fea888ab 100644 --- a/src/jtag/drivers/versaloon/versaloon.c +++ b/src/jtag/drivers/versaloon/versaloon.c @@ -19,11 +19,12 @@ #include "config.h" #endif +#include "versaloon_include.h" + #include #include #include -#include "versaloon_include.h" #include "versaloon.h" #include "versaloon_internal.h" #include "usbtoxxx/usbtoxxx.h" diff --git a/src/jtag/drivers/versaloon/versaloon_include.h b/src/jtag/drivers/versaloon/versaloon_include.h index 901402520..4ca81d5e2 100644 --- a/src/jtag/drivers/versaloon/versaloon_include.h +++ b/src/jtag/drivers/versaloon/versaloon_include.h @@ -18,6 +18,7 @@ #ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H #define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H +#include "helper/system.h" /* This file is used to include different header and macros */ /* according to different platform */ #include diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 86091e6a7..feb4614fa 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -24,6 +24,7 @@ #include #include +#include #ifndef DEBUG_JTAG_IOZ #define DEBUG_JTAG_IOZ 64 diff --git a/src/main.c b/src/main.c index 83e60d8e0..a437b6b4c 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include "config.h" #endif #include "openocd.h" +#include "helper/system.h" /* This is the main entry for developer PC hosted OpenOCD. * diff --git a/src/pld/pld.c b/src/pld/pld.c index 9e8c07d80..66f5d44bc 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -22,6 +22,7 @@ #include "pld.h" #include +#include #include diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c index f83d8942d..a530ee776 100644 --- a/src/pld/xilinx_bit.c +++ b/src/pld/xilinx_bit.c @@ -25,7 +25,7 @@ #include #include - +#include static int read_section(FILE *input_file, int length_size, char section, uint32_t *buffer_length, uint8_t **buffer) diff --git a/src/pld/xilinx_bit.h b/src/pld/xilinx_bit.h index 1a35c3be2..625a9d35e 100644 --- a/src/pld/xilinx_bit.h +++ b/src/pld/xilinx_bit.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_PLD_XILINX_BIT_H #define OPENOCD_PLD_XILINX_BIT_H +#include "helper/types.h" + struct xilinx_bit_file { uint8_t unknown_header[13]; uint8_t *source_file; diff --git a/src/server/server.c b/src/server/server.c index e53f37d0b..307266389 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -33,6 +33,7 @@ #include "openocd.h" #include "tcl_server.h" #include "telnet_server.h" +#include "time_support.h" #include diff --git a/src/server/server.h b/src/server/server.h index ff2ada9cb..de18d2b4b 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -30,6 +30,7 @@ #endif #include +#include #ifdef HAVE_NETINET_IN_H #include diff --git a/src/svf/svf.c b/src/svf/svf.c index 608703434..f35c61314 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -31,6 +31,7 @@ #include #include "svf.h" +#include "helper/system.h" #include /* SVF command */ diff --git a/src/target/algorithm.h b/src/target/algorithm.h index 8894241c0..0fc49d069 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -19,6 +19,9 @@ #ifndef OPENOCD_TARGET_ALGORITHM_H #define OPENOCD_TARGET_ALGORITHM_H +#include "helper/types.h" +#include "helper/replacements.h" + enum param_direction { PARAM_IN, PARAM_OUT, diff --git a/src/target/armv4_5_cache.h b/src/target/armv4_5_cache.h index 768938fd1..985a3a770 100644 --- a/src/target/armv4_5_cache.h +++ b/src/target/armv4_5_cache.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_ARMV4_5_CACHE_H #define OPENOCD_TARGET_ARMV4_5_CACHE_H +#include "helper/types.h" + struct command_invocation; struct armv4_5_cachesize { diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 20faf4e6c..8c247f7a9 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -21,6 +21,8 @@ #include +#include "helper/types.h" + struct target; enum breakpoint_type { diff --git a/src/target/image.h b/src/target/image.h index c8d00d1d7..5b5d11f6b 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -29,6 +29,7 @@ #define OPENOCD_TARGET_IMAGE_H #include +#include #ifdef HAVE_ELF_H #include diff --git a/src/target/nds32_edm.h b/src/target/nds32_edm.h index 1dec190f1..2b5067a34 100644 --- a/src/target/nds32_edm.h +++ b/src/target/nds32_edm.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_NDS32_EDM_H #define OPENOCD_TARGET_NDS32_EDM_H +#include "helper/types.h" + /** * @file * This is the interface to the Embedded Debug Module for Andes cores. diff --git a/src/target/register.h b/src/target/register.h index 5f1c25fb4..a7705f76e 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -22,6 +22,9 @@ #ifndef OPENOCD_TARGET_REGISTER_H #define OPENOCD_TARGET_REGISTER_H +#include "helper/replacements.h" +#include "helper/types.h" + struct target; enum reg_type { diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index 8fb5e0c3a..b83464ed5 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -25,6 +25,7 @@ #include #include #include +#include "helper/replacements.h" /* * According to: diff --git a/src/target/target.h b/src/target/target.h index b9ae2f78e..046bd99ae 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -32,6 +32,8 @@ #define OPENOCD_TARGET_TARGET_H #include +#include "helper/replacements.h" +#include "helper/system.h" #include struct reg; diff --git a/src/target/trace.h b/src/target/trace.h index 2966bbd94..45308c0d8 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_TRACE_H #define OPENOCD_TARGET_TRACE_H +#include "helper/types.h" + struct target; struct command_context; diff --git a/src/transport/transport.c b/src/transport/transport.c index cb000ab11..ba1f9e9f7 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -42,6 +42,7 @@ */ #include +#include #include extern struct command_context *global_cmd_ctx; diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index eaa5a3aae..2a7b56dbf 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -39,6 +39,7 @@ #endif #include "xsvf.h" +#include "helper/system.h" #include #include From 64a3e7ba4f47c5340543d9a5cadd41bc45d93c93 Mon Sep 17 00:00:00 2001 From: asier70 Date: Mon, 12 Apr 2021 14:09:36 +0200 Subject: [PATCH 54/58] flash/nor/stm32f1x: Add support for GD32F1x0/3x0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nowadays, when it's difficult to buy STM32F030, the use of GD32F130 seems to be an interesting functional alternative. This is cortex-M3 and it works with the stm32f1x driver, but unfortunately not fully. The main difference is another offset of user option bits (like WDG_SW, nRST_STOP, nRST_STDBY) in option byte register (FLASH_OBR/FMC_OBSTAT 0x4002201C). Any use of functions like lock or unlock results in change default values of the those bits stored in flash. Thus broken microcontroller is malfunctioning, e.g. flash block programming is interrupted by unexpected active hardware watchog (after 0.4s). This patch is a simplified version of #4592 done by Dominik Peklo (http://openocd.zylin.com/#/c/4592/). GigaDevice GD32F1x0 & GD32F3x0 series devices share DEV_ID with STM32F101/2/3 medium-density line, however they use a REV_ID different from any STM32 device, so can be succesfully detected. Change-Id: I252cdf738d94983b70676a3497326f90c329e292 Signed-off-by: asier70Andrzej Sierżęga Reviewed-on: http://openocd.zylin.com/6164 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 3 ++- src/flash/nor/stm32f1x.c | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index d71731138..a05f85d5e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6927,7 +6927,8 @@ applied to all of them. @deffn {Flash Driver} {stm32f1x} All members of the STM32F0, STM32F1 and STM32F3 microcontroller families -from STMicroelectronics include internal flash and use ARM Cortex-M0/M3/M4 cores. +from STMicroelectronics and all members of the GD32F1x0 and GD32F3x0 microcontroller +families from GigaDevice include internal flash and use ARM Cortex-M0/M3/M4 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 9cd282d65..125f77691 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -692,7 +692,7 @@ static int stm32x_probe(struct flash_bank *bank) struct stm32x_flash_bank *stm32x_info = bank->driver_priv; uint16_t flash_size_in_kb; uint16_t max_flash_size_in_kb; - uint32_t device_id; + uint32_t dbgmcu_idcode; int page_size; uint32_t base_address = 0x08000000; @@ -705,14 +705,17 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->default_rdp = 0xA5; /* read stm32 device id register */ - int retval = stm32x_get_device_id(bank, &device_id); + int retval = stm32x_get_device_id(bank, &dbgmcu_idcode); if (retval != ERROR_OK) return retval; - LOG_INFO("device id = 0x%08" PRIx32 "", device_id); + LOG_INFO("device id = 0x%08" PRIx32 "", dbgmcu_idcode); + + uint16_t device_id = dbgmcu_idcode & 0xfff; + uint16_t rev_id = dbgmcu_idcode >> 16; /* set page size, protection granularity and max flash size depending on family */ - switch (device_id & 0xfff) { + switch (device_id) { case 0x440: /* stm32f05x */ page_size = 1024; stm32x_info->ppage_size = 4; @@ -754,6 +757,25 @@ static int stm32x_probe(struct flash_bank *bank) page_size = 1024; stm32x_info->ppage_size = 4; max_flash_size_in_kb = 128; + /* GigaDevice GD32F1x0 & GD32F3x0 series devices share DEV_ID + with STM32F101/2/3 medium-density line, + however they use a REV_ID different from any STM32 device. + The main difference is another offset of user option bits + (like WDG_SW, nRST_STOP, nRST_STDBY) in option byte register + (FLASH_OBR/FMC_OBSTAT 0x4002201C). + This caused problems e.g. during flash block programming + because of unexpected active hardware watchog. */ + switch (rev_id) { + case 0x1303: /* gd32f1x0 */ + stm32x_info->user_data_offset = 16; + stm32x_info->option_offset = 6; + max_flash_size_in_kb = 64; + break; + case 0x1704: /* gd32f3x0 */ + stm32x_info->user_data_offset = 16; + stm32x_info->option_offset = 6; + break; + } break; case 0x412: /* stm32f1x low-density */ page_size = 1024; @@ -955,6 +977,14 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) rev_str = "A"; break; + case 0x1303: /* gd32f1x0 */ + device_str = "GD32F1x0"; + break; + + case 0x1704: /* gd32f3x0 */ + device_str = "GD32F3x0"; + break; + case 0x2000: rev_str = "B"; break; From b60d06ae325c00979e9ff17bb35e868879e6047f Mon Sep 17 00:00:00 2001 From: Peter Lawrence Date: Tue, 2 Mar 2021 15:21:28 -0600 Subject: [PATCH 55/58] tcl/board: add pico-debug support pico-debug is not a board; it is a virtual CMSIS-DAP adapter that runs on the same RP2040 also being debugged. This is possible due to pico-debug running on the normally-dormant second Cortex-M0+ core (Core1), providing debugging of the first core (Core0). As such, it could be used on a variety of RP2040-based boards. Since a flash driver is useful (if not essential), a flash driver is included. This driver code originated on RPi's bespoke OpenOCD fork; lipstick was added to this particular pig to make it more presentable on OpenOCD proper. no new Clang analyzer warnings Change-Id: I31f98b5ea1664f0adfbc184b57efba963acfb958 Signed-off-by: Peter Lawrence Reviewed-on: http://openocd.zylin.com/6075 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 11 + src/flash/nor/Makefile.am | 1 + src/flash/nor/drivers.c | 2 + src/flash/nor/rp2040.c | 453 ++++++++++++++++++++++++++++++++++++ tcl/board/pico-debug.cfg | 11 + tcl/target/rp2040-core0.cfg | 38 +++ 6 files changed, 516 insertions(+) create mode 100644 src/flash/nor/rp2040.c create mode 100644 tcl/board/pico-debug.cfg create mode 100644 tcl/target/rp2040-core0.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index a05f85d5e..a8a413c4f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6876,6 +6876,17 @@ Note: only Main and Work flash regions support Erase operation. @end deffn @end deffn +@deffn {Flash Driver} {rp2040} +Supports RP2040 "Raspberry Pi Pico" microcontroller. +RP2040 is a dual-core device with two CM0+ cores. Both cores share the same +Flash/RAM/MMIO address space. Non-volatile storage is achieved with an +external QSPI flash; a Boot ROM provides helper functions. + +@example +flash bank $_FLASHNAME rp2040_flash $_FLASHBASE $_FLASHSIZE 1 32 $_TARGETNAME +@end example +@end deffn + @deffn {Flash Driver} {sim3x} All members of the SiM3 microcontroller family from Silicon Laboratories include internal flash and use ARM Cortex-M3 cores. It supports both JTAG diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 8c9b2b7ab..532670436 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -52,6 +52,7 @@ NOR_DRIVERS = \ %D%/psoc5lp.c \ %D%/psoc6.c \ %D%/renesas_rpchf.c \ + %D%/rp2040.c \ %D%/sfdp.c \ %D%/sh_qspi.c \ %D%/sim3x.c \ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 570861ec5..6eadc756b 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -67,6 +67,7 @@ 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 renesas_rpchf_flash; +extern const struct flash_driver rp2040_flash; extern const struct flash_driver sh_qspi_flash; extern const struct flash_driver sim3x_flash; extern const struct flash_driver stellaris_flash; @@ -140,6 +141,7 @@ static const struct flash_driver * const flash_drivers[] = { &psoc5lp_nvl_flash, &psoc6_flash, &renesas_rpchf_flash, + &rp2040_flash, &sh_qspi_flash, &sim3x_flash, &stellaris_flash, diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c new file mode 100644 index 000000000..5b4c16bb9 --- /dev/null +++ b/src/flash/nor/rp2040.c @@ -0,0 +1,453 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include +#include +#include +#include "spi.h" + +/* NOTE THAT THIS CODE REQUIRES FLASH ROUTINES in BOOTROM WITH FUNCTION TABLE PTR AT 0x00000010 + Your gdbinit should load the bootrom.elf if appropriate */ + +/* this is 'M' 'u', 1 (version) */ +#define BOOTROM_MAGIC 0x01754d +#define BOOTROM_MAGIC_ADDR 0x00000010 + +/* Call a ROM function via the debug trampoline + Up to four arguments passed in r0...r3 as per ABI + Function address is passed in r7 + the trampoline is needed because OpenOCD "algorithm" code insists on sw breakpoints. */ + +#define MAKE_TAG(a, b) (((b)<<8) | a) +#define FUNC_DEBUG_TRAMPOLINE MAKE_TAG('D', 'T') +#define FUNC_DEBUG_TRAMPOLINE_END MAKE_TAG('D', 'E') +#define FUNC_FLASH_EXIT_XIP MAKE_TAG('E', 'X') +#define FUNC_CONNECT_INTERNAL_FLASH MAKE_TAG('I', 'F') +#define FUNC_FLASH_RANGE_ERASE MAKE_TAG('R', 'E') +#define FUNC_FLASH_RANGE_PROGRAM MAKE_TAG('R', 'P') +#define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C') +#define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X') + +struct rp2040_flash_bank { + /* flag indicating successful flash probe */ + bool probed; + /* stack used by Boot ROM calls */ + struct working_area *stack; + /* function jump table populated by rp2040_flash_probe() */ + uint16_t jump_debug_trampoline; + uint16_t jump_debug_trampoline_end; + uint16_t jump_flash_exit_xip; + uint16_t jump_connect_internal_flash; + uint16_t jump_flash_range_erase; + uint16_t jump_flash_range_program; + uint16_t jump_flush_cache; + uint16_t jump_enter_cmd_xip; + /* detected model of SPI flash */ + const struct flash_device *dev; +}; + +static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol) +{ + uint32_t magic; + int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic); + if (err != ERROR_OK) + return err; + + magic &= 0xffffff; /* ignore bootrom version */ + if (magic != BOOTROM_MAGIC) { + if (!((magic ^ BOOTROM_MAGIC)&0xffff)) + LOG_ERROR("Incorrect RP2040 BOOT ROM version"); + else + LOG_ERROR("RP2040 BOOT ROM not found"); + return ERROR_FAIL; + } + + /* dereference the table pointer */ + uint16_t table_entry; + err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_entry); + if (err != ERROR_OK) + return err; + + uint16_t entry_tag; + do { + err = target_read_u16(target, table_entry, &entry_tag); + if (err != ERROR_OK) + return err; + if (entry_tag == tag) { + /* 16 bit symbol is next */ + return target_read_u16(target, table_entry + 2, symbol); + } + table_entry += 4; + } while (entry_tag); + return ERROR_FAIL; +} + +static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv, + uint16_t func_offset, uint32_t argdata[], unsigned int n_args) +{ + char *regnames[4] = { "r0", "r1", "r2", "r3" }; + + assert(n_args <= ARRAY_SIZE(regnames)); /* only allow register arguments */ + + if (!priv->stack) { + LOG_ERROR("no stack for flash programming code"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + target_addr_t stacktop = priv->stack->address + priv->stack->size; + + LOG_DEBUG("Calling ROM func @0x%" PRIx16 " with %d arguments", func_offset, n_args); + LOG_DEBUG("Calling on core \"%s\"", target->cmd_name); + + struct reg_param args[ARRAY_SIZE(regnames) + 2]; + struct armv7m_algorithm alg_info; + + for (unsigned int i = 0; i < n_args; ++i) { + init_reg_param(&args[i], regnames[i], 32, PARAM_OUT); + buf_set_u32(args[i].value, 0, 32, argdata[i]); + } + /* Pass function pointer in r7 */ + init_reg_param(&args[n_args], "r7", 32, PARAM_OUT); + buf_set_u32(args[n_args].value, 0, 32, func_offset); + init_reg_param(&args[n_args + 1], "sp", 32, PARAM_OUT); + buf_set_u32(args[n_args + 1].value, 0, 32, stacktop); + + + for (unsigned int i = 0; i < n_args + 2; ++i) + LOG_DEBUG("Set %s = 0x%" PRIx32, args[i].reg_name, buf_get_u32(args[i].value, 0, 32)); + + /* Actually call the function */ + alg_info.common_magic = ARMV7M_COMMON_MAGIC; + alg_info.core_mode = ARM_MODE_THREAD; + int err = target_run_algorithm( + target, + 0, NULL, /* No memory arguments */ + n_args + 1, args, /* User arguments + r7 */ + priv->jump_debug_trampoline, priv->jump_debug_trampoline_end, + 3000, /* 3s timeout */ + &alg_info + ); + for (unsigned int i = 0; i < n_args + 2; ++i) + destroy_reg_param(&args[i]); + if (err != ERROR_OK) + LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16 "\n", func_offset); + return err; + +} + +static int stack_grab_and_prep(struct flash_bank *bank) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + + /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */ + const int STACK_SIZE = 256; + int err = target_alloc_working_area(bank->target, STACK_SIZE, &priv->stack); + if (err != ERROR_OK) { + LOG_ERROR("Could not allocate stack for flash programming code"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + LOG_DEBUG("Connecting internal flash"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0); + if (err != ERROR_OK) { + LOG_ERROR("RP2040 erase: failed to connect internal flash"); + return err; + } + + LOG_DEBUG("Kicking flash out of XIP mode"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_exit_xip, NULL, 0); + if (err != ERROR_OK) { + LOG_ERROR("RP2040 erase: failed to exit flash XIP mode"); + return err; + } + + return ERROR_OK; +} + +static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) +{ + LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset); + + struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; + struct working_area *bounce; + + int err = stack_grab_and_prep(bank); + if (err != ERROR_OK) + return err; + + const unsigned int chunk_size = target_get_working_area_avail(target); + if (target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) { + LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address); + + while (count > 0) { + uint32_t write_size = count > chunk_size ? chunk_size : count; + LOG_DEBUG("Writing %d bytes to offset 0x%" PRIx32, write_size, offset); + err = target_write_buffer(target, bounce->address, write_size, buffer); + if (err != ERROR_OK) { + LOG_ERROR("Could not load data into target bounce buffer"); + break; + } + uint32_t args[3] = { + offset, /* addr */ + bounce->address, /* data */ + write_size /* count */ + }; + err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); + if (err != ERROR_OK) { + LOG_ERROR("Failed to invoke flash programming code on target"); + break; + } + + buffer += write_size; + offset += write_size; + count -= write_size; + } + target_free_working_area(target, bounce); + + if (err != ERROR_OK) + return err; + + /* Flash is successfully programmed. We can now do a bit of poking to make the flash + contents visible to us via memory-mapped (XIP) interface in the 0x1... memory region */ + LOG_DEBUG("Flushing flash cache after write behind"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0); + if (err != ERROR_OK) { + LOG_ERROR("RP2040 write: failed to flush flash cache"); + return err; + } + LOG_DEBUG("Configuring SSI for execute-in-place"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_enter_cmd_xip, NULL, 0); + if (err != ERROR_OK) + LOG_ERROR("RP2040 write: failed to flush flash cache"); + return err; +} + +static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + uint32_t start_addr = bank->sectors[first].offset; + uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; + LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr); + + int err = stack_grab_and_prep(bank); + if (err != ERROR_OK) + return err; + + LOG_DEBUG("Remote call flash_range_erase"); + + uint32_t args[4] = { + bank->sectors[first].offset, /* addr */ + bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */ + priv->dev->sectorsize, /* block_size */ + priv->dev->erase_cmd /* block_cmd */ + }; + + /* + The RP2040 Boot ROM provides a _flash_range_erase() API call documented in Section 2.8.3.1.3: + https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf + and the particular source code for said Boot ROM function can be found here: + https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c + + In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and + an optional larger "block" (size and command provided in args). OpenOCD's spi.c only uses "block" sizes. + */ + + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); + + return err; +} + +/* ----------------------------------------------------------------------------- + Driver probing etc */ + +static int rp2040_ssel_active(struct target *target, bool active) +{ + const target_addr_t qspi_ctrl_addr = 0x4001800c; + const uint32_t qspi_ctrl_outover_low = 2UL << 8; + const uint32_t qspi_ctrl_outover_high = 3UL << 8; + uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high; + uint32_t val; + + int err = target_read_u32(target, qspi_ctrl_addr, &val); + if (err != ERROR_OK) + return err; + + val = (val & ~qspi_ctrl_outover_high) | state; + + err = target_write_u32(target, qspi_ctrl_addr, val); + if (err != ERROR_OK) + return err; + + return ERROR_OK; +} + +static int rp2040_flash_probe(struct flash_bank *bank) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; + + int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline); + if (err != ERROR_OK) { + LOG_ERROR("Debug trampoline not found in RP2040 ROM."); + return err; + } + priv->jump_debug_trampoline &= ~1u; /* mask off thumb bit */ + + err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE_END, &priv->jump_debug_trampoline_end); + if (err != ERROR_OK) { + LOG_ERROR("Debug trampoline end not found in RP2040 ROM."); + return err; + } + priv->jump_debug_trampoline_end &= ~1u; /* mask off thumb bit */ + + err = rp2040_lookup_symbol(target, FUNC_FLASH_EXIT_XIP, &priv->jump_flash_exit_xip); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2040 ROM."); + return err; + } + + err = rp2040_lookup_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, &priv->jump_connect_internal_flash); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2040 ROM."); + return err; + } + + err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_ERASE, &priv->jump_flash_range_erase); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM."); + return err; + } + + err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2040 ROM."); + return err; + } + + err = rp2040_lookup_symbol(target, FUNC_FLASH_FLUSH_CACHE, &priv->jump_flush_cache); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2040 ROM."); + return err; + } + + err = rp2040_lookup_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, &priv->jump_enter_cmd_xip); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2040 ROM."); + return err; + } + + err = stack_grab_and_prep(bank); + if (err != ERROR_OK) + return err; + + uint32_t device_id = 0; + const target_addr_t ssi_dr0 = 0x18000060; + + err = rp2040_ssel_active(target, true); + + /* write RDID request into SPI peripheral's FIFO */ + for (int count = 0; (count < 4) && (err == ERROR_OK); count++) + err = target_write_u32(target, ssi_dr0, SPIFLASH_READ_ID); + + /* by this time, there is a receive FIFO entry for every write */ + for (int count = 0; (count < 4) && (err == ERROR_OK); count++) { + uint32_t status; + err = target_read_u32(target, ssi_dr0, &status); + + device_id >>= 8; + device_id |= (status & 0xFF) << 24; + } + device_id >>= 8; + + err = rp2040_ssel_active(target, false); + if (err != ERROR_OK) { + LOG_ERROR("SSEL inactive failed"); + return err; + } + + /* search for a SPI flash Device ID match */ + priv->dev = NULL; + for (const struct flash_device *p = flash_devices; p->name ; p++) + if (p->device_id == device_id) { + priv->dev = p; + break; + } + + if (!priv->dev) { + LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id); + return ERROR_FAIL; + } + + LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", + priv->dev->name, priv->dev->device_id); + + /* the Boot ROM flash_range_program() routine requires page alignment */ + bank->write_start_alignment = priv->dev->pagesize; + bank->write_end_alignment = priv->dev->pagesize; + + bank->size = priv->dev->size_in_bytes; + + bank->num_sectors = bank->size / priv->dev->sectorsize; + LOG_INFO("RP2040 B0 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n", + bank->size, bank->base, bank->num_sectors); + bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors); + if (!bank->sectors) + return ERROR_FAIL; + + if (err == ERROR_OK) + priv->probed = true; + + return err; +} + +static int rp2040_flash_auto_probe(struct flash_bank *bank) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + + if (priv->probed) + return ERROR_OK; + + return rp2040_flash_probe(bank); +} + +static void rp2040_flash_free_driver_priv(struct flash_bank *bank) +{ + free(bank->driver_priv); + bank->driver_priv = NULL; +} + +/* ----------------------------------------------------------------------------- + Driver boilerplate */ + +FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) +{ + struct rp2040_flash_bank *priv; + priv = malloc(sizeof(struct rp2040_flash_bank)); + priv->probed = false; + + /* Set up driver_priv */ + bank->driver_priv = priv; + + return ERROR_OK; +} + +struct flash_driver rp2040_flash = { + .name = "rp2040_flash", + .commands = NULL, + .flash_bank_command = rp2040_flash_bank_command, + .erase = rp2040_flash_erase, + .write = rp2040_flash_write, + .read = default_flash_read, + .probe = rp2040_flash_probe, + .auto_probe = rp2040_flash_auto_probe, + .erase_check = default_flash_blank_check, + .free_driver_priv = rp2040_flash_free_driver_priv +}; diff --git a/tcl/board/pico-debug.cfg b/tcl/board/pico-debug.cfg new file mode 100644 index 000000000..c2fe7d3e2 --- /dev/null +++ b/tcl/board/pico-debug.cfg @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# pico-debug is a virtual CMSIS-DAP debug adapter +# it runs on the very same RP2040 target being debugged without additional hardware +# https://github.com/majbthrd/pico-debug + +source [find interface/cmsis-dap.cfg] +adapter speed 4000 + +set CHIPNAME rp2040 +source [find target/rp2040-core0.cfg] + diff --git a/tcl/target/rp2040-core0.cfg b/tcl/target/rp2040-core0.cfg new file mode 100644 index 000000000..e427083bc --- /dev/null +++ b/tcl/target/rp2040-core0.cfg @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +transport select swd + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rp2040 +} + +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x01002927 +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap +$_TARGETNAME configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE + +set _FLASHNAME $_CHIPNAME.flash +set _FLASHSIZE 0x200000 +set _FLASHBASE 0x10000000 +flash bank $_FLASHNAME rp2040_flash $_FLASHBASE $_FLASHSIZE 1 32 $_TARGETNAME + +# srst does not exist; use SYSRESETREQ to perform a soft reset +cortex_m reset_config sysresetreq + From a115b589a71d665787759cf8f2ff07210fd47164 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 22 Apr 2021 20:47:23 +0100 Subject: [PATCH 56/58] cortex_m: implement hit_watchpoint function this change aims to provide a better gdb debugging experience, by making gdb understand what's really happening. before this change when hitting a watchpoint - openocd reports "T05" to gdb - gdb displays: Program received signal SIGTRAP, Trace/breakpoint trap. after the change - openocd reports "T05watch:20000000;" to gdb - gdb displays: Hardware watchpoint 1: *0x20000000 Old value = 16000000 New value = 170000000 ... Change-Id: Iac3a85eadd86663617889001dd04513a4211ced9 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/6181 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/cortex_m.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 46b0e3c2a..2b38b4a7f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1596,6 +1596,35 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo return ERROR_OK; } +int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) +{ + if (target->debug_reason != DBG_REASON_WATCHPOINT) + return ERROR_FAIL; + + struct cortex_m_common *cortex_m = target_to_cm(target); + + for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) { + if (!wp->set) + continue; + + unsigned int dwt_num = wp->set - 1; + struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num; + + uint32_t dwt_function; + int retval = target_read_u32(target, comparator->dwt_comparator_address + 8, &dwt_function); + if (retval != ERROR_OK) + return ERROR_FAIL; + + /* check the MATCHED bit */ + if (dwt_function & BIT(24)) { + *hit_watchpoint = wp; + return ERROR_OK; + } + } + + return ERROR_FAIL; +} + void cortex_m_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; @@ -2523,6 +2552,7 @@ struct target_type cortexm_target = { .remove_breakpoint = cortex_m_remove_breakpoint, .add_watchpoint = cortex_m_add_watchpoint, .remove_watchpoint = cortex_m_remove_watchpoint, + .hit_watchpoint = cortex_m_hit_watchpoint, .commands = cortex_m_command_handlers, .target_create = cortex_m_target_create, From f950c4fbf2d6c14e86a33d6b5ea1acf890fc1d59 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 3 May 2021 11:10:58 -0700 Subject: [PATCH 57/58] Fix build. Change-Id: Icb7318c8ea6eaeace503d6d2171b34e59a6449db --- src/helper/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/command.c b/src/helper/command.c index eb50ce182..4cda7c2f8 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -980,7 +980,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL))) return JIM_ERR; - target_call_timer_callbacks_now(); + target_call_timer_callbacks_now(NULL); /* * Black magic of overridden current target: From 38eea2367cae855ba0a4be1fb188d61cbff23d91 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 3 May 2021 12:21:17 -0700 Subject: [PATCH 58/58] Add keep_alive() to system bus read loop. Without it the repeat read test wasn't passing any longer. This is because 7dd323b26d93e49e409e02053e30f53ac8138cd5 reduced the remote bitbang performance. I've notified the mailing list about this. Change-Id: Ie71592792202423aec89fa889b9e3d2a60a3c25f Signed-off-by: Tim Newsome --- src/target/riscv/riscv-013.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 0c1c04952..80fe5e551 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2745,6 +2745,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, } next_read = address + i * size + j * 4; } + keep_alive(); } uint32_t sbcs_read = 0;