diff --git a/Makefile.am b/Makefile.am index d2d199349..55d79e6e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -127,8 +127,6 @@ uninstall-hook: distclean-local: rm -rf Doxyfile doxygen rm -f $(srcdir)/jimtcl/configure.gnu -# FIXME: workaround for jimtcl 0.80 only. Remove from jimtcl 0.81 - rm -f jimtcl/examples.api/Makefile # We want every change to have Signed-off-by. This is tricky to enforce in # Travis, because it automatically makes temporary commits when merging. So diff --git a/contrib/loaders/flash/stm32/stm32lx.S b/contrib/loaders/flash/stm32/stm32lx.S index 399be8bfb..7cfe48545 100644 --- a/contrib/loaders/flash/stm32/stm32lx.S +++ b/contrib/loaders/flash/stm32/stm32lx.S @@ -22,37 +22,59 @@ * GNU General Public License for more details. * ***************************************************************************/ - .text .syntax unified .cpu cortex-m0 .thumb /* +Parameters r0 - destination address r1 - source address - r2 - count + r2 - half pages + r3 - bytes per half page + r4 - flash base +Variables + r0 - destination write pointer + r1 - source read pointer + r2 - source limit address + r3 - bytes per half page + r4 - flash base + r5 - pages left in current half page + r6 - temporary r/w */ +/* offsets of registers from flash reg base */ +#define STM32_FLASH_SR_OFFSET 0x18 + .thumb_func .global _start _start: - // r2 = source + count * 4 - lsls r2, r2, #2 - adds r2, r1, r2 + // r2 = source + half pages * bytes per half page + muls r2, r2, r3 + add r2, r1, r2 // Go to compare - b test_done + b test_done +write_half_page: + // initialize pages left in current half page + mov r5, r3 write_word: // load word from address in r1 and increase r1 by 4 - ldmia r1!, {r3} + ldmia r1!, {r6} // store word to address in r0 and increase r0 by 4 - stmia r0!, {r3} + stmia r0!, {r6} + // check for end of half page + subs r5, r5, #4 + bne write_word +wait_busy: + // read status register into r6, loop while bottom bit is set + ldr r6, [r4, #STM32_FLASH_SR_OFFSET] + lsls r6, r6, #31 + bne wait_busy test_done: - // compare r1 and r2 + // compare r1 and r2, loop if not equal cmp r1, r2 - // loop if not equal - bne write_word + bne write_half_page // Set breakpoint to exit - bkpt #0x00 - + bkpt #0x00 diff --git a/contrib/loaders/flash/stm32/stm32lx.inc b/contrib/loaders/flash/stm32/stm32lx.inc index eaaf1848a..668de2778 100644 --- a/contrib/loaders/flash/stm32/stm32lx.inc +++ b/contrib/loaders/flash/stm32/stm32lx.inc @@ -1,2 +1,3 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ -0x92,0x00,0x8a,0x18,0x01,0xe0,0x08,0xc9,0x08,0xc0,0x91,0x42,0xfb,0xd1,0x00,0xbe, +0x5a,0x43,0x0a,0x44,0x07,0xe0,0x1d,0x46,0x40,0xc9,0x40,0xc0,0x04,0x3d,0xfb,0xd1, +0xa6,0x69,0xf6,0x07,0xfc,0xd1,0x91,0x42,0xf5,0xd1,0x00,0xbe, diff --git a/doc/openocd.texi b/doc/openocd.texi index de07c7fca..d0e4e1431 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2367,6 +2367,14 @@ The USB bus topology can be queried with the command @emph{lsusb -t} or @emph{dm This command is only available if your libusb1 is at least version 1.0.16. @end deffn +@deffn {Config Command} {adapter serial} serial_string +Specifies the @var{serial_string} of the adapter to use. +If this command is not specified, serial strings are not checked. +Only the following adapter drivers use the serial string from this command: +aice (aice_usb), arm-jtag-ew, cmsis_dap, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus, +openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110. +@end deffn + @section Interface Drivers Each of the interface drivers listed here must be explicitly @@ -2419,11 +2427,6 @@ cmsis_dap_vid_pid 0xc251 0xf001 0x0d28 0x0204 @end example @end deffn -@deffn {Config Command} {cmsis_dap_serial} [serial] -Specifies the @var{serial} of the CMSIS-DAP device to use. -If not specified, serial numbers are not considered. -@end deffn - @deffn {Config Command} {cmsis_dap_backend} [@option{auto}|@option{usb_bulk}|@option{hid}] Specifies how to communicate with the adapter: @@ -2459,7 +2462,7 @@ This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, -bypassing intermediate libraries like libftdi or D2XX. +bypassing intermediate libraries like libftdi. Support for new FTDI based adapters can be added completely through configuration files, without the need to patch and rebuild OpenOCD. @@ -2508,15 +2511,6 @@ of the adapter. If not specified, the device description is ignored during device selection. @end deffn -@deffn {Config Command} {ftdi serial} serial-number -Specifies the @var{serial-number} of the adapter to use, -in case the vendor provides unique IDs and more than one adapter -is connected to the host. -If not specified, serial numbers are not considered. -(Note that USB serial numbers can be arbitrary Unicode strings, -and are not restricted to containing only decimal digits.) -@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. @@ -2637,12 +2631,6 @@ The vendor ID and product ID of the adapter. If not specified, default 0x0403:0x6001 is used. @end deffn -@deffn {Config Command} {ft232r serial_desc} @var{serial} -Specifies the @var{serial} of the adapter to use, in case the -vendor provides unique IDs and more than one adapter is connected to -the host. If not specified, serial numbers are not considered. -@end deffn - @deffn {Config Command} {ft232r jtag_nums} @var{tck} @var{tms} @var{tdi} @var{tdo} Set four JTAG GPIO numbers at once. If not specified, default 0 3 1 2 or TXD CTS RXD RTS is used. @@ -2728,13 +2716,6 @@ USB JTAG/USB-Blaster compatibles over one of the userspace libraries for FTDI chips. These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: -@deffn {Config Command} {usb_blaster device_desc} description -Provides the USB device description (the @emph{iProduct string}) -of the FTDI FT245 device. If not -specified, the FTDI default value is used. This setting is only valid -if compiled with FTD2XX support. -@end deffn - @deffn {Config Command} {usb_blaster vid_pid} vid pid The vendor ID and product ID of the FTDI FT245 device. If not specified, default values are used. @@ -2840,7 +2821,7 @@ Reset the current configuration. @deffn {Command} {jlink config write} Write the current configuration to the internal persistent storage. @end deffn -@deffn {Command} {jlink emucom write } +@deffn {Command} {jlink emucom write} Write data to an EMUCOM channel. The data needs to be encoded as hexadecimal pairs. @@ -2850,7 +2831,7 @@ the EMUCOM channel 0x10: > jlink emucom write 0x10 aa0b23 @end example @end deffn -@deffn {Command} {jlink emucom read } +@deffn {Command} {jlink emucom read} Read data from an EMUCOM channel. The read data is encoded as hexadecimal pairs. @@ -2866,12 +2847,6 @@ 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 the serial number instead, if possible. -As a configuration command, it can be used only before 'init'. -@end deffn -@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. - As a configuration command, it can be used only before 'init'. @end deffn @end deffn @@ -2914,11 +2889,6 @@ Indicate that a PSoC acquisition sequence needs to be run during adapter init. Please be aware that the acquisition sequence hard-resets the target. @end deffn -@deffn {Config Command} {kitprog_serial} serial -Select a KitProg device by its @var{serial}. If left unspecified, the first -device detected by OpenOCD will be used. -@end deffn - @deffn {Command} {kitprog acquire_psoc} Run a PSoC acquisition sequence immediately. Typically, this should not be used outside of the target-specific configuration scripts since it hard-resets the @@ -3033,9 +3003,6 @@ parport cable wiggler @deffn {Interface Driver} {presto} ASIX PRESTO USB JTAG programmer. -@deffn {Config Command} {presto serial} serial_string -Configures the USB serial number of the Presto device to use. -@end deffn @end deffn @deffn {Interface Driver} {rlink} @@ -3072,10 +3039,6 @@ version reported is V2.J21.S4. Currently Not Supported. @end deffn -@deffn {Config Command} {hla_serial} serial -Specifies the serial number of the adapter. -@end deffn - @deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi}|@option{nulink}) Specifies the adapter layout to use. @end deffn @@ -3124,10 +3087,6 @@ ST-LINK server software module}. @emph{Note:} ST-Link TCP server does not support the SWIM transport. @end deffn -@deffn {Config Command} {st-link serial} serial -Specifies the serial number of the adapter. -@end deffn - @deffn {Config Command} {st-link vid_pid} [vid pid]+ Pairs of vendor IDs and product IDs of the device. @end deffn @@ -3167,11 +3126,6 @@ LaunchPad evaluation boards. The XDS110 is also available as a stand-alone USB debug probe with the added capability to supply power to the target board. The following commands are supported by the XDS110 driver: -@deffn {Config Command} {xds110 serial} serial_string -Specifies the serial number of which XDS110 probe to use. Otherwise, the first -XDS110 found will be used. -@end deffn - @deffn {Config Command} {xds110 supply} voltage_in_millivolts Available only on the XDS110 stand-alone probe. Sets the voltage level of the XDS110 power supply. A value of 0 leaves the supply off. Otherwise, the supply @@ -3214,6 +3168,8 @@ able to coexist nicely with both sysfs bitbanging and various peripherals' kernel drivers. The driver restores the previous configuration on exit. +GPIO numbers >= 32 can't be used for performance reasons. + See @file{interface/raspberrypi-native.cfg} for a sample config and pinout. @@ -3476,11 +3432,6 @@ 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} -Updates TRN (turnaround delay) and prescaling.fields of the -Wire Control Register (WCR). -No parameters: displays current settings. -@end deffn @subsection SPI Transport @cindex SPI @@ -4409,6 +4360,20 @@ A DAP may also provide optional @var{configparams}: register during initial examination and when checking the sticky error bit. This bit is normally checked after setting the CSYSPWRUPREQ bit, but some devices do not set the ack bit until sometime later. + +@item @code{-dp-id} @var{number} +@*Debug port identification number for SWD DPv2 multidrop. +The @var{number} is written to bits 0..27 of DP TARGETSEL during DP selection. +To find the id number of a single connected device read DP TARGETID: +@code{device.dap dpreg 0x24} +Use bits 0..27 of TARGETID. + +@item @code{-instance-id} @var{number} +@*Instance identification number for SWD DPv2 multidrop. +The @var{number} is written to bits 28..31 of DP TARGETSEL during DP selection. +To find the instance number of a single connected device read DP DLPIDR: +@code{device.dap dpreg 0x34} +The instance number is in bits 28..31 of DLPIDR value. @end itemize @end deffn @@ -5585,6 +5550,10 @@ will not work. These include all @command{*_image} and functionality is available through the @command{flash write_bank}, @command{flash read_bank}, and @command{flash verify_bank} commands. +According to device size, 1- to 4-byte addresses are sent. However, some +flash chips additionally have to be switched to 4-byte addresses by an extra +command, see below. + @itemize @item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR. For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the @@ -5597,6 +5566,29 @@ set _XILINX_USER1 0x02 flash bank $_FLASHNAME spi 0x0 0 0 0 \ $_TARGETNAME $_XILINX_USER1 @end example + +@deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd +Sets flash parameters: @var{name} human readable string, @var{total_size} +size in bytes, @var{page_size} is write page size. @var{read_cmd} and @var{pprg_cmd} +are commands for read and page program, respectively. @var{mass_erase_cmd}, +@var{sector_size} and @var{sector_erase_cmd} are optional. +@example +jtagspi set 0 w25q128 0x1000000 0x100 0x03 0 0x02 0xC7 0x10000 0xD8 +@end example +@end deffn + +@deffn Command {jtagspi cmd} bank_id resp_num cmd_byte ... +Sends command @var{cmd_byte} and at most 20 following bytes and reads +@var{resp_num} bytes afterwards. E.g. for 'Enter 4-byte address mode' +@example +jtagspi cmd 0 0 0xB7 +@end example +@end deffn + +@deffn Command {jtagspi always_4byte} bank_id [ on | off ] +Some devices use 4-byte addresses for all commands except the legacy 0x03 read +regardless of device size. This command controls the corresponding hack. +@end deffn @end deffn @deffn {Flash Driver} {xcf} @@ -7098,8 +7090,8 @@ applied to all of them. @deffn {Flash Driver} {stm32f1x} All members of the STM32F0, STM32F1 and STM32F3 microcontroller families -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. +from STMicroelectronics and all members of the GD32F1x0, GD32F3x0 and GD32E23x microcontroller +families from GigaDevice include internal flash and use ARM Cortex-M0/M3/M4/M23 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @@ -7175,7 +7167,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 @@ -7612,7 +7604,7 @@ Some tms470-specific commands are defined: 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_megahertz} clock_mhz Reports the clock speed, which is used to calculate timings. @end deffn @@ -8647,7 +8639,7 @@ If the control block location is not known, OpenOCD starts searching for it. 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 @@ -8995,7 +8987,7 @@ Enable (@option{on}) or disable (@option{off}) the CTI. 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 @@ -9502,7 +9494,7 @@ cores @emph{except the ARM1176} use the same six bits. 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. @@ -9540,12 +9532,12 @@ possible (4096) entries are printed. @subsection ARMv7-R specific commands @cindex Cortex-R -@deffn {Command} {cortex_r dbginit} +@deffn {Command} {cortex_r4 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_r4 maskisr} [@option{on}|@option{off}] Selects whether interrupts will be processed when single stepping @end deffn @@ -10108,14 +10100,6 @@ included in the generated target descriptor file. addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system @end example - -@end deffn -@deffn {Command} {readgroup} (@option{group}) -Display all registers in @emph{group}. - -@emph{group} can be "system", - "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf", "power", "pic", - "timer" or any new group created with addreg command. @end deffn @section RISC-V Architecture @@ -10232,11 +10216,6 @@ 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] -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 @emph{DEPRECATED -- avoid using this. Use the command @command{riscv set_mem_access} instead.} diff --git a/jimtcl b/jimtcl index 2d66360c6..70b007b63 160000 --- a/jimtcl +++ b/jimtcl @@ -1 +1 @@ -Subproject commit 2d66360c61d2a89d4008e8bad12ae3aa5f0331e2 +Subproject commit 70b007b63669a709b0e8aef34a22658047815cc2 diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c index 6707314cc..b796fb7ce 100644 --- a/src/flash/nand/tcl.c +++ b/src/flash/nand/tcl.c @@ -528,8 +528,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name, } if (controller->commands) { - retval = register_commands(CMD_CTX, NULL, - controller->commands); + retval = register_commands(CMD_CTX, NULL, controller->commands); if (retval != ERROR_OK) return retval; } diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 5cefd1766..a8fab486c 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -251,6 +251,7 @@ static const struct samd_part saml21_parts[] = { /* SAMR34/R35 parts have integrated SAML21 with a lora radio */ { 0x28, "SAMR34J18", 256, 32 }, + { 0x2B, "SAMR35J18", 256, 32 }, }; /* Known SAML22 parts. */ diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index ab0186d7d..fb4b09624 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -119,9 +119,9 @@ static const struct efm32_family_data efm32_families[] = { { 16, "EFR32MG1P Mighty", .series = 1 }, { 17, "EFR32MG1B Mighty", .series = 1 }, { 18, "EFR32MG1V Mighty", .series = 1 }, - { 19, "EFR32MG1P Blue", .series = 1 }, - { 20, "EFR32MG1B Blue", .series = 1 }, - { 21, "EFR32MG1V Blue", .series = 1 }, + { 19, "EFR32BG1P Blue", .series = 1 }, + { 20, "EFR32BG1B Blue", .series = 1 }, + { 21, "EFR32BG1V Blue", .series = 1 }, { 25, "EFR32FG1P Flex", .series = 1 }, { 26, "EFR32FG1B Flex", .series = 1 }, { 27, "EFR32FG1V Flex", .series = 1 }, diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c index dc49fda61..a5672c63e 100644 --- a/src/flash/nor/jtagspi.c +++ b/src/flash/nor/jtagspi.c @@ -29,9 +29,12 @@ struct jtagspi_flash_bank { struct jtag_tap *tap; - const struct flash_device *dev; + struct flash_device dev; + char devname[32]; bool probed; + bool always_4byte; /* use always 4-byte address except for basic read 0x03 */ uint32_t ir; + unsigned int addr_len; /* address length in bytes */ }; FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command) @@ -46,6 +49,7 @@ FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command) LOG_ERROR("no memory for flash bank info"); return ERROR_FAIL; } + bank->sectors = NULL; bank->driver_priv = info; info->tap = NULL; @@ -69,70 +73,59 @@ static void jtagspi_set_ir(struct flash_bank *bank) jtag_add_ir_scan(info->tap, &field, TAP_IDLE); } -static void flip_u8(uint8_t *in, uint8_t *out, int len) +static void flip_u8(const uint8_t *in, uint8_t *out, unsigned int len) { - for (int i = 0; i < len; i++) + for (unsigned int i = 0; i < len; i++) out[i] = flip_u32(in[i], 8); } static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, - uint32_t *addr, uint8_t *data, int len) + uint8_t *write_buffer, unsigned int write_len, uint8_t *data_buffer, int data_len) { - struct jtagspi_flash_bank *info = bank->driver_priv; + assert(write_buffer || write_len == 0); + assert(data_buffer || data_len == 0); + struct scan_field fields[6]; - uint8_t marker = 1; - uint8_t xfer_bits_buf[4]; - uint8_t addr_buf[3]; - uint8_t *data_buf; - uint32_t xfer_bits; - int is_read, lenb, n; - /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */ + LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len); - is_read = (len < 0); + /* negative data_len == read operation */ + const bool is_read = (data_len < 0); if (is_read) - len = -len; - - n = 0; + data_len = -data_len; + int n = 0; + const uint8_t marker = 1; fields[n].num_bits = 1; fields[n].out_value = ▮ fields[n].in_value = NULL; n++; - xfer_bits = 8 + len - 1; - /* cmd + read/write - 1 due to the counter implementation */ - if (addr) - xfer_bits += 24; - h_u32_to_be(xfer_bits_buf, xfer_bits); - flip_u8(xfer_bits_buf, xfer_bits_buf, 4); - fields[n].num_bits = 32; - fields[n].out_value = xfer_bits_buf; + /* transfer length = cmd + address + read/write, + * -1 due to the counter implementation */ + uint8_t xfer_bits[4]; + h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1); + flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits)); + fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT; + fields[n].out_value = xfer_bits; fields[n].in_value = NULL; n++; - cmd = flip_u32(cmd, 8); - fields[n].num_bits = 8; + flip_u8(&cmd, &cmd, sizeof(cmd)); + fields[n].num_bits = sizeof(cmd) * CHAR_BIT; fields[n].out_value = &cmd; fields[n].in_value = NULL; n++; - if (addr) { - h_u24_to_be(addr_buf, *addr); - flip_u8(addr_buf, addr_buf, 3); - fields[n].num_bits = 24; - fields[n].out_value = addr_buf; + if (write_len) { + flip_u8(write_buffer, write_buffer, write_len); + fields[n].num_bits = write_len * CHAR_BIT; + fields[n].out_value = write_buffer; fields[n].in_value = NULL; n++; } - lenb = DIV_ROUND_UP(len, 8); - data_buf = malloc(lenb); - if (lenb > 0) { - if (!data_buf) { - LOG_ERROR("no memory for spi buffer"); - return ERROR_FAIL; - } + if (data_len > 0) { if (is_read) { fields[n].num_bits = jtag_tap_count_enabled(); fields[n].out_value = NULL; @@ -140,36 +133,263 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd, n++; fields[n].out_value = NULL; - fields[n].in_value = data_buf; + fields[n].in_value = data_buffer; } else { - flip_u8(data, data_buf, lenb); - fields[n].out_value = data_buf; + flip_u8(data_buffer, data_buffer, data_len); + fields[n].out_value = data_buffer; fields[n].in_value = NULL; } - fields[n].num_bits = len; + fields[n].num_bits = data_len * CHAR_BIT; n++; } jtagspi_set_ir(bank); /* passing from an IR scan to SHIFT-DR clears BYPASS registers */ + struct jtagspi_flash_bank *info = bank->driver_priv; jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE); int retval = jtag_execute_queue(); if (is_read) - flip_u8(data_buf, data, lenb); - free(data_buf); + flip_u8(data_buffer, data_buffer, data_len); return retval; } +COMMAND_HANDLER(jtagspi_handle_set) +{ + struct flash_bank *bank = NULL; + struct jtagspi_flash_bank *info = NULL; + struct flash_sector *sectors = NULL; + uint32_t temp; + unsigned int index = 1; + int retval; + + LOG_DEBUG("%s", __func__); + + /* there are 6 mandatory arguments: + * devname, size_in_bytes, pagesize, read_cmd, unused, pprog_cmd */ + if (index + 6 > CMD_ARGC) { + command_print(CMD, "jtagspi: not enough arguments"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + info = bank->driver_priv; + + /* invalidate all old info */ + if (info->probed) { + bank->size = 0; + bank->num_sectors = 0; + if (bank->sectors) + free(bank->sectors); + bank->sectors = NULL; + info->always_4byte = false; + info->probed = false; + } + memset(&info->dev, 0, sizeof(info->dev)); + + strncpy(info->devname, CMD_ARGV[index++], sizeof(info->devname) - 1); + info->devname[sizeof(info->devname) - 1] = '\0'; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], temp); + info->dev.size_in_bytes = temp; + if ((temp & (temp - 1)) || (temp < (1UL << 8))) { + command_print(CMD, "jtagspi: device size must be 2^n with n >= 8"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], temp); + info->dev.pagesize = temp; + if (info->dev.pagesize == 0) + info->dev.pagesize = SPIFLASH_DEF_PAGESIZE; + if ((temp & (temp - 1)) || (temp > info->dev.size_in_bytes)) { + command_print(CMD, "jtagspi: page size must be 2^n and <= device size"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], info->dev.read_cmd); + if ((info->dev.read_cmd != 0x03) && + (info->dev.read_cmd != 0x13)) { + command_print(CMD, "jtagspi: only 0x03/0x13 READ allowed"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], info->dev.qread_cmd); + + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], info->dev.pprog_cmd); + if ((info->dev.pprog_cmd != 0x02) && + (info->dev.pprog_cmd != 0x12)) { + command_print(CMD, "jtagspi: only 0x02/0x12 PPRG allowed"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + /* remaining params are optional */ + if (index < CMD_ARGC) + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], info->dev.chip_erase_cmd); + else + info->dev.chip_erase_cmd = 0x00; + + if (index < CMD_ARGC) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], temp); + info->dev.sectorsize = temp; + if ((info->dev.sectorsize > info->dev.size_in_bytes) || + (info->dev.sectorsize < info->dev.pagesize) || (temp & (temp - 1))) { + command_print(CMD, "jtagspi: sector size must be 2^n and <= device size"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (index < CMD_ARGC) + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], info->dev.erase_cmd); + else { + command_print(CMD, "jtagspi: erase command missing"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else { + /* no sector size / sector erase cmd given, treat whole bank as a single sector */ + info->dev.erase_cmd = 0x00; + info->dev.sectorsize = info->dev.size_in_bytes; + } + + if (index < CMD_ARGC) { + command_print(CMD, "jtagspi: extra arguments"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + /* set correct size value */ + bank->size = info->dev.size_in_bytes; + + /* calculate address length in bytes */ + if (bank->size <= (1UL << 8)) + info->addr_len = 1; + else if (bank->size <= (1UL << 16)) + info->addr_len = 2; + else if (bank->size <= (1UL << 24)) + info->addr_len = 3; + else { + info->addr_len = 4; + LOG_WARNING("4-byte addresses needed, might need extra command to enable"); + } + + /* create and fill sectors array */ + bank->num_sectors = + info->dev.size_in_bytes / info->dev.sectorsize; + sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + if (!sectors) { + LOG_ERROR("Not enough memory"); + return ERROR_FAIL; + } + + for (unsigned int sector = 0; sector < bank->num_sectors; sector++) { + sectors[sector].offset = sector * (info->dev.sectorsize); + sectors[sector].size = info->dev.sectorsize; + sectors[sector].is_erased = -1; + sectors[sector].is_protected = 0; + } + + bank->sectors = sectors; + info->dev.name = info->devname; + if (info->dev.size_in_bytes / 4096) + LOG_INFO("flash \'%s\' id = unknown\nflash size = %" PRIu32 " kbytes", + info->dev.name, info->dev.size_in_bytes / 1024); + else + LOG_INFO("flash \'%s\' id = unknown\nflash size = %" PRIu32 " bytes", + info->dev.name, info->dev.size_in_bytes); + info->probed = true; + + return ERROR_OK; +} + +COMMAND_HANDLER(jtagspi_handle_cmd) +{ + struct flash_bank *bank; + unsigned int index = 1; + const int max = 21; + uint8_t num_write, num_read, write_buffer[max], read_buffer[1 << CHAR_BIT]; + uint8_t data, *ptr; + char temp[4], output[(2 + max + (1 << CHAR_BIT)) * 3 + 8]; + int retval; + + LOG_DEBUG("%s", __func__); + + if (CMD_ARGC < 3) { + command_print(CMD, "jtagspi: not enough arguments"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + num_write = CMD_ARGC - 2; + if (num_write > max) { + LOG_ERROR("at most %d bytes may be send", max); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], num_read); + + snprintf(output, sizeof(output), "spi: "); + for (ptr = &write_buffer[0] ; index < CMD_ARGC; index++) { + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index], data); + *ptr++ = data; + snprintf(temp, sizeof(temp), "%02" PRIx8 " ", data); + strncat(output, temp, sizeof(output) - strlen(output) - 1); + } + strncat(output, "-> ", sizeof(output) - strlen(output) - 1); + + /* process command */ + ptr = &read_buffer[0]; + jtagspi_cmd(bank, write_buffer[0], &write_buffer[1], num_write - 1, ptr, -num_read); + if (retval != ERROR_OK) + return retval; + + for ( ; num_read > 0; num_read--) { + snprintf(temp, sizeof(temp), "%02" PRIx8 " ", *ptr++); + strncat(output, temp, sizeof(output) - strlen(output) - 1); + } + command_print(CMD, "%s", output); + + return ERROR_OK; +} + +COMMAND_HANDLER(jtagspi_handle_always_4byte) +{ + struct flash_bank *bank; + struct jtagspi_flash_bank *jtagspi_info; + int retval; + + LOG_DEBUG("%s", __func__); + + if ((CMD_ARGC != 1) && (CMD_ARGC != 2)) + return ERROR_COMMAND_SYNTAX_ERROR; + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + jtagspi_info = bank->driver_priv; + + if (CMD_ARGC == 1) + command_print(CMD, jtagspi_info->always_4byte ? "on" : "off"); + else + COMMAND_PARSE_BOOL(CMD_ARGV[1], jtagspi_info->always_4byte, "on", "off"); + + return ERROR_OK; +} + static int jtagspi_probe(struct flash_bank *bank) { struct jtagspi_flash_bank *info = bank->driver_priv; struct flash_sector *sectors; + const struct flash_device *p; uint8_t in_buf[3]; uint32_t id, sectorsize; - if (info->probed) + if (bank->sectors) { free(bank->sectors); + bank->sectors = NULL; + } info->probed = false; if (!bank->target->tap) { @@ -178,38 +398,46 @@ static int jtagspi_probe(struct flash_bank *bank) } info->tap = bank->target->tap; - jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, in_buf, -24); + jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, 0, in_buf, -3); /* the table in spi.c has the manufacturer byte (first) as the lsb */ id = le_to_h_u24(in_buf); - info->dev = NULL; - for (const struct flash_device *p = flash_devices; p->name ; p++) + memset(&info->dev, 0, sizeof(info->dev)); + for (p = flash_devices; p->name ; p++) if (p->device_id == id) { - info->dev = p; + memcpy(&info->dev, p, sizeof(info->dev)); break; } - if (!(info->dev)) { - LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); + if (!(p->name)) { + LOG_ERROR("Unknown flash device (ID 0x%06" PRIx32 ")", id & 0xFFFFFF); return ERROR_FAIL; } - LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", - info->dev->name, info->dev->device_id); + LOG_INFO("Found flash device \'%s\' (ID 0x%06" PRIx32 ")", + info->dev.name, info->dev.device_id & 0xFFFFFF); /* Set correct size value */ - bank->size = info->dev->size_in_bytes; - if (bank->size <= (1UL << 16)) - LOG_WARNING("device needs 2-byte addresses - not implemented"); - if (bank->size > (1UL << 24)) - LOG_WARNING("device needs paging or 4-byte addresses - not implemented"); + bank->size = info->dev.size_in_bytes; + + /* calculate address length in bytes */ + if (bank->size <= (1UL << 8)) + info->addr_len = 1; + else if (bank->size <= (1UL << 16)) + info->addr_len = 2; + else if (bank->size <= (1UL << 24)) + info->addr_len = 3; + else { + info->addr_len = 4; + LOG_WARNING("4-byte addresses needed, might need extra command to enable"); + } /* if no sectors, treat whole bank as single sector */ - sectorsize = info->dev->sectorsize ? - info->dev->sectorsize : info->dev->size_in_bytes; + sectorsize = info->dev.sectorsize ? + info->dev.sectorsize : info->dev.size_in_bytes; /* create and fill sectors array */ - bank->num_sectors = info->dev->size_in_bytes / sectorsize; + bank->num_sectors = info->dev.size_in_bytes / sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); if (!sectors) { LOG_ERROR("not enough memory"); @@ -228,27 +456,35 @@ static int jtagspi_probe(struct flash_bank *bank) return ERROR_OK; } +static int jtagspi_auto_probe(struct flash_bank *bank) +{ + struct jtagspi_flash_bank *info = bank->driver_priv; + + if (info->probed) + return ERROR_OK; + return jtagspi_probe(bank); +} + static int jtagspi_read_status(struct flash_bank *bank, uint32_t *status) { uint8_t buf; - int err = jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8); + int err = jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, 0, &buf, -1); if (err == ERROR_OK) { *status = buf; - /* LOG_DEBUG("status=0x%08" PRIx32, *status); */ + LOG_DEBUG("status=0x%02" PRIx32, *status); } - return err; } static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) { - uint32_t status; int64_t t0 = timeval_ms(); int64_t dt; do { dt = timeval_ms() - t0; + uint32_t status = (uint32_t)-1; int retval = jtagspi_read_status(bank, &status); if (retval != ERROR_OK) return retval; @@ -266,16 +502,15 @@ static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) static int jtagspi_write_enable(struct flash_bank *bank) { - uint32_t status; - - jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0); + jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, 0, NULL, 0); + uint32_t status = (uint32_t)-1; int retval = jtagspi_read_status(bank, &status); if (retval != ERROR_OK) return retval; if ((status & SPIFLASH_WE_BIT) == 0) { - LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status); + LOG_ERROR("Cannot enable write to flash. Status=0x%02" PRIx32, status); return ERROR_FAIL; } return ERROR_OK; @@ -287,28 +522,51 @@ static int jtagspi_bulk_erase(struct flash_bank *bank) int retval; int64_t t0 = timeval_ms(); - if (info->dev->chip_erase_cmd == 0x00) + if (info->dev.chip_erase_cmd == 0x00) return ERROR_FLASH_OPER_UNSUPPORTED; retval = jtagspi_write_enable(bank); if (retval != ERROR_OK) return retval; - jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0); - retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT); + + jtagspi_cmd(bank, info->dev.chip_erase_cmd, NULL, 0, NULL, 0); + if (retval != ERROR_OK) + return retval; + + retval = jtagspi_wait(bank, bank->num_sectors * JTAGSPI_MAX_TIMEOUT); LOG_INFO("took %" PRId64 " ms", timeval_ms() - t0); return retval; } +static uint8_t *fill_addr(uint32_t addr, unsigned int addr_len, uint8_t *buffer) +{ + for (buffer += addr_len; addr_len > 0; --addr_len) { + *--buffer = addr; + addr >>= 8; + } + + return buffer; +} + static int jtagspi_sector_erase(struct flash_bank *bank, unsigned int sector) { struct jtagspi_flash_bank *info = bank->driver_priv; int retval; + uint8_t addr[sizeof(uint32_t)]; int64_t t0 = timeval_ms(); retval = jtagspi_write_enable(bank); if (retval != ERROR_OK) return retval; - jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0); + + /* ATXP032/064/128 use always 4-byte addresses except for 0x03 read */ + unsigned int addr_len = info->always_4byte ? 4 : info->addr_len; + + retval = jtagspi_cmd(bank, info->dev.erase_cmd, fill_addr(bank->sectors[sector].offset, addr_len, addr), + addr_len, NULL, 0); + if (retval != ERROR_OK) + return retval; + retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT); LOG_INFO("sector %u took %" PRId64 " ms", sector, timeval_ms() - t0); return retval; @@ -339,8 +597,9 @@ static int jtagspi_erase(struct flash_bank *bank, unsigned int first, } } - if (first == 0 && last == (bank->num_sectors - 1) - && info->dev->chip_erase_cmd != info->dev->erase_cmd) { + if (first == 0 && last == (bank->num_sectors - 1) && + info->dev.chip_erase_cmd != 0x00 && + info->dev.chip_erase_cmd != info->dev.erase_cmd) { LOG_DEBUG("Trying bulk erase."); retval = jtagspi_bulk_erase(bank); if (retval == ERROR_OK) @@ -349,7 +608,7 @@ static int jtagspi_erase(struct flash_bank *bank, unsigned int first, LOG_WARNING("Bulk flash erase failed. Falling back to sector erase."); } - if (info->dev->erase_cmd == 0x00) + if (info->dev.erase_cmd == 0x00) return ERROR_FLASH_OPER_UNSUPPORTED; for (unsigned int sector = first; sector <= last; sector++) { @@ -374,49 +633,93 @@ static int jtagspi_protect(struct flash_bank *bank, int set, unsigned int first, static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct jtagspi_flash_bank *info = bank->driver_priv; + uint32_t pagesize, currsize; + uint8_t addr[sizeof(uint32_t)]; + int retval; if (!(info->probed)) { - LOG_ERROR("Flash bank not yet probed."); + LOG_ERROR("Flash bank not probed."); return ERROR_FLASH_BANK_NOT_PROBED; } - jtagspi_cmd(bank, SPIFLASH_READ, &offset, buffer, -count*8); + /* if no sectorsize, use reasonable default */ + pagesize = info->dev.sectorsize ? info->dev.sectorsize : info->dev.pagesize; + if (pagesize == 0) + pagesize = (info->dev.size_in_bytes <= SPIFLASH_DEF_PAGESIZE) ? + info->dev.size_in_bytes : SPIFLASH_DEF_PAGESIZE; + + /* ATXP032/064/128 use always 4-byte addresses except for 0x03 read */ + unsigned int addr_len = ((info->dev.read_cmd != 0x03) && info->always_4byte) ? 4 : info->addr_len; + + while (count > 0) { + /* length up to end of current page */ + currsize = ((offset + pagesize) & ~(pagesize - 1)) - offset; + /* but no more than remaining size */ + currsize = (count < currsize) ? count : currsize; + + retval = jtagspi_cmd(bank, info->dev.read_cmd, fill_addr(offset, addr_len, addr), + addr_len, buffer, -currsize); + if (retval != ERROR_OK) { + LOG_ERROR("page read error"); + return retval; + } + LOG_DEBUG("read page at 0x%08" PRIx32, offset); + offset += currsize; + buffer += currsize; + count -= currsize; + } return ERROR_OK; } static int jtagspi_page_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { + struct jtagspi_flash_bank *info = bank->driver_priv; + uint8_t addr[sizeof(uint32_t)]; int retval; retval = jtagspi_write_enable(bank); if (retval != ERROR_OK) return retval; - jtagspi_cmd(bank, SPIFLASH_PAGE_PROGRAM, &offset, (uint8_t *) buffer, count*8); + + /* ATXP032/064/128 use always 4-byte addresses except for 0x03 read */ + unsigned int addr_len = ((info->dev.read_cmd != 0x03) && info->always_4byte) ? 4 : info->addr_len; + + retval = jtagspi_cmd(bank, info->dev.pprog_cmd, fill_addr(offset, addr_len, addr), + addr_len, (uint8_t *) buffer, count); + if (retval != ERROR_OK) + return retval; return jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT); } static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct jtagspi_flash_bank *info = bank->driver_priv; + uint32_t pagesize, currsize; int retval; - uint32_t n, pagesize; if (!(info->probed)) { - LOG_ERROR("Flash bank not yet probed."); + LOG_ERROR("Flash bank not probed."); return ERROR_FLASH_BANK_NOT_PROBED; } /* if no write pagesize, use reasonable default */ - pagesize = info->dev->pagesize ? info->dev->pagesize : SPIFLASH_DEF_PAGESIZE; + pagesize = info->dev.pagesize ? info->dev.pagesize : SPIFLASH_DEF_PAGESIZE; - for (n = 0; n < count; n += pagesize) { - retval = jtagspi_page_write(bank, buffer + n, offset + n, - MIN(count - n, pagesize)); + while (count > 0) { + /* length up to end of current page */ + currsize = ((offset + pagesize) & ~(pagesize - 1)) - offset; + /* but no more than remaining size */ + currsize = (count < currsize) ? count : currsize; + + retval = jtagspi_page_write(bank, buffer, offset, currsize); if (retval != ERROR_OK) { LOG_ERROR("page write error"); return retval; } - LOG_DEBUG("wrote page at 0x%08" PRIx32, offset + n); + LOG_DEBUG("wrote page at 0x%08" PRIx32, offset); + offset += currsize; + buffer += currsize; + count -= currsize; } return ERROR_OK; } @@ -430,22 +733,72 @@ static int jtagspi_info(struct flash_bank *bank, struct command_invocation *cmd) return ERROR_OK; } - command_print_sameline(cmd, "\nSPIFI flash information:\n" - " Device \'%s\' (ID 0x%08" PRIx32 ")\n", - info->dev->name, info->dev->device_id); + command_print_sameline(cmd, "flash \'%s\', device id = 0x%06" PRIx32 + ", flash size = %" PRIu32 " %sbytes\n(page size = %" PRIu32 + ", read = 0x%02" PRIx8 ", qread = 0x%02" PRIx8 + ", pprog = 0x%02" PRIx8 ", mass_erase = 0x%02" PRIx8 + ", sector size = %" PRIu32 " %sbytes, sector_erase = 0x%02" PRIx8 ")", + info->dev.name, info->dev.device_id & 0xFFFFFF, + bank->size / 4096 ? bank->size / 1024 : bank->size, + bank->size / 4096 ? "k" : "", info->dev.pagesize, + info->dev.read_cmd, info->dev.qread_cmd, + info->dev.pprog_cmd, info->dev.chip_erase_cmd, + info->dev.sectorsize / 4096 ? + info->dev.sectorsize / 1024 : info->dev.sectorsize, + info->dev.sectorsize / 4096 ? "k" : "", + info->dev.erase_cmd); return ERROR_OK; } +static const struct command_registration jtagspi_exec_command_handlers[] = { + { + .name = "set", + .handler = jtagspi_handle_set, + .mode = COMMAND_EXEC, + .usage = "bank_id name chip_size page_size read_cmd unused pprg_cmd " + "[ mass_erase_cmd ] [ sector_size sector_erase_cmd ]", + .help = "Set device parameters if not autodetected.", + }, + { + .name = "cmd", + .handler = jtagspi_handle_cmd, + .mode = COMMAND_EXEC, + .usage = "bank_id num_resp cmd_byte ...", + .help = "Send low-level command cmd_byte and following bytes, read num_bytes.", + }, + { + .name = "always_4byte", + .handler = jtagspi_handle_always_4byte, + .mode = COMMAND_EXEC, + .usage = "bank_id [ on | off ]", + .help = "Use always 4-byte address except for basic 0x03.", + }, + + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration jtagspi_command_handlers[] = { + { + .name = "jtagspi", + .mode = COMMAND_ANY, + .help = "jtagspi command group", + .usage = "", + .chain = jtagspi_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + const struct flash_driver jtagspi_flash = { .name = "jtagspi", + .commands = jtagspi_command_handlers, .flash_bank_command = jtagspi_flash_bank_command, .erase = jtagspi_erase, .protect = jtagspi_protect, .write = jtagspi_write, .read = jtagspi_read, .probe = jtagspi_probe, - .auto_probe = jtagspi_probe, + .auto_probe = jtagspi_auto_probe, .erase_check = default_flash_blank_check, .info = jtagspi_info, .free_driver_priv = default_flash_free_driver_priv, diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index d3a4b3702..198dff5c8 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -1015,7 +1015,7 @@ static const struct command_registration psoc6_exec_command_handlers[] = { .name = "reset_halt", .handler = psoc6_handle_reset_halt, .mode = COMMAND_EXEC, - .usage = NULL, + .usage = "", .help = "Tries to simulate broken Vector Catch", }, COMMAND_REGISTRATION_DONE diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 5b4c16bb9..fb34172d2 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -441,7 +441,6 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) 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, diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 3bda9bc20..90cee6412 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -640,6 +640,9 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) case CORTEX_M4_PARTNO: /* STM32F3x devices */ device_id_register = 0xE0042000; break; + case CORTEX_M23_PARTNO: /* GD32E23x devices */ + device_id_register = 0x40015800; + break; default: LOG_ERROR("Cannot identify target as a stm32x"); return ERROR_FAIL; @@ -674,6 +677,9 @@ static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_i case CORTEX_M4_PARTNO: /* STM32F3x devices */ flash_size_reg = 0x1FFFF7CC; break; + case CORTEX_M23_PARTNO: /* GD32E23x devices */ + flash_size_reg = 0x1FFFF7E0; + break; default: LOG_ERROR("Cannot identify target as a stm32x"); return ERROR_FAIL; @@ -756,8 +762,8 @@ 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, + /* GigaDevice GD32F1x0 & GD32F3x0 & GD32E23x 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 @@ -774,6 +780,11 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->user_data_offset = 16; stm32x_info->option_offset = 6; break; + case 0x1909: /* gd32e23x */ + stm32x_info->user_data_offset = 16; + stm32x_info->option_offset = 6; + max_flash_size_in_kb = 64; + break; } break; case 0x412: /* stm32f1x low-density */ @@ -984,6 +995,10 @@ static int get_stm32x_info(struct flash_bank *bank, struct command_invocation *c device_str = "GD32F3x0"; break; + case 0x1909: /* gd32e23x */ + device_str = "GD32E23x"; + break; + case 0x2000: rev_str = "B"; break; @@ -1530,7 +1545,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) return retval; } -static const struct command_registration stm32x_exec_command_handlers[] = { +static const struct command_registration stm32f1x_exec_command_handlers[] = { { .name = "lock", .handler = stm32x_handle_lock_command, @@ -1578,20 +1593,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const struct command_registration stm32x_command_handlers[] = { +static const struct command_registration stm32f1x_command_handlers[] = { { .name = "stm32f1x", .mode = COMMAND_ANY, .help = "stm32f1x flash command group", .usage = "", - .chain = stm32x_exec_command_handlers, + .chain = stm32f1x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; const struct flash_driver stm32f1x_flash = { .name = "stm32f1x", - .commands = stm32x_command_handlers, + .commands = stm32f1x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, .erase = stm32x_erase, .protect = stm32x_protect, diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index e80928ddf..d3e7d709c 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -1747,7 +1747,7 @@ COMMAND_HANDLER(stm32x_handle_otp_command) return retval; } -static const struct command_registration stm32x_exec_command_handlers[] = { +static const struct command_registration stm32f2x_exec_command_handlers[] = { { .name = "lock", .handler = stm32x_handle_lock_command, @@ -1800,20 +1800,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const struct command_registration stm32x_command_handlers[] = { +static const struct command_registration stm32f2x_command_handlers[] = { { .name = "stm32f2x", .mode = COMMAND_ANY, .help = "stm32f2x flash command group", .usage = "", - .chain = stm32x_exec_command_handlers, + .chain = stm32f2x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; const struct flash_driver stm32f2x_flash = { .name = "stm32f2x", - .commands = stm32x_command_handlers, + .commands = stm32f2x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, .erase = stm32x_erase, .protect = stm32x_protect, diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index 89ba75dad..d3f17b2b1 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -21,7 +21,7 @@ #include "imp.h" #include #include -#include +#include /* Erase time can be as high as 1000ms, 10x this and it's toast... */ @@ -100,6 +100,11 @@ #define FLASH_REG_BASE_B0 0x52002000 #define FLASH_REG_BASE_B1 0x52002100 +/* Supported device IDs */ +#define DEVID_STM32H74_H75XX 0x450 +#define DEVID_STM32H7A_H7BXX 0x480 +#define DEVID_STM32H72_H73XX 0x483 + struct stm32h7x_rev { uint16_t rev; const char *str; @@ -139,24 +144,24 @@ enum stm32h7x_opt_rdp { OPT_RDP_L2 = 0xcc }; -static const struct stm32h7x_rev stm32_450_revs[] = { +static const struct stm32h7x_rev stm32h74_h75xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2001, "X" }, { 0x2003, "V" }, }; -static const struct stm32h7x_rev stm32_480_revs[] = { +static const struct stm32h7x_rev stm32h7a_h7bxx_revs[] = { { 0x1000, "A"}, }; -static const struct stm32h7x_rev stm32_483_revs[] = { +static const struct stm32h7x_rev stm32h72_h73xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, }; -static uint32_t stm32x_compute_flash_cr_450_483(uint32_t cmd, int snb) +static uint32_t stm32h74_h75xx_compute_flash_cr(uint32_t cmd, int snb) { return cmd | (snb << 8); } -static uint32_t stm32x_compute_flash_cr_480(uint32_t cmd, int snb) +static uint32_t stm32h7a_h7bxx_compute_flash_cr(uint32_t cmd, int snb) { /* save FW and START bits, to be right shifted by 2 bits later */ const uint32_t tmp = cmd & (FLASH_FW | FLASH_START); @@ -169,9 +174,9 @@ static uint32_t stm32x_compute_flash_cr_480(uint32_t cmd, int snb) static const struct stm32h7x_part_info stm32h7x_parts[] = { { - .id = 0x450, - .revs = stm32_450_revs, - .num_revs = ARRAY_SIZE(stm32_450_revs), + .id = DEVID_STM32H74_H75XX, + .revs = stm32h74_h75xx_revs, + .num_revs = ARRAY_SIZE(stm32h74_h75xx_revs), .device_str = "STM32H74x/75x", .page_size_kb = 128, .block_size = 32, @@ -181,12 +186,12 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = { .fsize_addr = 0x1FF1E880, .wps_group_size = 1, .wps_mask = 0xFF, - .compute_flash_cr = stm32x_compute_flash_cr_450_483, + .compute_flash_cr = stm32h74_h75xx_compute_flash_cr, }, { - .id = 0x480, - .revs = stm32_480_revs, - .num_revs = ARRAY_SIZE(stm32_480_revs), + .id = DEVID_STM32H7A_H7BXX, + .revs = stm32h7a_h7bxx_revs, + .num_revs = ARRAY_SIZE(stm32h7a_h7bxx_revs), .device_str = "STM32H7Ax/7Bx", .page_size_kb = 8, .block_size = 16, @@ -196,12 +201,12 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = { .fsize_addr = 0x08FFF80C, .wps_group_size = 4, .wps_mask = 0xFFFFFFFF, - .compute_flash_cr = stm32x_compute_flash_cr_480, + .compute_flash_cr = stm32h7a_h7bxx_compute_flash_cr, }, { - .id = 0x483, - .revs = stm32_483_revs, - .num_revs = ARRAY_SIZE(stm32_483_revs), + .id = DEVID_STM32H72_H73XX, + .revs = stm32h72_h73xx_revs, + .num_revs = ARRAY_SIZE(stm32h72_h73xx_revs), .device_str = "STM32H72x/73x", .page_size_kb = 128, .block_size = 32, @@ -211,7 +216,7 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = { .fsize_addr = 0x1FF1E880, .wps_group_size = 1, .wps_mask = 0xFF, - .compute_flash_cr = stm32x_compute_flash_cr_450_483, + .compute_flash_cr = stm32h74_h75xx_compute_flash_cr, }, }; @@ -754,6 +759,7 @@ static int stm32x_read_id_code(struct flash_bank *bank, uint32_t *id) static int stm32x_probe(struct flash_bank *bank) { struct target *target = bank->target; + struct cortex_m_common *cortex_m = target_to_cm(target); struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv; uint16_t flash_size_in_kb; uint32_t device_id; @@ -792,15 +798,19 @@ static int stm32x_probe(struct flash_bank *bank) LOG_DEBUG("flash_regs_base: 0x%" PRIx32, stm32x_info->flash_regs_base); /* get flash size from target */ - retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb); + /* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */ + retval = ERROR_FAIL; + if (device_id == DEVID_STM32H74_H75XX && cortex_m->core_info->partno == CORTEX_M4_PARTNO) + LOG_WARNING("%s cannot read the flash size register", target_name(target)); + else + retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb); + if (retval != ERROR_OK) { /* read error when device has invalid value, set max flash size */ flash_size_in_kb = stm32x_info->part_info->max_flash_size_kb; + LOG_INFO("assuming %" PRIu16 "k flash", flash_size_in_kb); } else - LOG_INFO("flash size probed value %" PRIu16, flash_size_in_kb); - - - + LOG_INFO("flash size probed value %" PRIu16 "k", flash_size_in_kb); /* setup bank size */ const uint32_t bank1_base = FLASH_BANK0_ADDRESS; @@ -808,8 +818,8 @@ static int stm32x_probe(struct flash_bank *bank) bool has_dual_bank = stm32x_info->part_info->has_dual_bank; switch (device_id) { - case 0x450: - case 0x480: + case DEVID_STM32H74_H75XX: + case DEVID_STM32H7A_H7BXX: /* For STM32H74x/75x and STM32H7Ax/Bx * - STM32H7xxxI devices contains dual bank, 1 Mbyte each * - STM32H7xxxG devices contains dual bank, 512 Kbyte each @@ -822,7 +832,7 @@ static int stm32x_probe(struct flash_bank *bank) /* flash size is 2M or 1M */ flash_size_in_kb /= 2; break; - case 0x483: + case DEVID_STM32H72_H73XX: break; default: LOG_ERROR("unsupported device"); @@ -1141,7 +1151,7 @@ COMMAND_HANDLER(stm32x_handle_option_write_command) return stm32x_modify_option(bank, reg_offset, value, mask); } -static const struct command_registration stm32x_exec_command_handlers[] = { +static const struct command_registration stm32h7x_exec_command_handlers[] = { { .name = "lock", .handler = stm32x_handle_lock_command, @@ -1180,20 +1190,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const struct command_registration stm32x_command_handlers[] = { +static const struct command_registration stm32h7x_command_handlers[] = { { .name = "stm32h7x", .mode = COMMAND_ANY, .help = "stm32h7x flash command group", .usage = "", - .chain = stm32x_exec_command_handlers, + .chain = stm32h7x_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; const struct flash_driver stm32h7x_flash = { .name = "stm32h7x", - .commands = stm32x_command_handlers, + .commands = stm32h7x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, .erase = stm32x_erase, .protect = stm32x_protect, diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 585914de2..f6a8ffceb 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -425,12 +425,12 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; uint32_t hp_nb = stm32lx_info->part_info.page_size / 2; - uint32_t buffer_size = 16384; + uint32_t buffer_size = (16384 / hp_nb) * hp_nb; /* must be multiple of hp_nb */ struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; - struct reg_param reg_params[3]; + struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; @@ -440,6 +440,10 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff }; /* Make sure we're performing a half-page aligned write. */ + if (offset % hp_nb) { + LOG_ERROR("The offset must be %" PRIu32 "B-aligned but it is %" PRIi32 "B)", hp_nb, offset); + return ERROR_FAIL; + } if (count % hp_nb) { LOG_ERROR("The byte count must be %" PRIu32 "B-aligned but count is %" PRIu32 "B)", hp_nb, count); return ERROR_FAIL; @@ -476,6 +480,9 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } else { + /* Make sure we're still asking for an integral number of half-pages */ + buffer_size -= buffer_size % hp_nb; } } @@ -484,6 +491,8 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* Enable half-page write */ retval = stm32lx_enable_write_half_page(bank); @@ -494,6 +503,8 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); return retval; } @@ -524,8 +535,12 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff buf_set_u32(reg_params[0].value, 0, 32, address); /* The source address of the copy (R1) */ buf_set_u32(reg_params[1].value, 0, 32, source->address); - /* The length of the copy (R2) */ - buf_set_u32(reg_params[2].value, 0, 32, this_count / 4); + /* The number of half pages to copy (R2) */ + buf_set_u32(reg_params[2].value, 0, 32, this_count / hp_nb); + /* The size in byes of a half page (R3) */ + buf_set_u32(reg_params[3].value, 0, 32, hp_nb); + /* The flash base address (R4) */ + buf_set_u32(reg_params[4].value, 0, 32, stm32lx_info->flash_base); /* 5: Execute the bunch of code */ retval = target_run_algorithm(target, 0, NULL, @@ -593,6 +608,8 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); return retval; } diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index fceb1e3f7..05db31435 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1285,8 +1285,7 @@ COMMAND_HANDLER(handle_flash_bank_command) /* register flash specific commands */ if (driver->commands) { - int retval = register_commands(CMD_CTX, NULL, - driver->commands); + int retval = register_commands(CMD_CTX, NULL, driver->commands); if (retval != ERROR_OK) { LOG_ERROR("couldn't register '%s' commands", driver_name); diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl index 93ef82ce6..16cbe1950 100644 --- a/src/flash/startup.tcl +++ b/src/flash/startup.tcl @@ -121,3 +121,6 @@ proc stm32l5x args { eval stm32l4x $args } proc stm32u5x args { eval stm32l4x $args } proc stm32wbx args { eval stm32l4x $args } proc stm32wlx args { eval stm32l4x $args } + +# gd32e23x uses the same flash driver as the stm32f1x +proc gd32e23x args { eval stm32f1x $args } diff --git a/src/helper/command.c b/src/helper/command.c index 7c29f73e6..53ee2508a 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -137,41 +137,6 @@ static void command_log_capture_finish(struct log_capture_state *state) free(state); } -/* - * FIXME: workaround for memory leak in jimtcl 0.80 - * Jim API Jim_CreateCommand() converts the command name in a Jim object and - * does not free the object. Fixed for jimtcl 0.81 by e4416cf86f0b - * Use the internal jimtcl API Jim_CreateCommandObj, not exported by jim.h, - * and override the bugged API through preprocessor's macro. - * This workaround works only when jimtcl is compiled as OpenOCD submodule. - * It's broken on macOS, so it's currently restricted on Linux only. - * If jimtcl is linked-in from a precompiled library, either static or dynamic, - * the symbol Jim_CreateCommandObj is not exported and the build will use the - * bugged API. - * To be removed when OpenOCD will switch to jimtcl 0.81 - */ -#if JIM_VERSION == 80 && defined __linux__ -static int workaround_createcommand(Jim_Interp *interp, const char *cmdName, - Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc); -int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj, - Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) -__attribute__((weak, alias("workaround_createcommand"))); -static int workaround_createcommand(Jim_Interp *interp, const char *cmdName, - Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) -{ - if ((void *)Jim_CreateCommandObj == (void *)workaround_createcommand) - return Jim_CreateCommand(interp, cmdName, cmdProc, privData, delProc); - - Jim_Obj *cmd_name = Jim_NewStringObj(interp, cmdName, -1); - Jim_IncrRefCount(cmd_name); - int retval = Jim_CreateCommandObj(interp, cmd_name, cmdProc, privData, delProc); - Jim_DecrRefCount(interp, cmd_name); - return retval; -} -#define Jim_CreateCommand workaround_createcommand -#endif /* JIM_VERSION == 80 && defined __linux__*/ -/* FIXME: end of workaround for memory leak in jimtcl 0.80 */ - static int command_retval_set(Jim_Interp *interp, int retval) { int *return_retval = Jim_GetAssocData(interp, "retval"); diff --git a/src/helper/log.h b/src/helper/log.h index 34ff835b8..621d467b4 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -143,6 +143,23 @@ extern int debug_level; #define LOG_OUTPUT(expr ...) \ log_printf(LOG_LVL_OUTPUT, __FILE__, __LINE__, __func__, expr) +/* Output a log entry that is related to a given target */ + +#define LOG_TARGET_DEBUG_IO(target, fmt_str, ...) \ + LOG_DEBUG_IO("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + +#define LOG_TARGET_DEBUG(target, fmt_str, ...) \ + LOG_DEBUG("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + +#define LOG_TARGET_INFO(target, fmt_str, ...) \ + LOG_INFO("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + +#define LOG_TARGET_WARNING(target, fmt_str, ...) \ + LOG_WARNING("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + +#define LOG_TARGET_ERROR(target, fmt_str, ...) \ + LOG_ERROR("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + /* general failures * error codes < 100 */ diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index 4ed5e7aa0..23424f5a2 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -1,6 +1,5 @@ noinst_LTLIBRARIES += %D%/libjtag.la -JTAG_SRCS = %D%/commands.c %C%_libjtag_la_LIBADD = if HLADAPTER @@ -18,20 +17,20 @@ include %D%/drivers/Makefile.am %C%_libjtag_la_SOURCES = \ %D%/adapter.c \ + %D%/adapter.h \ + %D%/commands.c \ %D%/core.c \ %D%/interface.c \ %D%/interfaces.c \ %D%/tcl.c \ %D%/swim.c \ %D%/commands.h \ - %D%/driver.h \ %D%/interface.h \ %D%/interfaces.h \ %D%/minidriver.h \ %D%/jtag.h \ %D%/swd.h \ %D%/swim.h \ - %D%/tcl.h \ - $(JTAG_SRCS) + %D%/tcl.h STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 578160106..1c34a26c3 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -1,41 +1,22 @@ -/*************************************************************************** - * Copyright (C) 2005 by Dominic Rath * - * Dominic.Rath@gmx.de * - * * - * Copyright (C) 2007-2010 Øyvind Harboe * - * oyvind.harboe@zylin.com * - * * - * Copyright (C) 2009 SoftPLC Corporation * - * http://softplc.com * - * dick@softplc.com * - * * - * Copyright (C) 2009 Zachary T Welch * - * zw@superlucidity.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2005 by Dominic Rath + * Copyright (C) 2007-2010 Øyvind Harboe + * Copyright (C) 2009 SoftPLC Corporation, http://softplc.com, Dick Hollenbeck + * Copyright (C) 2009 Zachary T Welch + * Copyright (C) 2018 Pengutronix, Oleksij Rempel + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "adapter.h" #include "jtag.h" #include "minidriver.h" #include "interface.h" #include "interfaces.h" #include -#include /** * @file @@ -45,6 +26,281 @@ struct adapter_driver *adapter_driver; const char * const jtag_only[] = { "jtag", NULL }; +enum adapter_clk_mode { + CLOCK_MODE_UNSELECTED = 0, + CLOCK_MODE_KHZ, + CLOCK_MODE_RCLK +}; + +/** + * Adapter configuration + */ +static struct { + bool adapter_initialized; + char *usb_location; + char *serial; + enum adapter_clk_mode clock_mode; + int speed_khz; + int rclk_fallback_speed_khz; +} adapter_config; + +bool is_adapter_initialized(void) +{ + return adapter_config.adapter_initialized; +} + +/** + * Do low-level setup like initializing registers, output signals, + * and clocking. + */ +int adapter_init(struct command_context *cmd_ctx) +{ + if (is_adapter_initialized()) + return ERROR_OK; + + if (!adapter_driver) { + /* nothing was previously specified by "adapter driver" command */ + LOG_ERROR("Debug Adapter has to be specified, " + "see \"adapter driver\" command"); + return ERROR_JTAG_INVALID_INTERFACE; + } + + int retval; + retval = adapter_driver->init(); + if (retval != ERROR_OK) + return retval; + adapter_config.adapter_initialized = true; + + if (!adapter_driver->speed) { + LOG_INFO("This adapter doesn't support configurable speed"); + return ERROR_OK; + } + + if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) { + LOG_ERROR("An adapter speed is not selected in the init script." + " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed."); + return ERROR_JTAG_INIT_FAILED; + } + + int requested_khz = adapter_get_speed_khz(); + int actual_khz = requested_khz; + int speed_var = 0; + retval = adapter_get_speed(&speed_var); + if (retval != ERROR_OK) + return retval; + retval = adapter_driver->speed(speed_var); + if (retval != ERROR_OK) + return retval; + retval = adapter_get_speed_readable(&actual_khz); + if (retval != ERROR_OK) + LOG_INFO("adapter-specific clock speed value %d", speed_var); + else if (actual_khz) { + /* Adaptive clocking -- JTAG-specific */ + if ((adapter_config.clock_mode == CLOCK_MODE_RCLK) + || ((adapter_config.clock_mode == CLOCK_MODE_KHZ) && !requested_khz)) { + LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz" + , actual_khz); + } else + LOG_INFO("clock speed %d kHz", actual_khz); + } else + LOG_INFO("RCLK (adaptive clock speed)"); + + return ERROR_OK; +} + +int adapter_quit(void) +{ + if (is_adapter_initialized() && adapter_driver->quit) { + /* close the JTAG interface */ + int result = adapter_driver->quit(); + if (result != ERROR_OK) + LOG_ERROR("failed: %d", result); + } + + free(adapter_config.serial); + free(adapter_config.usb_location); + + struct jtag_tap *t = jtag_all_taps(); + while (t) { + struct jtag_tap *n = t->next_tap; + jtag_tap_free(t); + t = n; + } + + return ERROR_OK; +} + +unsigned int adapter_get_speed_khz(void) +{ + return adapter_config.speed_khz; +} + +static int adapter_khz_to_speed(unsigned int khz, int *speed) +{ + LOG_DEBUG("convert khz to adapter specific speed value"); + adapter_config.speed_khz = khz; + if (!is_adapter_initialized()) + return ERROR_OK; + LOG_DEBUG("have adapter set up"); + if (!adapter_driver->khz) { + LOG_ERROR("Translation from khz to adapter speed not implemented"); + return ERROR_FAIL; + } + int speed_div1; + int retval = adapter_driver->khz(adapter_get_speed_khz(), &speed_div1); + if (retval != ERROR_OK) + return retval; + *speed = speed_div1; + return ERROR_OK; +} + +static int adapter_rclk_to_speed(unsigned int fallback_speed_khz, int *speed) +{ + int retval = adapter_khz_to_speed(0, speed); + if ((retval != ERROR_OK) && fallback_speed_khz) { + LOG_DEBUG("trying fallback speed..."); + retval = adapter_khz_to_speed(fallback_speed_khz, speed); + } + return retval; +} + +static int adapter_set_speed(int speed) +{ + /* this command can be called during CONFIG, + * in which case adapter isn't initialized */ + return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK; +} + +int adapter_config_khz(unsigned int khz) +{ + LOG_DEBUG("handle adapter khz"); + adapter_config.clock_mode = CLOCK_MODE_KHZ; + int speed = 0; + int retval = adapter_khz_to_speed(khz, &speed); + return (retval != ERROR_OK) ? retval : adapter_set_speed(speed); +} + +int adapter_config_rclk(unsigned int fallback_speed_khz) +{ + LOG_DEBUG("handle adapter rclk"); + adapter_config.clock_mode = CLOCK_MODE_RCLK; + adapter_config.rclk_fallback_speed_khz = fallback_speed_khz; + int speed = 0; + int retval = adapter_rclk_to_speed(fallback_speed_khz, &speed); + return (retval != ERROR_OK) ? retval : adapter_set_speed(speed); +} + +int adapter_get_speed(int *speed) +{ + switch (adapter_config.clock_mode) { + case CLOCK_MODE_KHZ: + adapter_khz_to_speed(adapter_get_speed_khz(), speed); + break; + case CLOCK_MODE_RCLK: + adapter_rclk_to_speed(adapter_config.rclk_fallback_speed_khz, speed); + break; + default: + LOG_ERROR("BUG: unknown adapter clock mode"); + return ERROR_FAIL; + } + return ERROR_OK; +} + +int adapter_get_speed_readable(int *khz) +{ + int speed_var = 0; + int retval = adapter_get_speed(&speed_var); + if (retval != ERROR_OK) + return retval; + if (!is_adapter_initialized()) + return ERROR_OK; + if (!adapter_driver->speed_div) { + LOG_ERROR("Translation from adapter speed to khz not implemented"); + return ERROR_FAIL; + } + return adapter_driver->speed_div(speed_var, khz); +} + +const char *adapter_get_required_serial(void) +{ + return adapter_config.serial; +} + +/* + * 1 char: bus + * 2 * 7 chars: max 7 ports + * 1 char: test for overflow + * ------ + * 16 chars + */ +#define USB_MAX_LOCATION_LENGTH 16 + +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS +static void adapter_usb_set_location(const char *location) +{ + if (strnlen(location, USB_MAX_LOCATION_LENGTH) == USB_MAX_LOCATION_LENGTH) + LOG_WARNING("usb location string is too long!!"); + + free(adapter_config.usb_location); + + adapter_config.usb_location = strndup(location, USB_MAX_LOCATION_LENGTH); +} +#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */ + +const char *adapter_usb_get_location(void) +{ + return adapter_config.usb_location; +} + +bool adapter_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, size_t path_len) +{ + size_t path_step, string_length; + char *ptr, *loc; + bool equal = false; + + if (!adapter_usb_get_location()) + return equal; + + /* strtok need non const char */ + loc = strndup(adapter_usb_get_location(), USB_MAX_LOCATION_LENGTH); + string_length = strnlen(loc, USB_MAX_LOCATION_LENGTH); + + ptr = strtok(loc, "-"); + if (!ptr) { + LOG_WARNING("no '-' in usb path\n"); + goto done; + } + + string_length -= strnlen(ptr, string_length); + /* check bus mismatch */ + if (atoi(ptr) != dev_bus) + goto done; + + path_step = 0; + while (path_step < path_len) { + ptr = strtok(NULL, "."); + + /* no more tokens in path */ + if (!ptr) + break; + + /* path mismatch at some step */ + if (path_step < path_len && atoi(ptr) != port_path[path_step]) + break; + + path_step++; + string_length -= strnlen(ptr, string_length) + 1; + }; + + /* walked the full path, all elements match */ + if (path_step == path_len && !string_length) + equal = true; + +done: + free(loc); + return equal; +} + static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; @@ -114,8 +370,7 @@ COMMAND_HANDLER(handle_adapter_driver_command) continue; if (adapter_drivers[i]->commands) { - retval = register_commands(CMD_CTX, NULL, - adapter_drivers[i]->commands); + retval = register_commands(CMD_CTX, NULL, adapter_drivers[i]->commands); if (retval != ERROR_OK) return retval; } @@ -389,13 +644,13 @@ COMMAND_HANDLER(handle_adapter_speed_command) unsigned khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); - retval = jtag_config_khz(khz); + retval = adapter_config_khz(khz); if (retval != ERROR_OK) return retval; } - int cur_speed = jtag_get_speed_khz(); - retval = jtag_get_speed_readable(&cur_speed); + int cur_speed = adapter_get_speed_khz(); + retval = adapter_get_speed_readable(&cur_speed); if (retval != ERROR_OK) return retval; @@ -407,6 +662,16 @@ COMMAND_HANDLER(handle_adapter_speed_command) return retval; } +COMMAND_HANDLER(handle_adapter_serial_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + free(adapter_config.serial); + adapter_config.serial = strdup(CMD_ARGV[0]); + return ERROR_OK; +} + COMMAND_HANDLER(handle_adapter_reset_de_assert) { enum values { @@ -497,9 +762,9 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert) COMMAND_HANDLER(handle_usb_location_command) { if (CMD_ARGC == 1) - jtag_usb_set_location(CMD_ARGV[0]); + adapter_usb_set_location(CMD_ARGV[0]); - command_print(CMD, "adapter usb location: %s", jtag_usb_get_location()); + command_print(CMD, "adapter usb location: %s", adapter_usb_get_location()); return ERROR_OK; } @@ -554,6 +819,13 @@ static const struct command_registration adapter_command_handlers[] = { "With or without argument, display current setting.", .usage = "[khz]", }, + { + .name = "serial", + .handler = handle_adapter_serial_command, + .mode = COMMAND_CONFIG, + .help = "Set the serial number of the adapter", + .usage = "serial_string", + }, { .name = "list", .handler = handle_adapter_list_command, @@ -635,7 +907,7 @@ static const struct command_registration interface_command_handlers[] = { * @todo Remove internal assumptions that all debug adapters use JTAG for * transport. Various types and data structures are not named generically. */ -int interface_register_commands(struct command_context *ctx) +int adapter_register_commands(struct command_context *ctx) { return register_commands(ctx, NULL, interface_command_handlers); } diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h new file mode 100644 index 000000000..300769c22 --- /dev/null +++ b/src/jtag/adapter.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2005 by Dominic Rath + * Copyright (c) 2018 Pengutronix, Oleksij Rempel + */ + +#ifndef OPENOCD_JTAG_ADAPTER_H +#define OPENOCD_JTAG_ADAPTER_H + +#include +#include +#include + +struct command_context; + +/** Register the adapter's commands */ +int adapter_register_commands(struct command_context *ctx); + +/** Initialize debug adapter upon startup. */ +int adapter_init(struct command_context *cmd_ctx); + +/** Shutdown the debug adapter upon program exit. */ +int adapter_quit(void); + +/** @returns true if adapter has been initialized */ +bool is_adapter_initialized(void); + +/** @returns USB location string set with command 'adapter usb location' */ +const char *adapter_usb_get_location(void); + +/** @returns true if USB location string is "-[.[...]]" */ +bool adapter_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, size_t path_len); + +/** @returns The current adapter speed setting. */ +int adapter_get_speed(int *speed); + +/** + * Given a @a speed setting, use the interface @c speed_div callback to + * adjust the setting. + * @param speed The speed setting to convert back to readable kHz. + * @returns ERROR_OK if the interface has not been initialized or on success; + * otherwise, the error code produced by the @c speed_div callback. + */ +int adapter_get_speed_readable(int *speed); + +/** Attempt to configure the adapter for the specified kHz. */ +int adapter_config_khz(unsigned int khz); + +/** + * Attempt to enable RTCK/RCLK. If that fails, fallback to the + * specified frequency. + */ +int adapter_config_rclk(unsigned int fallback_speed_khz); + +/** Retrieves the clock speed of the adapter in kHz. */ +unsigned int adapter_get_speed_khz(void); + +/** Retrieves the serial number set with command 'adapter serial' */ +const char *adapter_get_required_serial(void); + +#endif /* OPENOCD_JTAG_ADAPTER_H */ diff --git a/src/jtag/aice/aice_interface.c b/src/jtag/aice/aice_interface.c index c7556c018..cb126c6b1 100644 --- a/src/jtag/aice/aice_interface.c +++ b/src/jtag/aice/aice_interface.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include #include #include #include @@ -269,7 +270,7 @@ COMMAND_HANDLER(aice_handle_aice_info_command) LOG_DEBUG("aice_handle_aice_info_command"); command_print(CMD, "Description: %s", param.device_desc); - command_print(CMD, "Serial number: %s", param.serial); + command_print(CMD, "Serial number: %s", adapter_get_required_serial()); if (strncmp(aice_port->name, "aice_pipe", 9) == 0) command_print(CMD, "Adapter: %s", param.adapter_name); @@ -308,18 +309,6 @@ COMMAND_HANDLER(aice_handle_aice_desc_command) return ERROR_OK; } -COMMAND_HANDLER(aice_handle_aice_serial_command) -{ - LOG_DEBUG("aice_handle_aice_serial_command"); - - if (CMD_ARGC == 1) - param.serial = strdup(CMD_ARGV[0]); - else - LOG_ERROR("expected exactly one argument to aice serial "); - - return ERROR_OK; -} - COMMAND_HANDLER(aice_handle_aice_vid_pid_command) { LOG_DEBUG("aice_handle_aice_vid_pid_command"); @@ -438,13 +427,6 @@ static const struct command_registration aice_subcommand_handlers[] = { .help = "set the aice device description", .usage = "[description string]", }, - { - .name = "serial", - .handler = &aice_handle_aice_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the AICE device", - .usage = "[serial string]", - }, { .name = "vid_pid", .handler = &aice_handle_aice_vid_pid_command, diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h index d3d6a1a2c..159368888 100644 --- a/src/jtag/aice/aice_port.h +++ b/src/jtag/aice/aice_port.h @@ -107,8 +107,6 @@ struct aice_port_param_s { /** */ const char *device_desc; /** */ - const char *serial; - /** */ uint16_t vid; /** */ uint16_t pid; diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c index 3e9d94219..2f2542e53 100644 --- a/src/jtag/aice/aice_transport.c +++ b/src/jtag/aice/aice_transport.c @@ -284,8 +284,7 @@ static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } /* */ -static const struct command_registration -aice_transport_jtag_subcommand_handlers[] = { +static const struct command_registration aice_transport_jtag_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_ANY, @@ -387,8 +386,7 @@ static const struct command_registration aice_transport_command_handlers[] = { /* */ static int aice_transport_register_commands(struct command_context *cmd_ctx) { - return register_commands(cmd_ctx, NULL, - aice_transport_command_handlers); + return register_commands(cmd_ctx, NULL, aice_transport_command_handlers); } /* */ diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 491406afa..fc46e3722 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -2086,7 +2086,7 @@ static int aice_usb_open(struct aice_port_param_s *param) const uint16_t pids[] = { param->pid, 0 }; struct libusb_device_handle *devh; - if (jtag_libusb_open(vids, pids, NULL, &devh, NULL) != ERROR_OK) + if (jtag_libusb_open(vids, pids, &devh, NULL) != ERROR_OK) return ERROR_FAIL; /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS @@ -2110,7 +2110,7 @@ static int aice_usb_open(struct aice_port_param_s *param) /* reopen jlink after usb_reset * on win32 this may take a second or two to re-enumerate */ int retval; - while ((retval = jtag_libusb_open(vids, pids, NULL, &devh, NULL)) != ERROR_OK) { + while ((retval = jtag_libusb_open(vids, pids, &devh, NULL)) != ERROR_OK) { usleep(1000); timeout--; if (!timeout) diff --git a/src/jtag/core.c b/src/jtag/core.c index 2de5fda47..29ab6cc1c 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -30,6 +30,7 @@ #include "config.h" #endif +#include "adapter.h" #include "jtag.h" #include "swd.h" #include "interface.h" @@ -123,15 +124,6 @@ struct jtag_event_callback { /* callbacks to inform high-level handlers about JTAG state changes */ static struct jtag_event_callback *jtag_event_callbacks; -/* speed in kHz*/ -static int speed_khz; -/* speed to fallback to when RCLK is requested but not supported */ -static int rclk_fallback_speed_khz; -static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; - -/* FIXME: change name to this variable, it is not anymore JTAG only */ -static struct adapter_driver *jtag; - extern struct adapter_driver *adapter_driver; void jtag_set_flush_queue_sleep(int ms) @@ -505,7 +497,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) { int retval; - if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ)) + if (!(adapter_driver->jtag_ops->supported & DEBUG_CAP_TMS_SEQ)) return ERROR_JTAG_NOT_IMPLEMENTED; jtag_checks(); @@ -627,7 +619,7 @@ static int adapter_system_reset(int req_srst) /* Maybe change SRST signal state */ if (jtag_srst != req_srst) { - retval = jtag->reset(0, req_srst); + retval = adapter_driver->reset(0, req_srst); if (retval != ERROR_OK) { LOG_ERROR("SRST error"); return ERROR_FAIL; @@ -764,7 +756,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) int new_srst = 0; int new_trst = 0; - if (!jtag->reset) { + if (!adapter_driver->reset) { legacy_jtag_add_reset(req_tlr_or_trst, req_srst); return; } @@ -813,7 +805,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) /* guarantee jtag queue empty before changing reset status */ jtag_execute_queue(); - retval = jtag->reset(new_trst, new_srst); + retval = adapter_driver->reset(new_trst, new_srst); if (retval != ERROR_OK) { jtag_set_error(retval); LOG_ERROR("TRST/SRST error"); @@ -933,7 +925,7 @@ void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *ma int default_interface_jtag_execute_queue(void) { - if (!jtag) { + if (!is_adapter_initialized()) { LOG_ERROR("No JTAG interface configured yet. " "Issue 'init' command in startup scripts " "before communicating with targets."); @@ -949,11 +941,11 @@ int default_interface_jtag_execute_queue(void) * The fix can be applied immediately after next release (v0.11.0 ?) */ LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface"); - if (!jtag->jtag_ops || !jtag->jtag_ops->execute_queue) + if (!adapter_driver->jtag_ops || !adapter_driver->jtag_ops->execute_queue) return ERROR_OK; } - int result = jtag->jtag_ops->execute_queue(); + int result = adapter_driver->jtag_ops->execute_queue(); struct jtag_command *cmd = jtag_command_queue; while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { @@ -1502,65 +1494,6 @@ void jtag_tap_free(struct jtag_tap *tap) free(tap); } -/** - * Do low-level setup like initializing registers, output signals, - * and clocking. - */ -int adapter_init(struct command_context *cmd_ctx) -{ - if (jtag) - return ERROR_OK; - - if (!adapter_driver) { - /* nothing was previously specified by "adapter driver" command */ - LOG_ERROR("Debug Adapter has to be specified, " - "see \"adapter driver\" command"); - return ERROR_JTAG_INVALID_INTERFACE; - } - - int retval; - retval = adapter_driver->init(); - if (retval != ERROR_OK) - return retval; - jtag = adapter_driver; - - if (!jtag->speed) { - LOG_INFO("This adapter doesn't support configurable speed"); - return ERROR_OK; - } - - if (clock_mode == CLOCK_MODE_UNSELECTED) { - LOG_ERROR("An adapter speed is not selected in the init script." - " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed."); - return ERROR_JTAG_INIT_FAILED; - } - - int requested_khz = jtag_get_speed_khz(); - int actual_khz = requested_khz; - int jtag_speed_var = 0; - retval = jtag_get_speed(&jtag_speed_var); - if (retval != ERROR_OK) - return retval; - retval = jtag->speed(jtag_speed_var); - if (retval != ERROR_OK) - return retval; - retval = jtag_get_speed_readable(&actual_khz); - if (retval != ERROR_OK) - LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var); - else if (actual_khz) { - /* Adaptive clocking -- JTAG-specific */ - if ((clock_mode == CLOCK_MODE_RCLK) - || ((clock_mode == CLOCK_MODE_KHZ) && !requested_khz)) { - LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz" - , actual_khz); - } else - LOG_INFO("clock speed %d kHz", actual_khz); - } else - LOG_INFO("RCLK (adaptive clock speed)"); - - return ERROR_OK; -} - int jtag_init_inner(struct command_context *cmd_ctx) { struct jtag_tap *tap; @@ -1641,25 +1574,6 @@ int jtag_init_inner(struct command_context *cmd_ctx) return ERROR_OK; } -int adapter_quit(void) -{ - if (jtag && jtag->quit) { - /* close the JTAG interface */ - int result = jtag->quit(); - if (result != ERROR_OK) - LOG_ERROR("failed: %d", result); - } - - struct jtag_tap *t = jtag_all_taps(); - while (t) { - struct jtag_tap *n = t->next_tap; - jtag_tap_free(t); - t = n; - } - - return ERROR_OK; -} - int swd_init_reset(struct command_context *cmd_ctx) { int retval, retval1; @@ -1767,97 +1681,6 @@ int jtag_init(struct command_context *cmd_ctx) return ERROR_OK; } -unsigned jtag_get_speed_khz(void) -{ - return speed_khz; -} - -static int adapter_khz_to_speed(unsigned khz, int *speed) -{ - LOG_DEBUG("convert khz to interface specific speed value"); - speed_khz = khz; - if (!jtag) - return ERROR_OK; - LOG_DEBUG("have interface set up"); - if (!jtag->khz) { - LOG_ERROR("Translation from khz to jtag_speed not implemented"); - return ERROR_FAIL; - } - int speed_div1; - int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1); - if (retval != ERROR_OK) - return retval; - *speed = speed_div1; - return ERROR_OK; -} - -static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed) -{ - int retval = adapter_khz_to_speed(0, speed); - if ((retval != ERROR_OK) && fallback_speed_khz) { - LOG_DEBUG("trying fallback speed..."); - retval = adapter_khz_to_speed(fallback_speed_khz, speed); - } - return retval; -} - -static int jtag_set_speed(int speed) -{ - /* this command can be called during CONFIG, - * in which case jtag isn't initialized */ - return jtag ? jtag->speed(speed) : ERROR_OK; -} - -int jtag_config_khz(unsigned khz) -{ - LOG_DEBUG("handle jtag khz"); - clock_mode = CLOCK_MODE_KHZ; - int speed = 0; - int retval = adapter_khz_to_speed(khz, &speed); - return (retval != ERROR_OK) ? retval : jtag_set_speed(speed); -} - -int jtag_config_rclk(unsigned fallback_speed_khz) -{ - LOG_DEBUG("handle jtag rclk"); - clock_mode = CLOCK_MODE_RCLK; - rclk_fallback_speed_khz = fallback_speed_khz; - int speed = 0; - int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed); - return (retval != ERROR_OK) ? retval : jtag_set_speed(speed); -} - -int jtag_get_speed(int *speed) -{ - switch (clock_mode) { - case CLOCK_MODE_KHZ: - adapter_khz_to_speed(jtag_get_speed_khz(), speed); - break; - case CLOCK_MODE_RCLK: - jtag_rclk_to_speed(rclk_fallback_speed_khz, speed); - break; - default: - LOG_ERROR("BUG: unknown jtag clock mode"); - return ERROR_FAIL; - } - return ERROR_OK; -} - -int jtag_get_speed_readable(int *khz) -{ - int jtag_speed_var = 0; - int retval = jtag_get_speed(&jtag_speed_var); - if (retval != ERROR_OK) - return retval; - if (!jtag) - return ERROR_OK; - if (!jtag->speed_div) { - LOG_ERROR("Translation from jtag_speed to khz not implemented"); - return ERROR_FAIL; - } - return jtag->speed_div(jtag_speed_var, khz); -} - void jtag_set_verify(bool enable) { jtag_verify = enable; @@ -1880,14 +1703,14 @@ bool jtag_will_verify_capture_ir(void) int jtag_power_dropout(int *dropout) { - if (!jtag) { + if (!is_adapter_initialized()) { /* TODO: as the jtag interface is not valid all * we can do at the moment is exit OpenOCD */ LOG_ERROR("No Valid JTAG Interface Configured."); exit(-1); } - if (jtag->power_dropout) - return jtag->power_dropout(dropout); + if (adapter_driver->power_dropout) + return adapter_driver->power_dropout(dropout); *dropout = 0; /* by default we can't detect power dropout */ return ERROR_OK; @@ -1895,8 +1718,8 @@ int jtag_power_dropout(int *dropout) int jtag_srst_asserted(int *srst_asserted) { - if (jtag->srst_asserted) - return jtag->srst_asserted(srst_asserted); + if (adapter_driver->srst_asserted) + return adapter_driver->srst_asserted(srst_asserted); *srst_asserted = 0; /* by default we can't detect srst asserted */ return ERROR_OK; @@ -2089,8 +1912,8 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq, unsigned int traceclkin_freq, uint16_t *prescaler) { - if (jtag->config_trace) { - return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq, + if (adapter_driver->config_trace) { + return adapter_driver->config_trace(enabled, pin_protocol, port_size, trace_freq, traceclkin_freq, prescaler); } else if (enabled) { LOG_ERROR("The selected interface does not support tracing"); @@ -2102,8 +1925,8 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, int adapter_poll_trace(uint8_t *buf, size_t *size) { - if (jtag->poll_trace) - return jtag->poll_trace(buf, size); + if (adapter_driver->poll_trace) + return adapter_driver->poll_trace(buf, size); return ERROR_FAIL; } diff --git a/src/jtag/driver.h b/src/jtag/driver.h deleted file mode 100644 index ae00414c4..000000000 --- a/src/jtag/driver.h +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 by Dominic Rath * - * Dominic.Rath@gmx.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************/ - -#ifndef OPENOCD_JTAG_DRIVER_H -#define OPENOCD_JTAG_DRIVER_H - -struct command_context; - -int interface_register_commands(struct command_context *ctx); - -#endif /* OPENOCD_JTAG_DRIVER_H */ diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index da60f366e..c2161523d 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -19,7 +19,6 @@ DRIVERFILES = # Standard Driver: common files DRIVERFILES += %D%/driver.c -DRIVERFILES += %D%/jtag_usb_common.c if USE_LIBUSB1 DRIVERFILES += %D%/libusb_helper.c @@ -187,7 +186,6 @@ endif DRIVERHEADERS = \ %D%/bitbang.h \ %D%/bitq.h \ - %D%/jtag_usb_common.h \ %D%/libftdi_helper.h \ %D%/libusb_helper.h \ %D%/cmsis_dap.h \ diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index e9ff8dfa1..c204f237a 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include #include #if PARPORT_USE_PPDEV == 1 @@ -198,7 +199,7 @@ static void amt_jtagaccel_state_move(void) aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f); AMT_AW(aw_scan_tms_5); int jtag_speed = 0; - int retval = jtag_get_speed(&jtag_speed); + int retval = adapter_get_speed(&jtag_speed); assert(retval == ERROR_OK); if (jtag_speed > 3 || rtck_enabled) amt_wait_scan_busy(); @@ -254,7 +255,7 @@ static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffe uint8_t aw_tms_scan; uint8_t tms_scan[2]; int jtag_speed_var; - int retval = jtag_get_speed(&jtag_speed_var); + int retval = adapter_get_speed(&jtag_speed_var); assert(retval == ERROR_OK); if (ir_scan) diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 5b5a9669e..703378940 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -688,7 +688,7 @@ static struct armjtagew *armjtagew_usb_open(void) const uint16_t pids[] = { USB_PID, 0 }; struct libusb_device_handle *dev; - if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK) + if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK) return NULL; struct armjtagew *result = malloc(sizeof(struct armjtagew)); diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 95e077c33..fd6c28b96 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -198,7 +198,7 @@ static int bcm2835gpio_speed(int speed) static int is_gpio_valid(int gpio) { - return gpio >= 0 && gpio <= 53; + return gpio >= 0 && gpio <= 31; } COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 5c4febb20..898d6d3df 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -434,10 +434,26 @@ static int bitbang_swd_switch_seq(enum swd_special_seq seq) LOG_DEBUG("JTAG-to-SWD"); bitbang_swd_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len); break; + case JTAG_TO_DORMANT: + LOG_DEBUG("JTAG-to-DORMANT"); + bitbang_swd_exchange(false, (uint8_t *)swd_seq_jtag_to_dormant, 0, swd_seq_jtag_to_dormant_len); + break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); bitbang_swd_exchange(false, (uint8_t *)swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len); break; + case SWD_TO_DORMANT: + LOG_DEBUG("SWD-to-DORMANT"); + bitbang_swd_exchange(false, (uint8_t *)swd_seq_swd_to_dormant, 0, swd_seq_swd_to_dormant_len); + break; + case DORMANT_TO_SWD: + LOG_DEBUG("DORMANT-to-SWD"); + bitbang_swd_exchange(false, (uint8_t *)swd_seq_dormant_to_swd, 0, swd_seq_dormant_to_swd_len); + break; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + bitbang_swd_exchange(false, (uint8_t *)swd_seq_dormant_to_jtag, 0, swd_seq_dormant_to_jtag_len); + break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; @@ -465,7 +481,7 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay for (;;) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; - cmd |= SWD_CMD_START | (1 << 7); + cmd |= SWD_CMD_START | SWD_CMD_PARK; bitbang_swd_exchange(false, &cmd, 0, 8); bitbang_interface->swdio_drive(false); @@ -476,38 +492,30 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32); int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1); - LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, + LOG_DEBUG("%s %s read reg %X = %08"PRIx32, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", cmd & SWD_CMD_APNDP ? "AP" : "DP", - cmd & SWD_CMD_RNW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, data); - switch (ack) { - case SWD_ACK_OK: - if (parity != parity_u32(data)) { - LOG_DEBUG("Wrong parity detected"); - queued_retval = ERROR_FAIL; - return; - } - if (value) - *value = data; - if (cmd & SWD_CMD_APNDP) - bitbang_swd_exchange(true, NULL, 0, ap_delay_clk); - return; - case SWD_ACK_WAIT: - LOG_DEBUG("SWD_ACK_WAIT"); + if (ack == SWD_ACK_WAIT) { swd_clear_sticky_errors(); - break; - case SWD_ACK_FAULT: - LOG_DEBUG("SWD_ACK_FAULT"); - queued_retval = ack; - return; - default: - LOG_DEBUG("No valid acknowledge: ack=%d", ack); - queued_retval = ack; + continue; + } else if (ack != SWD_ACK_OK) { + queued_retval = swd_ack_to_error_code(ack); return; } + + if (parity != parity_u32(data)) { + LOG_ERROR("Wrong parity detected"); + queued_retval = ERROR_FAIL; + return; + } + if (value) + *value = data; + if (cmd & SWD_CMD_APNDP) + bitbang_swd_exchange(true, NULL, 0, ap_delay_clk); + return; } } @@ -521,12 +529,15 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay return; } + /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ + bool check_ack = swd_cmd_returns_ack(cmd); + for (;;) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value); buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value)); - cmd |= SWD_CMD_START | (1 << 7); + cmd |= SWD_CMD_START | SWD_CMD_PARK; bitbang_swd_exchange(false, &cmd, 0, 8); bitbang_interface->swdio_drive(false); @@ -535,31 +546,27 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1); int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3); - LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, + + LOG_DEBUG("%s%s %s write reg %X = %08"PRIx32, + check_ack ? "" : "ack ignored ", ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", cmd & SWD_CMD_APNDP ? "AP" : "DP", - cmd & SWD_CMD_RNW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); - switch (ack) { - case SWD_ACK_OK: - if (cmd & SWD_CMD_APNDP) - bitbang_swd_exchange(true, NULL, 0, ap_delay_clk); - return; - case SWD_ACK_WAIT: - LOG_DEBUG("SWD_ACK_WAIT"); - swd_clear_sticky_errors(); - break; - case SWD_ACK_FAULT: - LOG_DEBUG("SWD_ACK_FAULT"); - queued_retval = ack; - return; - default: - LOG_DEBUG("No valid acknowledge: ack=%d", ack); - queued_retval = ack; - return; + if (check_ack) { + if (ack == SWD_ACK_WAIT) { + swd_clear_sticky_errors(); + continue; + } else if (ack != SWD_ACK_OK) { + queued_retval = swd_ack_to_error_code(ack); + return; + } } + + if (cmd & SWD_CMD_APNDP) + bitbang_swd_exchange(true, NULL, 0, ap_delay_clk); + return; } } diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 9bd4cb73a..e7562d087 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -40,6 +40,7 @@ #include #include "helper/replacements.h" +#include #include #include #include @@ -75,7 +76,6 @@ static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { /* vid = pid = 0 marks the end of the list */ static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 }; static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 }; -static char *cmsis_dap_serial; static int cmsis_dap_backend = -1; static bool swd_mode; @@ -288,13 +288,13 @@ static int cmsis_dap_open(void) if (cmsis_dap_backend >= 0) { /* Use forced backend */ backend = cmsis_dap_backends[cmsis_dap_backend]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) != ERROR_OK) + if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) != ERROR_OK) backend = NULL; } else { /* Try all backends */ for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { backend = cmsis_dap_backends[i]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) == ERROR_OK) + if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) == ERROR_OK) break; else backend = NULL; @@ -324,8 +324,6 @@ static void cmsis_dap_close(struct cmsis_dap *dap) free(cmsis_dap_handle->packet_buffer); free(cmsis_dap_handle); cmsis_dap_handle = NULL; - free(cmsis_dap_serial); - cmsis_dap_serial = NULL; for (int i = 0; i < MAX_PENDING_REQUESTS; i++) { free(pending_fifo[i].transfers); @@ -1133,6 +1131,11 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) s = swd_seq_dormant_to_swd; s_len = swd_seq_dormant_to_swd_len; break; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + s = swd_seq_dormant_to_jtag; + s_len = swd_seq_dormant_to_jtag_len; + break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; @@ -1144,7 +1147,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) /* Atmel EDBG needs renew clock setting after SWJ_Sequence * otherwise default frequency is used */ - return cmsis_dap_cmd_dap_swj_clock(jtag_get_speed_khz()); + return cmsis_dap_cmd_dap_swj_clock(adapter_get_speed_khz()); } static int cmsis_dap_swd_open(void) @@ -1261,7 +1264,7 @@ static int cmsis_dap_init(void) /* 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()); + retval = cmsis_dap_cmd_dap_swj_clock(adapter_get_speed_khz()); if (retval != ERROR_OK) goto init_err; @@ -2050,16 +2053,6 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) return ERROR_OK; } -COMMAND_HANDLER(cmsis_dap_handle_serial_command) -{ - if (CMD_ARGC == 1) - cmsis_dap_serial = strdup(CMD_ARGV[0]); - else - LOG_ERROR("expected exactly one argument to cmsis_dap_serial "); - - return ERROR_OK; -} - COMMAND_HANDLER(cmsis_dap_handle_backend_command) { if (CMD_ARGC == 1) { @@ -2116,13 +2109,6 @@ static const struct command_registration cmsis_dap_command_handlers[] = { .help = "the vendor ID and product ID of the CMSIS-DAP device", .usage = "(vid pid)*", }, - { - .name = "cmsis_dap_serial", - .handler = &cmsis_dap_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the adapter", - .usage = "serial_string", - }, { .name = "cmsis_dap_backend", .handler = &cmsis_dap_handle_backend_command, diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index f6d9df21b..7c64d492c 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -24,7 +24,7 @@ struct cmsis_dap { struct cmsis_dap_backend { const char *name; - int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial); + int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial); void (*close)(struct cmsis_dap *dap); int (*read)(struct cmsis_dap *dap, int timeout_ms); int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 26c6784f9..819596b21 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -55,7 +55,7 @@ static int cmsis_dap_usb_interface = -1; static void cmsis_dap_usb_close(struct cmsis_dap *dap); 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) +static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial) { int err; struct libusb_context *ctx; diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 5bb8ee8b1..912ba3972 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -48,7 +48,7 @@ struct cmsis_dap_backend_data { static void cmsis_dap_hid_close(struct cmsis_dap *dap); static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); -static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial) +static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial) { hid_device *dev = NULL; int i; diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 22c0fe5dd..c930d8c4c 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -26,6 +26,7 @@ #endif /* project specific includes */ +#include #include #include #include @@ -68,7 +69,6 @@ #define FT232R_BUF_SIZE_EXTRA 4096 -static char *ft232r_serial_desc; static uint16_t ft232r_vid = 0x0403; /* FTDI */ static uint16_t ft232r_pid = 0x6001; /* FT232R */ static struct libusb_device_handle *adapter; @@ -257,7 +257,8 @@ static int ft232r_init(void) { uint16_t avids[] = {ft232r_vid, 0}; uint16_t apids[] = {ft232r_pid, 0}; - if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter, NULL)) { + if (jtag_libusb_open(avids, apids, &adapter, NULL)) { + const char *ft232r_serial_desc = adapter_get_required_serial(); LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n", ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc); return ERROR_JTAG_INIT_FAILED; @@ -395,16 +396,6 @@ static int ft232r_bit_name_to_number(const char *name) return -1; } -COMMAND_HANDLER(ft232r_handle_serial_desc_command) -{ - if (CMD_ARGC == 1) - ft232r_serial_desc = strdup(CMD_ARGV[0]); - else - LOG_ERROR("require exactly one argument to " - "ft232r_serial_desc "); - return ERROR_OK; -} - COMMAND_HANDLER(ft232r_handle_vid_pid_command) { if (CMD_ARGC > 2) { @@ -561,13 +552,6 @@ COMMAND_HANDLER(ft232r_handle_restore_serial_command) } static const struct command_registration ft232r_subcommand_handlers[] = { - { - .name = "serial_desc", - .handler = ft232r_handle_serial_desc_command, - .mode = COMMAND_CONFIG, - .help = "USB serial descriptor of the adapter", - .usage = "serial string", - }, { .name = "vid_pid", .handler = ft232r_handle_vid_pid_command, diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 88b36169d..d2b496d5d 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -69,7 +69,7 @@ #endif /* project specific includes */ -#include +#include #include #include #include @@ -100,7 +100,6 @@ #define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) static char *ftdi_device_desc; -static char *ftdi_serial; static uint8_t ftdi_channel; static uint8_t ftdi_jtag_mode = JTAG_MODE; @@ -740,7 +739,7 @@ static int ftdi_initialize(void) for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) { mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc, - ftdi_serial, jtag_usb_get_location(), ftdi_channel); + adapter_get_required_serial(), adapter_usb_get_location(), ftdi_channel); if (mpsse_ctx) break; } @@ -778,7 +777,7 @@ static int ftdi_initialize(void) mpsse_loopback_config(mpsse_ctx, false); - freq = mpsse_set_frequency(mpsse_ctx, jtag_get_speed_khz() * 1000); + freq = mpsse_set_frequency(mpsse_ctx, adapter_get_speed_khz() * 1000); return mpsse_flush(mpsse_ctx); } @@ -796,7 +795,6 @@ static int ftdi_quit(void) } free(ftdi_device_desc); - free(ftdi_serial); free(swd_cmd_queue); @@ -1063,18 +1061,6 @@ COMMAND_HANDLER(ftdi_handle_device_desc_command) return ERROR_OK; } -COMMAND_HANDLER(ftdi_handle_serial_command) -{ - if (CMD_ARGC == 1) { - free(ftdi_serial); - ftdi_serial = strdup(CMD_ARGV[0]); - } else { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - COMMAND_HANDLER(ftdi_handle_channel_command) { if (CMD_ARGC == 1) @@ -1296,13 +1282,6 @@ static const struct command_registration ftdi_subcommand_handlers[] = { .help = "set the USB device description of the FTDI device", .usage = "description_string", }, - { - .name = "serial", - .handler = &ftdi_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the FTDI device", - .usage = "serial_string", - }, { .name = "channel", .handler = &ftdi_handle_channel_command, @@ -1471,7 +1450,11 @@ static int ftdi_swd_run_queue(void) for (size_t i = 0; i < swd_cmd_queue_length; i++) { int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3); - LOG_DEBUG_IO("%s %s %s reg %X = %08"PRIx32, + /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ + bool check_ack = swd_cmd_returns_ack(swd_cmd_queue[i].cmd); + + LOG_DEBUG_IO("%s%s %s %s reg %X = %08"PRIx32, + check_ack ? "" : "ack ignored ", ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", swd_cmd_queue[i].cmd & SWD_CMD_APNDP ? "AP" : "DP", swd_cmd_queue[i].cmd & SWD_CMD_RNW ? "read" : "write", @@ -1479,8 +1462,8 @@ static int ftdi_swd_run_queue(void) buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + (swd_cmd_queue[i].cmd & SWD_CMD_RNW ? 0 : 1), 32)); - if (ack != SWD_ACK_OK) { - queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + if (ack != SWD_ACK_OK && check_ack) { + queued_retval = swd_ack_to_error_code(ack); goto skip; } else if (swd_cmd_queue[i].cmd & SWD_CMD_RNW) { @@ -1588,11 +1571,31 @@ static int ftdi_swd_switch_seq(enum swd_special_seq seq) ftdi_swd_swdio_en(true); mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len, SWD_MODE); break; + case JTAG_TO_DORMANT: + LOG_DEBUG("JTAG-to-DORMANT"); + ftdi_swd_swdio_en(true); + mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_dormant, 0, swd_seq_jtag_to_dormant_len, SWD_MODE); + break; case SWD_TO_JTAG: LOG_DEBUG("SWD-to-JTAG"); ftdi_swd_swdio_en(true); mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len, SWD_MODE); break; + case SWD_TO_DORMANT: + LOG_DEBUG("SWD-to-DORMANT"); + ftdi_swd_swdio_en(true); + mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_dormant, 0, swd_seq_swd_to_dormant_len, SWD_MODE); + break; + case DORMANT_TO_SWD: + LOG_DEBUG("DORMANT-to-SWD"); + ftdi_swd_swdio_en(true); + mpsse_clock_data_out(mpsse_ctx, swd_seq_dormant_to_swd, 0, swd_seq_dormant_to_swd_len, SWD_MODE); + break; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + ftdi_swd_swdio_en(true); + mpsse_clock_data_out(mpsse_ctx, swd_seq_dormant_to_jtag, 0, swd_seq_dormant_to_jtag_len, SWD_MODE); + break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 53ae1dfae..fdf4ae778 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include @@ -547,7 +547,7 @@ static bool jlink_usb_location_equal(struct jaylink_device *dev) return false; } - equal = jtag_usb_location_equal(bus, ports, num_ports); + equal = adapter_usb_location_equal(bus, ports, num_ports); free(ports); return equal; @@ -573,7 +573,7 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) return ERROR_JTAG_INIT_FAILED; } - use_usb_location = !!jtag_usb_get_location(); + use_usb_location = !!adapter_usb_get_location(); if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { LOG_ERROR("Multiple devices found, specify the desired device"); @@ -669,6 +669,23 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } + const char *serial = adapter_get_required_serial(); + if (serial) { + ret = jaylink_parse_serial_number(serial, &serial_number); + if (ret == JAYLINK_ERR) { + LOG_ERROR("Invalid serial number: %s", serial); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_parse_serial_number() failed: %s", jaylink_strerror(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + use_serial_number = true; + use_usb_address = false; + } + bool found_device; ret = jlink_open_device(JAYLINK_HIF_USB, &found_device); if (ret != ERROR_OK) @@ -811,7 +828,7 @@ static int jlink_init(void) jtag_sleep(3000); jlink_tap_init(); - jlink_speed(jtag_get_speed_khz()); + jlink_speed(adapter_get_speed_khz()); if (iface == JAYLINK_TIF_JTAG) { /* @@ -979,38 +996,11 @@ COMMAND_HANDLER(jlink_usb_command) usb_address = tmp; - use_serial_number = false; use_usb_address = true; return ERROR_OK; } -COMMAND_HANDLER(jlink_serial_command) -{ - int ret; - - if (CMD_ARGC != 1) { - command_print(CMD, "Need exactly one argument for jlink serial"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number); - - if (ret == JAYLINK_ERR) { - command_print(CMD, "Invalid serial number: %s", CMD_ARGV[0]); - return ERROR_FAIL; - } else if (ret != JAYLINK_OK) { - command_print(CMD, "jaylink_parse_serial_number() failed: %s", - jaylink_strerror(ret)); - return ERROR_FAIL; - } - - use_serial_number = true; - use_usb_address = false; - - return ERROR_OK; -} - COMMAND_HANDLER(jlink_handle_hwstatus_command) { int ret; @@ -1932,13 +1922,6 @@ static const struct command_registration jlink_subcommand_handlers[] = { .help = "set the USB address of the device that should be used", .usage = "<0-3>" }, - { - .name = "serial", - .handler = &jlink_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the device that should be used", - .usage = "" - }, { .name = "config", .handler = &jlink_handle_config_command, @@ -2148,11 +2131,31 @@ static int jlink_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; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + s = swd_seq_dormant_to_jtag; + s_len = swd_seq_dormant_to_jtag_len; + break; default: LOG_ERROR("Sequence %d not supported", seq); return ERROR_FAIL; diff --git a/src/jtag/drivers/jtag_usb_common.c b/src/jtag/drivers/jtag_usb_common.c deleted file mode 100644 index 94cd7e74d..000000000 --- a/src/jtag/drivers/jtag_usb_common.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0+ - * Copyright (c) 2018 Pengutronix, Oleksij Rempel - */ - -#include -#include - -#include "jtag_usb_common.h" - -static char *jtag_usb_location; -/* - * 1 char: bus - * 2 * 7 chars: max 7 ports - * 1 char: test for overflow - * ------ - * 16 chars - */ -#define JTAG_USB_MAX_LOCATION_LENGTH 16 - -void jtag_usb_set_location(const char *location) -{ - if (strnlen(location, JTAG_USB_MAX_LOCATION_LENGTH) == - JTAG_USB_MAX_LOCATION_LENGTH) - LOG_WARNING("usb location string is too long!!\n"); - - free(jtag_usb_location); - - jtag_usb_location = strndup(location, JTAG_USB_MAX_LOCATION_LENGTH); -} - -const char *jtag_usb_get_location(void) -{ - return jtag_usb_location; -} - -bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, - size_t path_len) -{ - size_t path_step, string_length; - char *ptr, *loc; - bool equal = false; - - /* strtok need non const char */ - loc = strndup(jtag_usb_get_location(), JTAG_USB_MAX_LOCATION_LENGTH); - string_length = strnlen(loc, JTAG_USB_MAX_LOCATION_LENGTH); - - ptr = strtok(loc, "-"); - if (!ptr) { - LOG_WARNING("no '-' in usb path\n"); - goto done; - } - - string_length -= strnlen(ptr, string_length); - /* check bus mismatch */ - if (atoi(ptr) != dev_bus) - goto done; - - path_step = 0; - while (path_step < path_len) { - ptr = strtok(NULL, "."); - - /* no more tokens in path */ - if (!ptr) - break; - - /* path mismatch at some step */ - if (path_step < path_len && atoi(ptr) != port_path[path_step]) - break; - - path_step++; - string_length -= strnlen(ptr, string_length) + 1; - }; - - /* walked the full path, all elements match */ - if (path_step == path_len && !string_length) - equal = true; - -done: - free(loc); - return equal; -} diff --git a/src/jtag/drivers/jtag_usb_common.h b/src/jtag/drivers/jtag_usb_common.h deleted file mode 100644 index c4c28cc91..000000000 --- a/src/jtag/drivers/jtag_usb_common.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0+ - * Copyright (c) 2018 Pengutronix, Oleksij Rempel - */ - -#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, - size_t path_len); - -#endif /* OPENOCD_JTAG_USB_COMMON_H */ diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index a0138f840..0fc688edf 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -159,7 +159,7 @@ retry_write: /* This means we could not send all data, which is most likely fatal for the jtag_vpi connection (the underlying TCP connection likely not usable anymore) */ - LOG_ERROR("Could not send all data through jtag_vpi connection."); + LOG_ERROR("jtag_vpi: Could not send all data through jtag_vpi connection."); exit(-1); } @@ -541,7 +541,7 @@ static int jtag_vpi_init(void) sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { - LOG_ERROR("Could not create socket"); + LOG_ERROR("jtag_vpi: Could not create client socket"); return ERROR_FAIL; } @@ -556,13 +556,13 @@ static int jtag_vpi_init(void) serv_addr.sin_addr.s_addr = inet_addr(server_address); if (serv_addr.sin_addr.s_addr == INADDR_NONE) { - LOG_ERROR("inet_addr error occurred"); + LOG_ERROR("jtag_vpi: inet_addr error occurred"); return ERROR_FAIL; } if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { close(sockfd); - LOG_ERROR("Can't connect to %s : %u", server_address, server_port); + LOG_ERROR("jtag_vpi: Can't connect to %s : %u", server_address, server_port); return ERROR_COMMAND_CLOSE_CONNECTION; } @@ -573,7 +573,7 @@ static int jtag_vpi_init(void) setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); } - LOG_INFO("Connection to %s : %u succeed", server_address, server_port); + LOG_INFO("jtag_vpi: Connection to %s : %u successful", server_address, server_port); return ERROR_OK; } diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index 327bb572d..5e2168eea 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -114,7 +114,6 @@ struct pending_transfer_result { void *buffer; }; -static char *kitprog_serial; static bool kitprog_init_acquire_psoc; static int pending_transfer_count, pending_queue_len; @@ -230,7 +229,6 @@ static int kitprog_quit(void) free(kitprog_handle->packet_buffer); free(kitprog_handle->serial); free(kitprog_handle); - free(kitprog_serial); free(pending_transfers); return ERROR_OK; @@ -272,8 +270,7 @@ static int kitprog_usb_open(void) const uint16_t vids[] = { VID, 0 }; const uint16_t pids[] = { PID, 0 }; - if (jtag_libusb_open(vids, pids, kitprog_serial, - &kitprog_handle->usb_handle, NULL) != ERROR_OK) { + if (jtag_libusb_open(vids, pids, &kitprog_handle->usb_handle, NULL) != ERROR_OK) { LOG_ERROR("Failed to open or find the device"); return ERROR_FAIL; } @@ -851,22 +848,6 @@ COMMAND_HANDLER(kitprog_handle_acquire_psoc_command) return retval; } -COMMAND_HANDLER(kitprog_handle_serial_command) -{ - if (CMD_ARGC == 1) { - kitprog_serial = strdup(CMD_ARGV[0]); - if (!kitprog_serial) { - LOG_ERROR("Failed to allocate memory for the serial number"); - return ERROR_FAIL; - } - } else { - LOG_ERROR("expected exactly one argument to kitprog_serial "); - return ERROR_FAIL; - } - - return ERROR_OK; -} - COMMAND_HANDLER(kitprog_handle_init_acquire_psoc_command) { kitprog_init_acquire_psoc = true; @@ -900,13 +881,6 @@ static const struct command_registration kitprog_command_handlers[] = { .usage = "", .chain = kitprog_subcommand_handlers, }, - { - .name = "kitprog_serial", - .handler = &kitprog_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the adapter", - .usage = "serial_string", - }, { .name = "kitprog_init_acquire_psoc", .handler = &kitprog_handle_init_acquire_psoc_command, diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 3308d8742..fc961cb91 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -20,8 +20,11 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif + +#include + #include -#include +#include #include "libusb_helper.h" /* @@ -85,7 +88,7 @@ static bool jtag_libusb_location_equal(struct libusb_device *device) } dev_bus = libusb_get_bus_number(device); - return jtag_usb_location_equal(dev_bus, port_path, path_len); + return adapter_usb_location_equal(dev_bus, port_path, path_len); } #else /* HAVE_LIBUSB_GET_PORT_NUMBERS */ static bool jtag_libusb_location_equal(struct libusb_device *device) @@ -154,7 +157,6 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device, } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - const char *serial, struct libusb_device_handle **out, adapter_get_alternate_serial_fn adapter_get_alternate_serial) { @@ -162,6 +164,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], int retval = ERROR_FAIL; bool serial_mismatch = false; struct libusb_device_handle *libusb_handle = NULL; + const char *serial = adapter_get_required_serial(); if (libusb_init(&jtag_libusb_context) < 0) return ERROR_FAIL; @@ -177,7 +180,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], if (!jtag_libusb_match_ids(&dev_desc, vids, pids)) continue; - if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) + if (adapter_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) continue; err_code = libusb_open(devs[idx], &libusb_handle); diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h index 6087128d2..2ddb246b3 100644 --- a/src/jtag/drivers/libusb_helper.h +++ b/src/jtag/drivers/libusb_helper.h @@ -28,7 +28,6 @@ typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *d struct libusb_device_descriptor *dev_desc); int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - const char *serial, struct libusb_device_handle **out, adapter_get_alternate_serial_fn adapter_get_alternate_serial); void jtag_libusb_close(struct libusb_device_handle *dev); diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index dd50b4406..75f6152be 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -360,7 +360,11 @@ static int linuxgpiod_init(void) goto out_error; if (is_gpio_valid(trst_gpio)) { - gpiod_trst = helper_get_output_line("trst", trst_gpio, 1); + if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) + gpiod_trst = helper_get_open_drain_output_line("trst", trst_gpio, 1); + else + gpiod_trst = helper_get_output_line("trst", trst_gpio, 1); + if (!gpiod_trst) goto out_error; } diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c index 3eea9de58..d4b8b53bc 100644 --- a/src/jtag/drivers/nulink_usb.c +++ b/src/jtag/drivers/nulink_usb.c @@ -22,6 +22,7 @@ /* project specific includes */ #include +#include #include #include #include @@ -1054,8 +1055,9 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd) goto error_open; } - if (param->serial) { - size_t len = mbstowcs(NULL, param->serial, 0); + const char *serial = adapter_get_required_serial(); + if (serial) { + size_t len = mbstowcs(NULL, serial, 0); target_serial = calloc(len + 1, sizeof(wchar_t)); if (!target_serial) { @@ -1063,7 +1065,7 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd) goto error_open; } - if (mbstowcs(target_serial, param->serial, len + 1) == (size_t)(-1)) { + if (mbstowcs(target_serial, serial, len + 1) == (size_t)(-1)) { LOG_WARNING("unable to convert serial"); free(target_serial); target_serial = NULL; diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 6881959c3..ae21cf2b9 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -706,7 +706,7 @@ struct opendous_jtag *opendous_usb_open(void) struct opendous_jtag *result; struct libusb_device_handle *devh; - if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK) + if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh, NULL) != ERROR_OK) return NULL; jtag_libusb_set_configuration(devh, 0); diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 123134f51..771b6e6f3 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -1,6 +1,6 @@ /******************************************************************************* * Driver for OpenJTAG Project (www.openjtag.org) * - * Compatible with libftdi and ftd2xx drivers. * + * Compatible with libftdi drivers. * * * * Cypress CY7C65215 support * * Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV * @@ -449,7 +449,7 @@ static int openjtag_init_cy7c65215(void) int ret; usbh = NULL; - ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL); + ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, &usbh, NULL); if (ret != ERROR_OK) { LOG_ERROR("unable to open cy7c65215 device"); goto err; diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index 5c43d3244..f7665eb12 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -374,7 +374,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue *queue) static int osbdm_open(struct osbdm *osbdm) { (void)memset(osbdm, 0, sizeof(*osbdm)); - if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK) + if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh, NULL) != ERROR_OK) return ERROR_FAIL; if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK) diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index d50d306d3..9273e3ec2 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -23,6 +23,7 @@ #include "config.h" #endif +#include #include #include "bitbang.h" @@ -457,9 +458,9 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) } parport_toggling_time_ns = ns; - retval = jtag_get_speed(&wait_states); + retval = adapter_get_speed(&wait_states); if (retval != ERROR_OK) { - /* if jtag_get_speed fails then the clock_mode + /* if adapter_get_speed fails then the clock_mode * has not been configured, this happens if parport_toggling_time is * called before the adapter speed is set */ LOG_INFO("no parport speed set - defaulting to zero wait states"); diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c index 61de42630..e938a3be3 100644 --- a/src/jtag/drivers/presto.c +++ b/src/jtag/drivers/presto.c @@ -29,6 +29,7 @@ #include "windows.h" #endif +#include #include #include #include "bitq.h" @@ -132,7 +133,7 @@ static int presto_read(uint8_t *buf, uint32_t size) return ERROR_OK; } -static int presto_open_libftdi(char *req_serial) +static int presto_open_libftdi(const char *req_serial) { uint8_t presto_data; @@ -195,7 +196,7 @@ static int presto_open_libftdi(char *req_serial) return ERROR_OK; } -static int presto_open(char *req_serial) +static int presto_open(const char *req_serial) { presto->buff_out_pos = 0; presto->buff_in_pos = 0; @@ -506,43 +507,10 @@ static int presto_jtag_speed(int speed) return 0; } -static char *presto_serial; - -COMMAND_HANDLER(presto_handle_serial_command) -{ - if (CMD_ARGC == 1) { - free(presto_serial); - presto_serial = strdup(CMD_ARGV[0]); - } else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - -static const struct command_registration presto_subcommand_handlers[] = { - { - .name = "serial", - .handler = presto_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "Configure USB serial number of Presto device.", - .usage = "serial_string", - }, - COMMAND_REGISTRATION_DONE -}; - -static const struct command_registration presto_command_handlers[] = { - { - .name = "presto", - .mode = COMMAND_ANY, - .help = "perform presto management", - .chain = presto_subcommand_handlers, - .usage = "", - }, - COMMAND_REGISTRATION_DONE -}; - static int presto_jtag_init(void) { + const char *presto_serial = adapter_get_required_serial(); + if (presto_open(presto_serial) != ERROR_OK) { presto_close(); if (presto_serial) @@ -562,10 +530,6 @@ static int presto_jtag_quit(void) bitq_cleanup(); presto_close(); LOG_INFO("PRESTO closed"); - - free(presto_serial); - presto_serial = NULL; - return ERROR_OK; } @@ -576,7 +540,6 @@ static struct jtag_interface presto_interface = { struct adapter_driver presto_adapter_driver = { .name = "presto", .transports = jtag_only, - .commands = presto_command_handlers, .init = presto_jtag_init, .quit = presto_jtag_quit, diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index f75a38b5d..73be3c57e 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -1461,7 +1461,7 @@ static int rlink_init(void) const uint16_t vids[] = { USB_IDVENDOR, 0 }; const uint16_t pids[] = { USB_IDPRODUCT, 0 }; - if (jtag_libusb_open(vids, pids, NULL, &hdev, NULL) != ERROR_OK) + if (jtag_libusb_open(vids, pids, &hdev, NULL) != ERROR_OK) return ERROR_FAIL; struct libusb_device_descriptor descriptor; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a52370863..2f61bf946 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -33,9 +33,12 @@ #endif /* project specific includes */ +#include #include #include #include +#include +#include #include #include #include @@ -79,7 +82,7 @@ #define STLINK_V2_1_TRACE_EP (2|ENDPOINT_IN) #define STLINK_SG_SIZE (31) -#define STLINK_DATA_SIZE (4096) +#define STLINK_DATA_SIZE (6144) #define STLINK_CMD_SIZE_V2 (16) #define STLINK_CMD_SIZE_V1 (10) @@ -97,15 +100,26 @@ * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and * this limits the bulk packet size and the 8bit read/writes to max 64 bytes. * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6. + * + * For 16 and 32bit read/writes stlink handles USB packet split and the limit + * is the internal buffer size of 6144 bytes. + * TODO: override ADIv5 layer's tar_autoincr_block that limits the transfer + * to 1024 or 4096 bytes */ -#define STLINK_MAX_RW8 (64) -#define STLINKV3_MAX_RW8 (512) +#define STLINK_MAX_RW8 (64) +#define STLINKV3_MAX_RW8 (512) +#define STLINK_MAX_RW16_32 STLINK_DATA_SIZE +#define STLINK_SWIM_DATA_SIZE STLINK_DATA_SIZE /* "WAIT" responses will be retried (with exponential backoff) at * most this many times before failing to caller. */ #define MAX_WAIT_RETRIES 8 +/* HLA is currently limited at AP#0 and no control on CSW */ +#define STLINK_HLA_AP_NUM 0 +#define STLINK_HLA_CSW 0 + enum stlink_jtag_api_version { STLINK_JTAG_API_V1 = 1, STLINK_JTAG_API_V2, @@ -168,6 +182,68 @@ struct stlink_backend_s { int (*read_trace)(void *handle, const uint8_t *buf, int size); }; +/* TODO: make queue size dynamic */ +/* TODO: don't allocate queue for HLA */ +#define MAX_QUEUE_DEPTH (4096) + +enum queue_cmd { + CMD_DP_READ = 1, + CMD_DP_WRITE, + + CMD_AP_READ, + CMD_AP_WRITE, + + /* + * encode the bytes size in the enum's value. This makes easy to extract it + * with a simple logic AND, by using the macro CMD_MEM_AP_2_SIZE() below + */ + CMD_MEM_AP_READ8 = 0x10 + 1, + CMD_MEM_AP_READ16 = 0x10 + 2, + CMD_MEM_AP_READ32 = 0x10 + 4, + + CMD_MEM_AP_WRITE8 = 0x20 + 1, + CMD_MEM_AP_WRITE16 = 0x20 + 2, + CMD_MEM_AP_WRITE32 = 0x20 + 4, +}; + +#define CMD_MEM_AP_2_SIZE(cmd) ((cmd) & 7) + +struct dap_queue { + enum queue_cmd cmd; + union { + struct dp_r { + unsigned int reg; + struct adiv5_dap *dap; + uint32_t *p_data; + } dp_r; + struct dp_w { + unsigned int reg; + struct adiv5_dap *dap; + uint32_t data; + } dp_w; + struct ap_r { + unsigned int reg; + struct adiv5_ap *ap; + uint32_t *p_data; + } ap_r; + struct ap_w { + unsigned int reg; + struct adiv5_ap *ap; + uint32_t data; + bool changes_csw_default; + } ap_w; + struct mem_ap { + uint32_t addr; + struct adiv5_ap *ap; + union { + uint32_t *p_data; + uint32_t data; + }; + uint32_t csw; + } mem_ap; + }; +}; + /** */ struct stlink_usb_handle_s { /** */ @@ -211,6 +287,10 @@ struct stlink_usb_handle_s { /** reconnect is needed next time we try to query the * status */ bool reconnect_pending; + /** queue of dap_direct operations */ + struct dap_queue queue[MAX_QUEUE_DEPTH]; + /** first element available in the queue */ + unsigned int queue_index; }; /** */ @@ -358,6 +438,12 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, i #define STLINK_DEBUG_APIV2_INIT_AP 0x4B #define STLINK_DEBUG_APIV2_CLOSE_AP_DBG 0x4C +#define STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC 0x50 +#define STLINK_DEBUG_APIV2_RW_MISC_OUT 0x51 +#define STLINK_DEBUG_APIV2_RW_MISC_IN 0x52 + +#define STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC 0x54 + #define STLINK_APIV3_SET_COM_FREQ 0x61 #define STLINK_APIV3_GET_COM_FREQ 0x62 @@ -430,6 +516,10 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, i /* aliases */ #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE #define STLINK_F_HAS_FPU_REG STLINK_F_HAS_GETLASTRWSTATUS2 +#define STLINK_F_HAS_MEM_WR_NO_INC STLINK_F_HAS_MEM_16BIT +#define STLINK_F_HAS_MEM_RD_NO_INC STLINK_F_HAS_DPBANKSEL +#define STLINK_F_HAS_RW_MISC STLINK_F_HAS_DPBANKSEL +#define STLINK_F_HAS_CSW STLINK_F_HAS_DPBANKSEL #define STLINK_REGSEL_IS_FPU(x) ((x) > 0x1F) @@ -838,17 +928,35 @@ static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, bool return ERROR_FAIL; } - keep_alive(); - /* read the TCP response */ - int received_size = recv(h->tcp_backend_priv.fd, (void *)h->tcp_backend_priv.recv_buf, recv_size, 0); - if (received_size != recv_size) { - LOG_ERROR("failed to receive USB CMD response"); - if (received_size == -1) + int retval = ERROR_OK; + int remaining_bytes = recv_size; + uint8_t *recv_buf = h->tcp_backend_priv.recv_buf; + const int64_t timeout = timeval_ms() + 1000; /* 1 second */ + + while (remaining_bytes > 0) { + if (timeval_ms() > timeout) { + LOG_DEBUG("received size %d (expected %d)", recv_size - remaining_bytes, recv_size); + retval = ERROR_TIMEOUT_REACHED; + break; + } + + keep_alive(); + int received = recv(h->tcp_backend_priv.fd, (void *)recv_buf, remaining_bytes, 0); + + if (received == -1) { LOG_DEBUG("socket recv error: %s (errno %d)", strerror(errno), errno); - else - LOG_DEBUG("received size %d (expected %d)", received_size, recv_size); - return ERROR_FAIL; + retval = ERROR_FAIL; + break; + } + + recv_buf += received; + remaining_bytes -= received; + } + + if (retval != ERROR_OK) { + LOG_ERROR("failed to receive USB CMD response"); + return retval; } if (check_tcp_status) { @@ -1246,6 +1354,7 @@ static int stlink_usb_version(void *handle) flags |= STLINK_F_QUIRK_JTAG_DP_READ; /* API to read/write memory at 16 bit from J26 */ + /* API to write memory without address increment from J26 */ if (h->version.jtag >= 26) flags |= STLINK_F_HAS_MEM_16BIT; @@ -1258,6 +1367,8 @@ static int stlink_usb_version(void *handle) flags |= STLINK_F_FIX_CLOSE_AP; /* Banked regs (DPv1 & DPv2) support from V2J32 */ + /* API to read memory without address increment from V2J32 */ + /* Memory R/W supports CSW from V2J32 */ if (h->version.jtag >= 32) flags |= STLINK_F_HAS_DPBANKSEL; @@ -1279,6 +1390,7 @@ static int stlink_usb_version(void *handle) flags |= STLINK_F_HAS_DAP_REG; /* API to read/write memory at 16 bit */ + /* API to write memory without address increment */ flags |= STLINK_F_HAS_MEM_16BIT; /* API required to init AP before any AP access */ @@ -1288,6 +1400,8 @@ static int stlink_usb_version(void *handle) flags |= STLINK_F_FIX_CLOSE_AP; /* Banked regs (DPv1 & DPv2) support from V3J2 */ + /* API to read memory without address increment from V3J2 */ + /* Memory R/W supports CSW from V3J2 */ if (h->version.jtag >= 2) flags |= STLINK_F_HAS_DPBANKSEL; @@ -1807,7 +1921,7 @@ static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, con unsigned int datalen = 0; int cmdsize = STLINK_CMD_SIZE_V2; - if (len > STLINK_DATA_SIZE) + if (len > STLINK_SWIM_DATA_SIZE) return ERROR_FAIL; if (h->version.stlink == 1) @@ -1840,7 +1954,7 @@ static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint struct stlink_usb_handle_s *h = handle; int res; - if (len > STLINK_DATA_SIZE) + if (len > STLINK_SWIM_DATA_SIZE) return ERROR_FAIL; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -2329,8 +2443,8 @@ static int stlink_usb_get_rw_status(void *handle) } /** */ -static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, - uint8_t *buffer) +static int stlink_usb_read_mem8(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, uint8_t *buffer) { int res; uint16_t read_len = len; @@ -2338,6 +2452,9 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, assert(handle); + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + /* max 8 bit read/write is 64 bytes or 512 bytes for v3 */ if (len > stlink_usb_block(h)) { LOG_DEBUG("max buffer (%d) length exceeded", stlink_usb_block(h)); @@ -2352,6 +2469,9 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; /* we need to fix read length for single bytes */ if (read_len == 1) @@ -2368,14 +2488,17 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, } /** */ -static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, - const uint8_t *buffer) +static int stlink_usb_write_mem8(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle); + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + /* max 8 bit read/write is 64 bytes or 512 bytes for v3 */ if (len > stlink_usb_block(h)) { LOG_DEBUG("max buffer length (%d) exceeded", stlink_usb_block(h)); @@ -2390,6 +2513,9 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; res = stlink_usb_xfer_noerrcheck(handle, buffer, len); @@ -2400,8 +2526,8 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, } /** */ -static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, - uint8_t *buffer) +static int stlink_usb_read_mem16(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; @@ -2411,6 +2537,14 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT)) return ERROR_COMMAND_NOTFOUND; + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + /* data must be a multiple of 2 and half-word aligned */ if (len % 2 || addr % 2) { LOG_DEBUG("Invalid data alignment"); @@ -2425,6 +2559,9 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); @@ -2437,8 +2574,8 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, } /** */ -static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, - const uint8_t *buffer) +static int stlink_usb_write_mem16(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; @@ -2448,6 +2585,14 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT)) return ERROR_COMMAND_NOTFOUND; + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + /* data must be a multiple of 2 and half-word aligned */ if (len % 2 || addr % 2) { LOG_DEBUG("Invalid data alignment"); @@ -2462,6 +2607,9 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; res = stlink_usb_xfer_noerrcheck(handle, buffer, len); @@ -2472,14 +2620,22 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, } /** */ -static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, - uint8_t *buffer) +static int stlink_usb_read_mem32(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle); + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + /* data must be a multiple of 4 and word aligned */ if (len % 4 || addr % 4) { LOG_DEBUG("Invalid data alignment"); @@ -2494,6 +2650,9 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); @@ -2506,14 +2665,22 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, } /** */ -static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, - const uint8_t *buffer) +static int stlink_usb_write_mem32(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle); + if ((ap_num != 0 || csw != 0) && !(h->version.flags & STLINK_F_HAS_CSW)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + /* data must be a multiple of 4 and word aligned */ if (len % 4 || addr % 4) { LOG_DEBUG("Invalid data alignment"); @@ -2528,6 +2695,9 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; res = stlink_usb_xfer_noerrcheck(handle, buffer, len); @@ -2537,6 +2707,88 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, return stlink_usb_get_rw_status(handle); } +static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, uint8_t *buffer) +{ + struct stlink_usb_handle_s *h = handle; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_MEM_RD_NO_INC)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + + /* data must be a multiple of 4 and word aligned */ + if (len % 4 || addr % 4) { + LOG_DEBUG("Invalid data alignment"); + return ERROR_TARGET_UNALIGNED_ACCESS; + } + + stlink_usb_init_buffer(handle, h->rx_ep, len); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC; + h_u32_to_le(h->cmdbuf + h->cmdidx, addr); + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf + h->cmdidx, len); + h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; + + int retval = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); + if (retval != ERROR_OK) + return retval; + + memcpy(buffer, h->databuf, len); + + return stlink_usb_get_rw_status(handle); +} + +static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint16_t len, const uint8_t *buffer) +{ + struct stlink_usb_handle_s *h = handle; + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_MEM_WR_NO_INC)) + return ERROR_COMMAND_NOTFOUND; + + if (len > STLINK_MAX_RW16_32) { + LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32); + return ERROR_FAIL; + } + + /* data must be a multiple of 4 and word aligned */ + if (len % 4 || addr % 4) { + LOG_DEBUG("Invalid data alignment"); + return ERROR_TARGET_UNALIGNED_ACCESS; + } + + stlink_usb_init_buffer(handle, h->tx_ep, len); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC; + h_u32_to_le(h->cmdbuf + h->cmdidx, addr); + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf + h->cmdidx, len); + h->cmdidx += 2; + h->cmdbuf[h->cmdidx++] = ap_num; + h_u24_to_le(h->cmdbuf + h->cmdidx, csw >> 8); + h->cmdidx += 3; + + int retval = stlink_usb_xfer_noerrcheck(handle, buffer, len); + if (retval != ERROR_OK) + return retval; + + return stlink_usb_get_rw_status(handle); +} + static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t address) { uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address)); @@ -2545,8 +2797,93 @@ static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t addr return max_tar_block; } +static int stlink_usb_read_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) +{ + int retval = ERROR_OK; + uint32_t bytes_remaining; + int retries = 0; + struct stlink_usb_handle_s *h = handle; + + /* calculate byte count */ + count *= size; + + /* switch to 8 bit if stlink does not support 16 bit memory read */ + if (size == 2 && !(h->version.flags & STLINK_F_HAS_MEM_16BIT)) + size = 1; + + while (count) { + bytes_remaining = (size != 1) ? + stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h); + + if (count < bytes_remaining) + bytes_remaining = count; + + /* + * all stlink support 8/32bit memory read/writes and only from + * stlink V2J26 there is support for 16 bit memory read/write. + * Honour 32 bit and, if possible, 16 bit too. Otherwise, handle + * as 8bit access. + */ + if (size != 1) { + /* When in jtag mode the stlink uses the auto-increment functionality. + * However it expects us to pass the data correctly, this includes + * alignment and any page boundaries. We already do this as part of the + * adi_v5 implementation, but the stlink is a hla adapter and so this + * needs implementing manually. + * currently this only affects jtag mode, according to ST they do single + * access in SWD mode - but this may change and so we do it for both modes */ + + /* we first need to check for any unaligned bytes */ + if (addr & (size - 1)) { + uint32_t head_bytes = size - (addr & (size - 1)); + retval = stlink_usb_read_mem8(handle, ap_num, csw, addr, head_bytes, buffer); + if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { + usleep((1 << retries++) * 1000); + continue; + } + if (retval != ERROR_OK) + return retval; + buffer += head_bytes; + addr += head_bytes; + count -= head_bytes; + bytes_remaining -= head_bytes; + } + + if (bytes_remaining & (size - 1)) + retval = stlink_usb_read_ap_mem(handle, ap_num, csw, addr, 1, bytes_remaining, buffer); + else if (size == 2) + retval = stlink_usb_read_mem16(handle, ap_num, csw, addr, bytes_remaining, buffer); + else + retval = stlink_usb_read_mem32(handle, ap_num, csw, addr, bytes_remaining, buffer); + } else { + retval = stlink_usb_read_mem8(handle, ap_num, csw, addr, bytes_remaining, buffer); + } + + if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { + usleep((1 << retries++) * 1000); + continue; + } + if (retval != ERROR_OK) + return retval; + + buffer += bytes_remaining; + addr += bytes_remaining; + count -= bytes_remaining; + } + + return retval; +} + static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) +{ + return stlink_usb_read_ap_mem(handle, STLINK_HLA_AP_NUM, STLINK_HLA_CSW, + addr, size, count, buffer); +} + +static int stlink_usb_write_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, + uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval = ERROR_OK; uint32_t bytes_remaining; @@ -2588,7 +2925,7 @@ static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, if (addr & (size - 1)) { uint32_t head_bytes = size - (addr & (size - 1)); - retval = stlink_usb_read_mem8(handle, addr, head_bytes, buffer); + retval = stlink_usb_write_mem8(handle, ap_num, csw, addr, head_bytes, buffer); if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { usleep((1<version.flags & STLINK_F_HAS_MEM_16BIT)) - size = 1; - - while (count) { - - bytes_remaining = (size != 1) ? - stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h); - - if (count < bytes_remaining) - bytes_remaining = count; - - /* - * all stlink support 8/32bit memory read/writes and only from - * stlink V2J26 there is support for 16 bit memory read/write. - * Honour 32 bit and, if possible, 16 bit too. Otherwise, handle - * as 8bit access. - */ - if (size != 1) { - - /* When in jtag mode the stlink uses the auto-increment functionality. - * However it expects us to pass the data correctly, this includes - * alignment and any page boundaries. We already do this as part of the - * adi_v5 implementation, but the stlink is a hla adapter and so this - * needs implementing manually. - * currently this only affects jtag mode, according to ST they do single - * access in SWD mode - but this may change and so we do it for both modes */ - - /* we first need to check for any unaligned bytes */ - if (addr & (size - 1)) { - - uint32_t head_bytes = size - (addr & (size - 1)); - retval = stlink_usb_write_mem8(handle, addr, head_bytes, buffer); - if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { - usleep((1<vid, param->pid, param->serial, + if (jtag_libusb_open(param->vid, param->pid, &h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) { LOG_ERROR("open failed"); return ERROR_FAIL; @@ -3311,7 +3575,8 @@ static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param) char serial[STLINK_TCP_SERIAL_SIZE + 1] = {0}; uint8_t stlink_used; bool stlink_id_matched = false; - bool stlink_serial_matched = (!param->serial); + const char *adapter_serial = adapter_get_required_serial(); + bool stlink_serial_matched = !adapter_serial; for (uint32_t stlink_id = 0; stlink_id < connected_stlinks; stlink_id++) { /* get the stlink info */ @@ -3341,27 +3606,28 @@ static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param) continue; /* check the serial if specified */ - if (param->serial) { + if (adapter_serial) { /* ST-Link server fixes the buggy serial returned by old ST-Link DFU * for further details refer to stlink_usb_get_alternate_serial * so if the user passes the buggy serial, we need to fix it before * comparing with the serial returned by ST-Link server */ - if (strlen(param->serial) == STLINK_SERIAL_LEN / 2) { + if (strlen(adapter_serial) == STLINK_SERIAL_LEN / 2) { char fixed_serial[STLINK_SERIAL_LEN + 1]; for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2) - sprintf(fixed_serial + i, "%02X", param->serial[i / 2]); + sprintf(fixed_serial + i, "%02X", adapter_serial[i / 2]); fixed_serial[STLINK_SERIAL_LEN] = '\0'; stlink_serial_matched = strcmp(fixed_serial, serial) == 0; - } else - stlink_serial_matched = strcmp(param->serial, serial) == 0; + } else { + stlink_serial_matched = strcmp(adapter_serial, serial) == 0; + } } if (!stlink_serial_matched) LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'", - serial, param->serial); + serial, adapter_serial); else /* exit the search loop if there is match */ break; } @@ -3430,7 +3696,7 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode for (unsigned i = 0; param->vid[i]; i++) { LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", h->st_mode, param->vid[i], param->pid[i], - param->serial ? param->serial : ""); + adapter_get_required_serial() ? adapter_get_required_serial() : ""); } if (param->use_stlink_tcp) @@ -3482,7 +3748,7 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode goto error_open; } *fd = h; - h->max_mem_packet = STLINK_DATA_SIZE; + h->max_mem_packet = STLINK_SWIM_DATA_SIZE; return ERROR_OK; } @@ -3493,8 +3759,8 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode h->max_mem_packet = (1 << 10); uint8_t buffer[4]; - stlink_usb_open_ap(h, 0); - err = stlink_usb_read_mem32(h, CPUID, 4, buffer); + stlink_usb_open_ap(h, STLINK_HLA_AP_NUM); + err = stlink_usb_read_mem32(h, STLINK_HLA_AP_NUM, STLINK_HLA_CSW, CPUID, 4, buffer); if (err == ERROR_OK) { uint32_t cpuid = le_to_h_u32(buffer); int i = (cpuid >> 4) & 0xf; @@ -3627,6 +3893,53 @@ static int stlink_usb_close_access_port(void *handle, unsigned char ap_num) } +static int stlink_usb_rw_misc_out(void *handle, uint32_t items, const uint8_t *buffer) +{ + struct stlink_usb_handle_s *h = handle; + unsigned int buflen = ALIGN_UP(items, 4) + 4 * items; + + LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) + return ERROR_COMMAND_NOTFOUND; + + stlink_usb_init_buffer(handle, h->tx_ep, buflen); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_RW_MISC_OUT; + h_u32_to_le(&h->cmdbuf[2], items); + + return stlink_usb_xfer_noerrcheck(handle, buffer, buflen); +} + +static int stlink_usb_rw_misc_in(void *handle, uint32_t items, uint8_t *buffer) +{ + struct stlink_usb_handle_s *h = handle; + unsigned int buflen = 2 * 4 * items; + + LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); + + assert(handle != NULL); + + if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) + return ERROR_COMMAND_NOTFOUND; + + stlink_usb_init_buffer(handle, h->rx_ep, buflen); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_RW_MISC_IN; + + int res = stlink_usb_xfer_noerrcheck(handle, h->databuf, buflen); + if (res != ERROR_OK) + return res; + + memcpy(buffer, h->databuf, buflen); + + return ERROR_OK; +} + /** */ static int stlink_read_dap_register(void *handle, unsigned short dap_port, unsigned short addr, uint32_t *val) @@ -3721,11 +4034,9 @@ struct hl_layout_api_s stlink_usb_layout_api = { static struct stlink_usb_handle_s *stlink_dap_handle; static struct hl_interface_param_s stlink_dap_param; static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1); +static uint32_t last_csw_default[DP_APSEL_MAX + 1]; static int stlink_dap_error = ERROR_OK; -static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, - uint32_t *data); - /** */ static int stlink_dap_record_error(int error) { @@ -3742,6 +4053,11 @@ static int stlink_dap_get_and_clear_error(void) return retval; } +static int stlink_dap_get_error(void) +{ + return stlink_dap_error; +} + static int stlink_usb_open_ap(void *handle, unsigned short apsel) { struct stlink_usb_handle_s *h = handle; @@ -3763,6 +4079,7 @@ static int stlink_usb_open_ap(void *handle, unsigned short apsel) LOG_DEBUG("AP %d enabled", apsel); set_bit(apsel, opened_ap); + last_csw_default[apsel] = 0; return ERROR_OK; } @@ -3846,6 +4163,8 @@ static int stlink_dap_op_connect(struct adiv5_dap *dap) dap->do_reconnect = false; dap_invalidate_cache(dap); + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) + last_csw_default[i] = 0; retval = dap_dp_init(dap); if (retval != ERROR_OK) { @@ -3887,8 +4206,7 @@ static int stlink_dap_op_send_sequence(struct adiv5_dap *dap, enum swd_special_s } /** */ -static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, - uint32_t *data) +static int stlink_dap_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { uint32_t dummy; int retval; @@ -3899,10 +4217,6 @@ static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, return ERROR_COMMAND_NOTFOUND; } - retval = stlink_dap_check_reconnect(dap); - if (retval != ERROR_OK) - return retval; - data = data ? data : &dummy; if (stlink_dap_handle->version.flags & STLINK_F_QUIRK_JTAG_DP_READ && stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG) { @@ -3917,12 +4231,11 @@ static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg, STLINK_DEBUG_PORT_ACCESS, reg, data); } - return stlink_dap_record_error(retval); + return retval; } /** */ -static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned reg, - uint32_t data) +static int stlink_dap_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { int retval; @@ -3938,31 +4251,22 @@ static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned reg, data &= ~DP_SELECT_DPBANK; } - retval = stlink_dap_check_reconnect(dap); - if (retval != ERROR_OK) - return retval; - /* ST-Link does not like that we set CORUNDETECT */ if (reg == DP_CTRL_STAT) data &= ~CORUNDETECT; retval = stlink_write_dap_register(stlink_dap_handle, STLINK_DEBUG_PORT_ACCESS, reg, data); - return stlink_dap_record_error(retval); + return retval; } /** */ -static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned reg, - uint32_t *data) +static int stlink_dap_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { struct adiv5_dap *dap = ap->dap; uint32_t dummy; int retval; - retval = stlink_dap_check_reconnect(dap); - if (retval != ERROR_OK) - return retval; - if (reg != AP_REG_IDR) { retval = stlink_dap_open_ap(ap->ap_num); if (retval != ERROR_OK) @@ -3972,20 +4276,15 @@ static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned reg, retval = stlink_read_dap_register(stlink_dap_handle, ap->ap_num, reg, data); dap->stlink_flush_ap_write = false; - return stlink_dap_record_error(retval); + return retval; } /** */ -static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned reg, - uint32_t data) +static int stlink_dap_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { struct adiv5_dap *dap = ap->dap; int retval; - retval = stlink_dap_check_reconnect(dap); - if (retval != ERROR_OK) - return retval; - retval = stlink_dap_open_ap(ap->ap_num); if (retval != ERROR_OK) return retval; @@ -3993,7 +4292,7 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned reg, retval = stlink_write_dap_register(stlink_dap_handle, ap->ap_num, reg, data); dap->stlink_flush_ap_write = true; - return stlink_dap_record_error(retval); + return retval; } /** */ @@ -4003,8 +4302,304 @@ static int stlink_dap_op_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) return ERROR_OK; } +#define RW_MISC_CMD_ADDRESS 1 +#define RW_MISC_CMD_WRITE 2 +#define RW_MISC_CMD_READ 3 +#define RW_MISC_CMD_APNUM 5 + +static int stlink_usb_misc_rw_segment(void *handle, const struct dap_queue *q, unsigned int len, unsigned int items) +{ + uint8_t buf[2 * 4 * items]; + + LOG_DEBUG("Queue: %u commands in %u items", len, items); + + int ap_num = DP_APSEL_INVALID; + unsigned int cmd_index = 0; + unsigned int val_index = ALIGN_UP(items, 4); + for (unsigned int i = 0; i < len; i++) { + if (ap_num != q[i].mem_ap.ap->ap_num) { + ap_num = q[i].mem_ap.ap->ap_num; + buf[cmd_index++] = RW_MISC_CMD_APNUM; + h_u32_to_le(&buf[val_index], ap_num); + val_index += 4; + } + + switch (q[i].cmd) { + case CMD_MEM_AP_READ32: + buf[cmd_index++] = RW_MISC_CMD_READ; + h_u32_to_le(&buf[val_index], q[i].mem_ap.addr); + val_index += 4; + break; + case CMD_MEM_AP_WRITE32: + buf[cmd_index++] = RW_MISC_CMD_ADDRESS; + h_u32_to_le(&buf[val_index], q[i].mem_ap.addr); + val_index += 4; + buf[cmd_index++] = RW_MISC_CMD_WRITE; + h_u32_to_le(&buf[val_index], q[i].mem_ap.data); + val_index += 4; + break; + default: + /* Not supposed to happen */ + return ERROR_FAIL; + } + } + /* pad after last command */ + while (!IS_ALIGNED(cmd_index, 4)) + buf[cmd_index++] = 0; + + int retval = stlink_usb_rw_misc_out(handle, items, buf); + if (retval != ERROR_OK) + return retval; + + retval = stlink_usb_rw_misc_in(handle, items, buf); + if (retval != ERROR_OK) + return retval; + + ap_num = DP_APSEL_INVALID; + val_index = 0; + unsigned int err_index = 4 * items; + for (unsigned int i = 0; i < len; i++) { + uint32_t errcode = le_to_h_u32(&buf[err_index]); + if (errcode != STLINK_DEBUG_ERR_OK) { + LOG_ERROR("unknown/unexpected STLINK status code 0x%x", errcode); + return ERROR_FAIL; + } + if (ap_num != q[i].mem_ap.ap->ap_num) { + ap_num = q[i].mem_ap.ap->ap_num; + err_index += 4; + val_index += 4; + errcode = le_to_h_u32(&buf[err_index]); + if (errcode != STLINK_DEBUG_ERR_OK) { + LOG_ERROR("unknown/unexpected STLINK status code 0x%x", errcode); + return ERROR_FAIL; + } + } + + if (q[i].cmd == CMD_MEM_AP_READ32) { + *q[i].mem_ap.p_data = le_to_h_u32(&buf[val_index]); + } else { /* q[i]->cmd == CMD_MEM_AP_WRITE32 */ + err_index += 4; + val_index += 4; + errcode = le_to_h_u32(&buf[err_index]); + if (errcode != STLINK_DEBUG_ERR_OK) { + LOG_ERROR("unknown/unexpected STLINK status code 0x%x", errcode); + return ERROR_FAIL; + } + } + err_index += 4; + val_index += 4; + } + + return ERROR_OK; +} + +static int stlink_usb_buf_rw_segment(void *handle, const struct dap_queue *q, unsigned int count) +{ + uint32_t bufsize = count * CMD_MEM_AP_2_SIZE(q[0].cmd); + uint8_t buf[bufsize]; + uint8_t ap_num = q[0].mem_ap.ap->ap_num; + uint32_t addr = q[0].mem_ap.addr; + uint32_t csw = q[0].mem_ap.csw; + + int retval = stlink_dap_open_ap(ap_num); + if (retval != ERROR_OK) + return retval; + + switch (q[0].cmd) { + case CMD_MEM_AP_WRITE8: + for (unsigned int i = 0; i < count; i++) + buf[i] = q[i].mem_ap.data >> 8 * (q[i].mem_ap.addr & 3); + return stlink_usb_write_mem8(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + + case CMD_MEM_AP_WRITE16: + for (unsigned int i = 0; i < count; i++) + h_u16_to_le(&buf[2 * i], q[i].mem_ap.data >> 8 * (q[i].mem_ap.addr & 2)); + return stlink_usb_write_mem16(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + + case CMD_MEM_AP_WRITE32: + for (unsigned int i = 0; i < count; i++) + h_u32_to_le(&buf[4 * i], q[i].mem_ap.data); + if (count > 1 && q[0].mem_ap.addr == q[1].mem_ap.addr) + return stlink_usb_write_mem32_noaddrinc(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + else + return stlink_usb_write_mem32(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + + case CMD_MEM_AP_READ8: + retval = stlink_usb_read_mem8(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + if (retval == ERROR_OK) + for (unsigned int i = 0; i < count; i++) + *q[i].mem_ap.p_data = buf[i] << 8 * (q[i].mem_ap.addr & 3); + return retval; + + case CMD_MEM_AP_READ16: + retval = stlink_usb_read_mem16(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + if (retval == ERROR_OK) + for (unsigned int i = 0; i < count; i++) + *q[i].mem_ap.p_data = le_to_h_u16(&buf[2 * i]) << 8 * (q[i].mem_ap.addr & 2); + return retval; + + case CMD_MEM_AP_READ32: + if (count > 1 && q[0].mem_ap.addr == q[1].mem_ap.addr) + retval = stlink_usb_read_mem32_noaddrinc(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + else + retval = stlink_usb_read_mem32(stlink_dap_handle, ap_num, csw, addr, bufsize, buf); + if (retval == ERROR_OK) + for (unsigned int i = 0; i < count; i++) + *q[i].mem_ap.p_data = le_to_h_u32(&buf[4 * i]); + return retval; + + default: + return ERROR_FAIL; + }; +} + +/* TODO: recover these values with cmd STLINK_DEBUG_APIV2_RW_MISC_GET_MAX (0x53) */ +#define STLINK_V2_RW_MISC_SIZE (64) +#define STLINK_V3_RW_MISC_SIZE (1227) + +static int stlink_usb_count_misc_rw_queue(void *handle, const struct dap_queue *q, unsigned int len, + unsigned int *pkt_items) +{ + struct stlink_usb_handle_s *h = handle; + unsigned int i, items = 0; + int ap_num = DP_APSEL_INVALID; + unsigned int misc_max_items = (h->version.stlink == 2) ? STLINK_V2_RW_MISC_SIZE : STLINK_V3_RW_MISC_SIZE; + + if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) + return 0; + /* + * RW_MISC sequence doesn't lock the st-link, so are not safe in shared mode. + * Don't use it with TCP backend to prevent any issue in case of sharing. + * This further degrades the performance, on top of TCP server overhead. + */ + if (h->backend == &stlink_tcp_backend) + return 0; + + for (i = 0; i < len; i++) { + if (q[i].cmd != CMD_MEM_AP_READ32 && q[i].cmd != CMD_MEM_AP_WRITE32) + break; + unsigned int count = 1; + if (ap_num != q[i].mem_ap.ap->ap_num) { + count++; + ap_num = q[i].mem_ap.ap->ap_num; + } + if (q[i].cmd == CMD_MEM_AP_WRITE32) + count++; + if (items + count > misc_max_items) + break; + items += count; + } + + *pkt_items = items; + + return i; +} + +static int stlink_usb_count_buf_rw_queue(const struct dap_queue *q, unsigned int len) +{ + uint32_t incr = CMD_MEM_AP_2_SIZE(q[0].cmd); + unsigned int len_max; + + if (incr == 1) + len_max = stlink_usb_block(stlink_dap_handle); + else + len_max = STLINK_MAX_RW16_32 / incr; + + /* check for no address increment, 32 bits only */ + if (len > 1 && incr == 4 && q[0].mem_ap.addr == q[1].mem_ap.addr) + incr = 0; + + if (len > len_max) + len = len_max; + + for (unsigned int i = 1; i < len; i++) + if (q[i].cmd != q[0].cmd || + q[i].mem_ap.ap != q[0].mem_ap.ap || + q[i].mem_ap.csw != q[0].mem_ap.csw || + q[i].mem_ap.addr != q[i - 1].mem_ap.addr + incr) + return i; + + return len; +} + +static int stlink_usb_mem_rw_queue(void *handle, const struct dap_queue *q, unsigned int len, unsigned int *skip) +{ + unsigned int count, misc_items = 0; + int retval; + + unsigned int count_misc = stlink_usb_count_misc_rw_queue(handle, q, len, &misc_items); + unsigned int count_buf = stlink_usb_count_buf_rw_queue(q, len); + + if (count_misc > count_buf) { + count = count_misc; + retval = stlink_usb_misc_rw_segment(handle, q, count, misc_items); + } else { + count = count_buf; + retval = stlink_usb_buf_rw_segment(handle, q, count_buf); + } + if (retval != ERROR_OK) + return retval; + + *skip = count; + return ERROR_OK; +} + +static void stlink_dap_run_internal(struct adiv5_dap *dap) +{ + int retval = stlink_dap_check_reconnect(dap); + if (retval != ERROR_OK) { + stlink_dap_handle->queue_index = 0; + stlink_dap_record_error(retval); + return; + } + + unsigned int i = stlink_dap_handle->queue_index; + struct dap_queue *q = &stlink_dap_handle->queue[0]; + + while (i && stlink_dap_get_error() == ERROR_OK) { + unsigned int skip = 1; + + switch (q->cmd) { + case CMD_DP_READ: + retval = stlink_dap_dp_read(q->dp_r.dap, q->dp_r.reg, q->dp_r.p_data); + break; + case CMD_DP_WRITE: + retval = stlink_dap_dp_write(q->dp_w.dap, q->dp_w.reg, q->dp_w.data); + break; + case CMD_AP_READ: + retval = stlink_dap_ap_read(q->ap_r.ap, q->ap_r.reg, q->ap_r.p_data); + break; + case CMD_AP_WRITE: + /* ignore increment packed, not supported */ + if (q->ap_w.reg == MEM_AP_REG_CSW) + q->ap_w.data &= ~CSW_ADDRINC_PACKED; + retval = stlink_dap_ap_write(q->ap_w.ap, q->ap_w.reg, q->ap_w.data); + break; + + case CMD_MEM_AP_READ8: + case CMD_MEM_AP_READ16: + case CMD_MEM_AP_READ32: + case CMD_MEM_AP_WRITE8: + case CMD_MEM_AP_WRITE16: + case CMD_MEM_AP_WRITE32: + retval = stlink_usb_mem_rw_queue(stlink_dap_handle, q, i, &skip); + break; + + default: + LOG_ERROR("ST-Link: Unknown queue command %d", q->cmd); + retval = ERROR_FAIL; + break; + } + stlink_dap_record_error(retval); + q += skip; + i -= skip; + } + + stlink_dap_handle->queue_index = 0; +} + /** */ -static int stlink_dap_op_run(struct adiv5_dap *dap) +static int stlink_dap_run_finalize(struct adiv5_dap *dap) { uint32_t ctrlstat, pwrmask; int retval, saved_retval; @@ -4019,7 +4614,7 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) */ if (dap->stlink_flush_ap_write) { dap->stlink_flush_ap_write = false; - retval = stlink_dap_op_queue_dp_read(dap, DP_RDBUFF, NULL); + retval = stlink_dap_dp_read(dap, DP_RDBUFF, NULL); if (retval != ERROR_OK) { dap->do_reconnect = true; return retval; @@ -4028,12 +4623,7 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) saved_retval = stlink_dap_get_and_clear_error(); - retval = stlink_dap_op_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat); - if (retval != ERROR_OK) { - dap->do_reconnect = true; - return retval; - } - retval = stlink_dap_get_and_clear_error(); + retval = stlink_dap_dp_read(dap, DP_CTRL_STAT, &ctrlstat); if (retval != ERROR_OK) { LOG_ERROR("Fail reading CTRL/STAT register. Force reconnect"); dap->do_reconnect = true; @@ -4042,15 +4632,10 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) if (ctrlstat & SSTICKYERR) { if (stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG) - retval = stlink_dap_op_queue_dp_write(dap, DP_CTRL_STAT, + retval = stlink_dap_dp_write(dap, DP_CTRL_STAT, ctrlstat & (dap->dp_ctrl_stat | SSTICKYERR)); else - retval = stlink_dap_op_queue_dp_write(dap, DP_ABORT, STKERRCLR); - if (retval != ERROR_OK) { - dap->do_reconnect = true; - return retval; - } - retval = stlink_dap_get_and_clear_error(); + retval = stlink_dap_dp_write(dap, DP_ABORT, STKERRCLR); if (retval != ERROR_OK) { dap->do_reconnect = true; return retval; @@ -4065,6 +4650,12 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) return saved_retval; } +static int stlink_dap_op_queue_run(struct adiv5_dap *dap) +{ + stlink_dap_run_internal(dap); + return stlink_dap_run_finalize(dap); +} + /** */ static void stlink_dap_op_quit(struct adiv5_dap *dap) { @@ -4075,6 +4666,182 @@ static void stlink_dap_op_quit(struct adiv5_dap *dap) LOG_ERROR("Error closing APs"); } +static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, + uint32_t *data) +{ + if (stlink_dap_get_error() != ERROR_OK) + return ERROR_OK; + + unsigned int i = stlink_dap_handle->queue_index++; + struct dap_queue *q = &stlink_dap_handle->queue[i]; + q->cmd = CMD_DP_READ; + q->dp_r.reg = reg; + q->dp_r.dap = dap; + q->dp_r.p_data = data; + + if (i == MAX_QUEUE_DEPTH - 1) + stlink_dap_run_internal(dap); + + return ERROR_OK; +} + +static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, + uint32_t data) +{ + if (stlink_dap_get_error() != ERROR_OK) + return ERROR_OK; + + unsigned int i = stlink_dap_handle->queue_index++; + struct dap_queue *q = &stlink_dap_handle->queue[i]; + q->cmd = CMD_DP_WRITE; + q->dp_w.reg = reg; + q->dp_w.dap = dap; + q->dp_w.data = data; + + if (i == MAX_QUEUE_DEPTH - 1) + stlink_dap_run_internal(dap); + + return ERROR_OK; +} + +static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, + uint32_t *data) +{ + if (stlink_dap_get_error() != ERROR_OK) + return ERROR_OK; + + unsigned int i = stlink_dap_handle->queue_index++; + struct dap_queue *q = &stlink_dap_handle->queue[i]; + + /* test STLINK_F_HAS_CSW implicitly tests STLINK_F_HAS_MEM_16BIT, STLINK_F_HAS_MEM_RD_NO_INC + * and STLINK_F_HAS_RW_MISC */ + if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) && + (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 || + reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) { + /* de-queue previous write-TAR */ + struct dap_queue *prev_q = q - 1; + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) { + stlink_dap_handle->queue_index = i; + i--; + q = prev_q; + prev_q--; + } + /* de-queue previous write-CSW if it didn't changed ap->csw_default */ + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + !prev_q->ap_w.changes_csw_default) { + stlink_dap_handle->queue_index = i; + q = prev_q; + } + + switch (ap->csw_value & CSW_SIZE_MASK) { + case CSW_8BIT: + q->cmd = CMD_MEM_AP_READ8; + break; + case CSW_16BIT: + q->cmd = CMD_MEM_AP_READ16; + break; + case CSW_32BIT: + q->cmd = CMD_MEM_AP_READ32; + break; + default: + LOG_ERROR("ST-Link: Unsupported CSW size %d", ap->csw_value & CSW_SIZE_MASK); + stlink_dap_record_error(ERROR_FAIL); + return ERROR_FAIL; + } + + q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); + q->mem_ap.ap = ap; + q->mem_ap.p_data = data; + q->mem_ap.csw = ap->csw_default; + + /* force TAR and CSW update */ + ap->tar_valid = false; + ap->csw_value = 0; + } else { + q->cmd = CMD_AP_READ; + q->ap_r.reg = reg; + q->ap_r.ap = ap; + q->ap_r.p_data = data; + } + + if (i == MAX_QUEUE_DEPTH - 1) + stlink_dap_run_internal(ap->dap); + + return ERROR_OK; +} + +static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, + uint32_t data) +{ + if (stlink_dap_get_error() != ERROR_OK) + return ERROR_OK; + + unsigned int i = stlink_dap_handle->queue_index++; + struct dap_queue *q = &stlink_dap_handle->queue[i]; + + /* test STLINK_F_HAS_CSW implicitly tests STLINK_F_HAS_MEM_16BIT, STLINK_F_HAS_MEM_WR_NO_INC + * and STLINK_F_HAS_RW_MISC */ + if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) && + (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 || + reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) { + /* de-queue previous write-TAR */ + struct dap_queue *prev_q = q - 1; + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) { + stlink_dap_handle->queue_index = i; + i--; + q = prev_q; + prev_q--; + } + /* de-queue previous write-CSW if it didn't changed ap->csw_default */ + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + !prev_q->ap_w.changes_csw_default) { + stlink_dap_handle->queue_index = i; + q = prev_q; + } + + switch (ap->csw_value & CSW_SIZE_MASK) { + case CSW_8BIT: + q->cmd = CMD_MEM_AP_WRITE8; + break; + case CSW_16BIT: + q->cmd = CMD_MEM_AP_WRITE16; + break; + case CSW_32BIT: + q->cmd = CMD_MEM_AP_WRITE32; + break; + default: + LOG_ERROR("ST-Link: Unsupported CSW size %d", ap->csw_value & CSW_SIZE_MASK); + stlink_dap_record_error(ERROR_FAIL); + return ERROR_FAIL; + } + + q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); + q->mem_ap.ap = ap; + q->mem_ap.data = data; + q->mem_ap.csw = ap->csw_default; + + /* force TAR and CSW update */ + ap->tar_valid = false; + ap->csw_value = 0; + } else { + q->cmd = CMD_AP_WRITE; + q->ap_w.reg = reg; + q->ap_w.ap = ap; + q->ap_w.data = data; + if (reg == MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) { + q->ap_w.changes_csw_default = true; + last_csw_default[ap->ap_num] = ap->csw_default; + } else { + q->ap_w.changes_csw_default = false; + } + } + + if (i == MAX_QUEUE_DEPTH - 1) + stlink_dap_run_internal(ap->dap); + + return ERROR_OK; +} + static int stlink_swim_op_srst(void) { return stlink_swim_generate_rst(stlink_dap_handle); @@ -4090,7 +4857,7 @@ static int stlink_swim_op_read_mem(uint32_t addr, uint32_t size, count *= size; while (count) { - bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count; + bytes_remaining = (count > STLINK_SWIM_DATA_SIZE) ? STLINK_SWIM_DATA_SIZE : count; retval = stlink_swim_readbytes(stlink_dap_handle, addr, bytes_remaining, buffer); if (retval != ERROR_OK) return retval; @@ -4113,7 +4880,7 @@ static int stlink_swim_op_write_mem(uint32_t addr, uint32_t size, count *= size; while (count) { - bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count; + bytes_remaining = (count > STLINK_SWIM_DATA_SIZE) ? STLINK_SWIM_DATA_SIZE : count; retval = stlink_swim_writebytes(stlink_dap_handle, addr, bytes_remaining, buffer); if (retval != ERROR_OK) return retval; @@ -4152,25 +4919,6 @@ static int stlink_dap_trace_read(uint8_t *buf, size_t *size) return stlink_usb_trace_read(stlink_dap_handle, buf, size); } -/** */ -COMMAND_HANDLER(stlink_dap_serial_command) -{ - LOG_DEBUG("stlink_dap_serial_command"); - - if (CMD_ARGC != 1) { - LOG_ERROR("Expected exactly one argument for \"st-link serial \"."); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - if (stlink_dap_param.serial) { - LOG_WARNING("Command \"st-link serial\" already used. Replacing previous value"); - free((void *)stlink_dap_param.serial); - } - - stlink_dap_param.serial = strdup(CMD_ARGV[0]); - return ERROR_OK; -} - /** */ COMMAND_HANDLER(stlink_dap_vid_pid) { @@ -4261,13 +5009,6 @@ COMMAND_HANDLER(stlink_dap_cmd_command) /** */ static const struct command_registration stlink_dap_subcommand_handlers[] = { - { - .name = "serial", - .handler = stlink_dap_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the adapter", - .usage = "", - }, { .name = "vid_pid", .handler = stlink_dap_vid_pid, @@ -4348,9 +5089,6 @@ static int stlink_dap_quit(void) { LOG_DEBUG("stlink_dap_quit()"); - free((void *)stlink_dap_param.serial); - stlink_dap_param.serial = NULL; - return stlink_close(stlink_dap_handle); } @@ -4403,7 +5141,7 @@ static const struct dap_ops stlink_dap_ops = { .queue_ap_read = stlink_dap_op_queue_ap_read, .queue_ap_write = stlink_dap_op_queue_ap_write, .queue_ap_abort = stlink_dap_op_queue_ap_abort, - .run = stlink_dap_op_run, + .run = stlink_dap_op_queue_run, .sync = NULL, /* optional */ .quit = stlink_dap_op_quit, /* optional */ }; diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index d911fdacb..c94a1102f 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -23,6 +23,7 @@ /* project specific includes */ #include +#include #include #include #include @@ -681,11 +682,11 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd) for (uint8_t i = 0; param->vid[i] && param->pid[i]; ++i) LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", param->transport, - param->vid[i], param->pid[i], param->serial ? param->serial : ""); + param->vid[i], param->pid[i], adapter_get_required_serial() ? adapter_get_required_serial() : ""); /* TI (Stellaris) ICDI provides its serial number in the USB descriptor; no need to provide a callback here. */ - jtag_libusb_open(param->vid, param->pid, param->serial, &h->usb_dev, NULL); + jtag_libusb_open(param->vid, param->pid, &h->usb_dev, NULL); if (!h->usb_dev) { LOG_ERROR("open failed"); diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index d55bf85cd..21f9ae72b 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -210,7 +210,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) bool renumeration = false; int ret; - if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) { + if (jtag_libusb_open(vids, pids, &temp, NULL) == ERROR_OK) { LOG_INFO("Altera USB-Blaster II (uninitialized) found"); LOG_INFO("Loading firmware..."); ret = load_usb_blaster_firmware(temp, low); @@ -224,15 +224,13 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) const uint16_t pids_renum[] = { low->ublast_pid, 0 }; if (renumeration == false) { - if (jtag_libusb_open(vids_renum, pids_renum, NULL, - &low->libusb_dev, NULL) != ERROR_OK) { + if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK) { LOG_ERROR("Altera USB-Blaster II not found"); return ERROR_FAIL; } } else { int retry = 10; - while (jtag_libusb_open(vids_renum, pids_renum, NULL, - &low->libusb_dev, NULL) != ERROR_OK && retry--) { + while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK && retry--) { usleep(1000000); LOG_INFO("Waiting for reenumerate..."); } diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index ad20d65d4..ada764c1c 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -36,7 +36,6 @@ struct ublast_lowlevel { uint16_t ublast_pid; uint16_t ublast_vid_uninit; uint16_t ublast_pid_uninit; - char *ublast_device_desc; struct libusb_device_handle *libusb_dev; char *firmware_path; diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index cc1d4758f..049a24378 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -119,7 +119,6 @@ struct ublast_info { char *lowlevel_name; struct ublast_lowlevel *drv; - char *ublast_device_desc; uint16_t ublast_vid, ublast_pid; uint16_t ublast_vid_uninit, ublast_pid_uninit; int flags; @@ -140,7 +139,7 @@ static struct ublast_info info = { }; /* - * Available lowlevel drivers (FTDI, FTD2xx, ...) + * Available lowlevel drivers (FTDI, libusb, ...) */ struct drvs_map { char *name; @@ -874,7 +873,6 @@ static int ublast_init(void) info.drv->ublast_pid = info.ublast_pid; info.drv->ublast_vid_uninit = info.ublast_vid_uninit; info.drv->ublast_pid_uninit = info.ublast_pid_uninit; - info.drv->ublast_device_desc = info.ublast_device_desc; info.drv->firmware_path = info.firmware_path; info.flags |= info.drv->flags; @@ -908,16 +906,6 @@ static int ublast_quit(void) return info.drv->close(info.drv); } -COMMAND_HANDLER(ublast_handle_device_desc_command) -{ - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - info.ublast_device_desc = strdup(CMD_ARGV[0]); - - return ERROR_OK; -} - COMMAND_HANDLER(ublast_handle_vid_pid_command) { if (CMD_ARGC > 4) { @@ -1031,13 +1019,6 @@ COMMAND_HANDLER(ublast_firmware_command) static const struct command_registration ublast_subcommand_handlers[] = { - { - .name = "device_desc", - .handler = ublast_handle_device_desc_command, - .mode = COMMAND_CONFIG, - .help = "set the USB device description of the USB-Blaster", - .usage = "description-string", - }, { .name = "vid_pid", .handler = ublast_handle_vid_pid_command, diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 44db61ec0..a2ebdbc86 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -354,7 +354,7 @@ struct usbprog_jtag *usbprog_jtag_open(void) const uint16_t pids[] = { PID, 0 }; struct libusb_device_handle *dev; - if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK) + if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK) return NULL; struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag)); diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c index b17c1d49b..7c2efefaa 100644 --- a/src/jtag/drivers/versaloon/versaloon.c +++ b/src/jtag/drivers/versaloon/versaloon.c @@ -87,7 +87,6 @@ struct versaloon_interface_t versaloon_interface = { .ep_out = VERSALOON_OUTP, .ep_in = VERSALOON_INP, .interface = VERSALOON_IFACE, - .serialstring = NULL, .buf_size = 256, } }; diff --git a/src/jtag/drivers/versaloon/versaloon.h b/src/jtag/drivers/versaloon/versaloon.h index 22e73fb35..e4aafb250 100644 --- a/src/jtag/drivers/versaloon/versaloon.h +++ b/src/jtag/drivers/versaloon/versaloon.h @@ -94,8 +94,6 @@ struct versaloon_usb_setting_t { uint8_t ep_out; uint8_t ep_in; uint8_t interface; - char *serialstring; - uint16_t buf_size; }; diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 7325f6abc..f59a7033e 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -24,6 +24,7 @@ #include "config.h" #endif +#include #include #include #include @@ -323,7 +324,7 @@ static int vsllink_init(void) versaloon_interface.adaptors.gpio.config(0, GPIO_TRST, 0, GPIO_TRST, GPIO_TRST); versaloon_interface.adaptors.swd.init(0); - vsllink_swd_frequency(jtag_get_speed_khz() * 1000); + vsllink_swd_frequency(adapter_get_speed_khz() * 1000); vsllink_swd_switch_seq(JTAG_TO_SWD); } else { @@ -339,7 +340,7 @@ static int vsllink_init(void) } versaloon_interface.adaptors.jtag_raw.init(0); - versaloon_interface.adaptors.jtag_raw.config(0, jtag_get_speed_khz()); + versaloon_interface.adaptors.jtag_raw.config(0, adapter_get_speed_khz()); versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST, GPIO_TRST, GPIO_SRST, GPIO_SRST); } @@ -498,21 +499,6 @@ COMMAND_HANDLER(vsllink_handle_usb_pid_command) return ERROR_OK; } -COMMAND_HANDLER(vsllink_handle_usb_serial_command) -{ - if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - free(versaloon_interface.usb_setting.serialstring); - - if (CMD_ARGC == 1) - versaloon_interface.usb_setting.serialstring = strdup(CMD_ARGV[0]); - else - versaloon_interface.usb_setting.serialstring = NULL; - - return ERROR_OK; -} - COMMAND_HANDLER(vsllink_handle_usb_bulkin_command) { if (CMD_ARGC != 1) @@ -785,14 +771,14 @@ static int vsllink_check_usb_strings( char desc_string[256]; int retval; - if (versaloon_interface.usb_setting.serialstring) { + if (adapter_get_required_serial()) { retval = libusb_get_string_descriptor_ascii(usb_device_handle, usb_desc->iSerialNumber, (unsigned char *)desc_string, sizeof(desc_string)); if (retval < 0) return ERROR_FAIL; - if (strncmp(desc_string, versaloon_interface.usb_setting.serialstring, + if (strncmp(desc_string, adapter_get_required_serial(), sizeof(desc_string))) return ERROR_FAIL; } @@ -902,13 +888,6 @@ static const struct command_registration vsllink_subcommand_handlers[] = { .help = "Set USB PID", .usage = "", }, - { - .name = "usb_serial", - .handler = &vsllink_handle_usb_serial_command, - .mode = COMMAND_CONFIG, - .help = "Set or disable check for USB serial", - .usage = "[]", - }, { .name = "usb_bulkin", .handler = &vsllink_handle_usb_bulkin_command, diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index 243577d7c..c5249b296 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -20,15 +20,13 @@ #endif #include +#include #include #include #include #include #include -/* XDS110 USB serial number length */ -#define XDS110_SERIAL_LEN 8 - /* XDS110 stand-alone probe voltage supply limits */ #define XDS110_MIN_VOLTAGE 1800 #define XDS110_MAX_VOLTAGE 3600 @@ -238,8 +236,6 @@ struct xds110_info { /* TCK speed and delay count*/ uint32_t speed; uint32_t delay_count; - /* XDS110 serial number */ - char serial[XDS110_SERIAL_LEN + 1]; /* XDS110 voltage supply setting */ uint32_t voltage; /* XDS110 firmware and hardware version */ @@ -269,7 +265,6 @@ static struct xds110_info xds110 = { .is_ap_dirty = false, .speed = XDS110_DEFAULT_TCK_SPEED, .delay_count = 0, - .serial = {0}, .voltage = 0, .firmware = 0, .hardware = 0, @@ -371,7 +366,7 @@ static bool usb_connect(void) *data = '\0'; /* May be the requested device if serial number matches */ - if (xds110.serial[0] == 0) { + if (!adapter_get_required_serial()) { /* No serial number given; match first XDS110 found */ found = true; break; @@ -380,7 +375,7 @@ static bool usb_connect(void) result = libusb_get_string_descriptor_ascii(dev, desc.iSerialNumber, data, max_data); if (result > 0 && - strcmp((char *)data, (char *)xds110.serial) == 0) { + strcmp((char *)data, adapter_get_required_serial()) == 0) { found = true; break; } @@ -1395,8 +1390,8 @@ static void xds110_show_info(void) (((firmware >> 12) & 0xf) * 10) + ((firmware >> 8) & 0xf), (((firmware >> 4) & 0xf) * 10) + ((firmware >> 0) & 0xf)); LOG_INFO("XDS110: hardware version = 0x%04x", xds110.hardware); - if (xds110.serial[0] != 0) - LOG_INFO("XDS110: serial number = %s", xds110.serial); + if (adapter_get_required_serial()) + LOG_INFO("XDS110: serial number = %s", adapter_get_required_serial()); if (xds110.is_swd_mode) { LOG_INFO("XDS110: connected to target via SWD"); LOG_INFO("XDS110: SWCLK set to %" PRIu32 " kHz", xds110.speed); @@ -2024,34 +2019,6 @@ COMMAND_HANDLER(xds110_handle_info_command) return ERROR_OK; } -COMMAND_HANDLER(xds110_handle_serial_command) -{ - wchar_t serial[XDS110_SERIAL_LEN + 1]; - - xds110.serial[0] = 0; - - if (CMD_ARGC == 1) { - size_t len = mbstowcs(0, CMD_ARGV[0], 0); - if (len > XDS110_SERIAL_LEN) { - LOG_ERROR("XDS110: serial number is limited to %d characters", - XDS110_SERIAL_LEN); - return ERROR_FAIL; - } - if ((size_t)-1 == mbstowcs(serial, CMD_ARGV[0], len + 1)) { - LOG_ERROR("XDS110: unable to convert serial number"); - return ERROR_FAIL; - } - - for (uint32_t i = 0; i < len; i++) - xds110.serial[i] = (char)serial[i]; - - xds110.serial[len] = 0; - } else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - COMMAND_HANDLER(xds110_handle_supply_voltage_command) { uint32_t voltage = 0; @@ -2082,13 +2049,6 @@ static const struct command_registration xds110_subcommand_handlers[] = { .help = "show XDS110 info", .usage = "", }, - { - .name = "serial", - .handler = &xds110_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the XDS110 probe serial number", - .usage = "serial_string", - }, { .name = "supply", .handler = &xds110_handle_supply_voltage_command, diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index fc362c040..074e3c2fb 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -38,7 +38,6 @@ static struct hl_interface_s hl_if = { .param = { .device_desc = NULL, - .serial = NULL, .vid = { 0 }, .pid = { 0 }, .transport = HL_TRANSPORT_UNKNOWN, @@ -136,7 +135,6 @@ static int hl_interface_quit(void) jtag_command_queue_reset(); free((void *)hl_if.param.device_desc); - free((void *)hl_if.param.serial); return ERROR_OK; } @@ -238,19 +236,6 @@ COMMAND_HANDLER(hl_interface_handle_device_desc_command) return ERROR_OK; } -COMMAND_HANDLER(hl_interface_handle_serial_command) -{ - LOG_DEBUG("hl_interface_handle_serial_command"); - - if (CMD_ARGC == 1) { - hl_if.param.serial = strdup(CMD_ARGV[0]); - } else { - LOG_ERROR("expected exactly one argument to hl_serial "); - } - - return ERROR_OK; -} - COMMAND_HANDLER(hl_interface_handle_layout_command) { LOG_DEBUG("hl_interface_handle_layout_command"); @@ -354,13 +339,6 @@ static const struct command_registration hl_interface_command_handlers[] = { .help = "set the device description of the adapter", .usage = "description_string", }, - { - .name = "hla_serial", - .handler = &hl_interface_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the adapter", - .usage = "serial_string", - }, { .name = "hla_layout", .handler = &hl_interface_handle_layout_command, diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index c882acf48..31d055a3c 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -34,8 +34,6 @@ extern const char *hl_transports[]; struct hl_interface_param_s { /** */ const char *device_desc; - /** */ - const char *serial; /** List of recognised VIDs */ uint16_t vid[HLA_MAX_USB_IDS + 1]; /** List of recognised PIDs */ diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h index a8088fe95..732fe1e6a 100644 --- a/src/jtag/hla/hla_layout.h +++ b/src/jtag/hla/hla_layout.h @@ -23,6 +23,7 @@ #define OPENOCD_JTAG_HLA_HLA_LAYOUT_H #include +#include /** */ struct hl_interface_s; diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index d925b174a..58dfe4b63 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -45,8 +45,7 @@ COMMAND_HANDLER(hl_transport_reset_command) return hl_interface_init_reset(); } -static const struct command_registration -hl_swd_transport_subcommand_handlers[] = { +static const struct command_registration hl_swd_transport_subcommand_handlers[] = { { .name = "newdap", .mode = COMMAND_CONFIG, @@ -67,8 +66,7 @@ static const struct command_registration hl_swd_transport_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const struct command_registration -hl_transport_jtag_subcommand_handlers[] = { +static const struct command_registration hl_transport_jtag_subcommand_handlers[] = { { .name = "newtap", .mode = COMMAND_CONFIG, @@ -196,15 +194,13 @@ static int hl_jtag_transport_select(struct command_context *cmd_ctx) * That works with only C code ... no Tcl glue required. */ - return register_commands(cmd_ctx, NULL, - hl_jtag_transport_command_handlers); + return register_commands(cmd_ctx, NULL, hl_jtag_transport_command_handlers); } static int hl_swd_transport_select(struct command_context *cmd_ctx) { LOG_DEBUG("hl_swd_transport_select"); - return register_commands(cmd_ctx, NULL, - hl_swd_transport_command_handlers); + return register_commands(cmd_ctx, NULL, hl_swd_transport_command_handlers); } static struct transport hl_swd_transport = { diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index feb4614fa..d7d7d977c 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -217,31 +217,6 @@ int jtag_unregister_event_callback(jtag_event_handler_t f, void *x); int jtag_call_event_callbacks(enum jtag_event event); - -/** @returns The current JTAG speed setting. */ -int jtag_get_speed(int *speed); - -/** - * Given a @a speed setting, use the interface @c speed_div callback to - * adjust the setting. - * @param speed The speed setting to convert back to readable KHz. - * @returns ERROR_OK if the interface has not been initialized or on success; - * otherwise, the error code produced by the @c speed_div callback. - */ -int jtag_get_speed_readable(int *speed); - -/** Attempt to configure the interface for the specified KHz. */ -int jtag_config_khz(unsigned khz); - -/** - * Attempt to enable RTCK/RCLK. If that fails, fallback to the - * specified frequency. - */ -int jtag_config_rclk(unsigned fallback_speed_khz); - -/** Retrieves the clock speed of the JTAG interface in KHz. */ -unsigned jtag_get_speed_khz(void); - enum reset_types { RESET_NONE = 0x0, RESET_HAS_TRST = 0x1, @@ -285,12 +260,6 @@ void jtag_set_verify_capture_ir(bool enable); /** @returns True if IR scan verification will be performed. */ bool jtag_will_verify_capture_ir(void); -/** Initialize debug adapter upon startup. */ -int adapter_init(struct command_context *cmd_ctx); - -/** Shutdown the debug adapter upon program exit. */ -int adapter_quit(void); - /** Set ms to sleep after jtag_execute_queue() flushes queue. Debug purposes. */ void jtag_set_flush_queue_sleep(int ms); diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index d5b2ae221..ee116269e 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -187,8 +187,8 @@ proc ftdi_location args { lappend _telnet_autocomplete_skip xds110_serial proc xds110_serial args { - echo "DEPRECATED! use 'xds110 serial' not 'xds110_serial'" - eval xds110 serial $args + echo "DEPRECATED! use 'adapter serial' not 'xds110_serial'" + eval adapter serial $args } lappend _telnet_autocomplete_skip xds110_supply_voltage @@ -215,8 +215,8 @@ proc ftdi_device_desc args { lappend _telnet_autocomplete_skip ftdi_serial proc ftdi_serial args { - echo "DEPRECATED! use 'ftdi serial' not 'ftdi_serial'" - eval ftdi serial $args + echo "DEPRECATED! use 'adapter serial' not 'ftdi_serial'" + eval adapter serial $args } lappend _telnet_autocomplete_skip ftdi_channel @@ -371,8 +371,8 @@ proc vsllink_usb_pid args { lappend _telnet_autocomplete_skip vsllink_usb_serial proc vsllink_usb_serial args { - echo "DEPRECATED! use 'vsllink usb_serial' not 'vsllink_usb_serial'" - eval vsllink usb_serial $args + echo "DEPRECATED! use 'adapter serial' not 'vsllink_usb_serial'" + eval adapter serial $args } lappend _telnet_autocomplete_skip vsllink_usb_bulkin @@ -677,8 +677,8 @@ proc usb_blaster_firmware args { lappend _telnet_autocomplete_skip ft232r_serial_desc proc ft232r_serial_desc args { - echo "DEPRECATED! use 'ft232r serial_desc' not 'ft232r_serial_desc'" - eval ft232r serial_desc $args + echo "DEPRECATED! use 'adapter serial_desc' not 'ft232r_serial_desc'" + eval adapter serial_desc $args } lappend _telnet_autocomplete_skip ft232r_vid_pid @@ -735,4 +735,70 @@ proc ft232r_restore_serial args { eval ft232r restore_serial $args } +lappend _telnet_autocomplete_skip "aice serial" +proc "aice serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'aice serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip cmsis_dap_serial +proc cmsis_dap_serial args { + echo "DEPRECATED! use 'adapter serial' not 'cmsis_dap_serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "ft232r serial_desc" +proc "ft232r serial_desc" {args} { + echo "DEPRECATED! use 'adapter serial' not 'ft232r serial_desc'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "ftdi serial" +proc "ftdi serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'ftdi serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip hla_serial +proc hla_serial args { + echo "DEPRECATED! use 'adapter serial' not 'hla_serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "jlink serial" +proc "jlink serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'jlink serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip kitprog_serial +proc kitprog_serial args { + echo "DEPRECATED! use 'adapter serial' not 'kitprog_serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "presto serial" +proc "presto serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'presto serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "st-link serial" +proc "st-link serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'st-link serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "vsllink usb_serial" +proc "vsllink usb_serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'vsllink usb_serial'" + eval adapter serial $args +} + +lappend _telnet_autocomplete_skip "xds110 serial" +proc "xds110 serial" {args} { + echo "DEPRECATED! use 'adapter serial' not 'xds110 serial'" + eval adapter serial $args +} + # END MIGRATION AIDS diff --git a/src/jtag/swd.h b/src/jtag/swd.h index fe28667c6..8a436d0c6 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -18,6 +18,7 @@ #ifndef OPENOCD_JTAG_SWD_H #define OPENOCD_JTAG_SWD_H +#include #include /* Bits in SWD command packets, written from host to target @@ -32,6 +33,12 @@ #define SWD_CMD_PARK (1 << 7) /* driven high by host */ /* followed by TRN, 3-bits of ACK, TRN */ +/* + * The SWD subsystem error codes + */ +#define ERROR_SWD_FAIL (-400) /** protocol or parity error */ +#define ERROR_SWD_FAULT (-401) /** device returned FAULT in ACK field */ + /** * Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg() * and swd_driver.write_reg() methods will use directly. @@ -53,6 +60,40 @@ static inline uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum) /* SWD_ACK_* bits are defined in */ +/** + * Test if we can rely on ACK returned by SWD command + * + * @param cmd Byte constructed by swd_cmd(), START, STOP and TRN are filtered off + * @returns true if ACK should be checked, false if should be ignored + */ +static inline bool swd_cmd_returns_ack(uint8_t cmd) +{ + uint8_t base_cmd = cmd & (SWD_CMD_APNDP | SWD_CMD_RNW | SWD_CMD_A32); + + /* DPv2 does not reply to DP_TARGETSEL write cmd */ + return base_cmd != swd_cmd(false, false, DP_TARGETSEL); +} + +/** + * Convert SWD ACK value returned from DP to OpenOCD error code + * + * @param ack + * @returns error code + */ +static inline int swd_ack_to_error_code(uint8_t ack) +{ + switch (ack) { + case SWD_ACK_OK: + return ERROR_OK; + case SWD_ACK_WAIT: + return ERROR_WAIT; + case SWD_ACK_FAULT: + return ERROR_SWD_FAULT; + default: + return ERROR_SWD_FAIL; + } +} + /* * The following sequences are updated to * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031E diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 6d3fee43c..566c406b9 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -30,6 +30,7 @@ #include "config.h" #endif +#include "adapter.h" #include "jtag.h" #include "swd.h" #include "minidriver.h" @@ -1040,13 +1041,13 @@ COMMAND_HANDLER(handle_jtag_rclk_command) unsigned khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); - retval = jtag_config_rclk(khz); + retval = adapter_config_rclk(khz); if (retval != ERROR_OK) return retval; } - int cur_khz = jtag_get_speed_khz(); - retval = jtag_get_speed_readable(&cur_khz); + int cur_khz = adapter_get_speed_khz(); + retval = adapter_get_speed_readable(&cur_khz); if (retval != ERROR_OK) return retval; diff --git a/src/openocd.c b/src/openocd.c index 12bd52c58..0292ba445 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -27,7 +27,7 @@ #endif #include "openocd.h" -#include +#include #include #include #include @@ -312,7 +312,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) &log_register_commands, &rtt_server_register_commands, &transport_register_commands, - &interface_register_commands, + &adapter_register_commands, &target_register_commands, &flash_register_commands, &nand_register_commands, diff --git a/src/pld/pld.c b/src/pld/pld.c index d0f85d74b..fe21f6c85 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -67,8 +67,7 @@ COMMAND_HANDLER(handle_pld_device_command) /* register pld specific commands */ int retval; if (pld_drivers[i]->commands) { - retval = register_commands(CMD_CTX, NULL, - pld_drivers[i]->commands); + retval = register_commands(CMD_CTX, NULL, pld_drivers[i]->commands); if (retval != ERROR_OK) { LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]); return ERROR_FAIL; diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 465dd6711..d338a479f 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -424,7 +424,7 @@ const struct rtos_register_stacking rtos_standard_cortex_m3_stacking = { }; const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking = { - .stack_registers_size = 0x44, /* 4 more for LR*/ + .stack_registers_size = 0x44, .stack_growth_direction = -1, .num_output_registers = ARMV7M_NUM_CORE_REGS, .calculate_process_stack = rtos_standard_cortex_m4f_stack_align, @@ -432,7 +432,7 @@ const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking = { }; const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking = { - .stack_registers_size = 0xcc, /* 4 more for LR + 48 more for FPU S0-S15 register*/ + .stack_registers_size = 0xcc, .stack_growth_direction = -1, .num_output_registers = ARMV7M_NUM_CORE_REGS, .calculate_process_stack = rtos_standard_cortex_m4f_fpu_stack_align, diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index a21bf25b9..c23cee157 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -53,8 +53,24 @@ #include +/* for debug, set do_sync to true to force synchronous transfers */ static bool do_sync; +static struct adiv5_dap *swd_multidrop_selected_dap; + + +static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, + uint32_t data); + + +static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + assert(swd); + + return swd->switch_seq(seq); +} + static void swd_finish_read(struct adiv5_dap *dap) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); @@ -64,11 +80,6 @@ static void swd_finish_read(struct adiv5_dap *dap) } } -static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, - uint32_t data); -static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, - uint32_t *data); - static void swd_clear_sticky_errors(struct adiv5_dap *dap) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); @@ -93,17 +104,264 @@ static int swd_run_inner(struct adiv5_dap *dap) return retval; } -static int swd_connect(struct adiv5_dap *dap) +static inline int check_sync(struct adiv5_dap *dap) +{ + return do_sync ? swd_run_inner(dap) : ERROR_OK; +} + +/** Select the DP register bank matching bits 7:4 of reg. */ +static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg) +{ + /* Only register address 4 is banked. */ + if ((reg & 0xf) != 4) + return ERROR_OK; + + uint32_t select_dp_bank = (reg & 0x000000F0) >> 4; + uint32_t sel = select_dp_bank + | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK)); + + if (sel == dap->select) + return ERROR_OK; + + dap->select = sel; + + int retval = swd_queue_dp_write_inner(dap, DP_SELECT, sel); + if (retval != ERROR_OK) + dap->select = DP_SELECT_INVALID; + + return retval; +} + +static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg, + uint32_t *data) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + assert(swd); + + int retval = swd_queue_dp_bankselect(dap, reg); + if (retval != ERROR_OK) + return retval; + + swd->read_reg(swd_cmd(true, false, reg), data, 0); + + return check_sync(dap); +} + +static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, + uint32_t data) +{ + int retval; + const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + assert(swd); + + swd_finish_read(dap); + + if (reg == DP_SELECT) { + dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK); + + swd->write_reg(swd_cmd(false, false, reg), data, 0); + + retval = check_sync(dap); + if (retval != ERROR_OK) + dap->select = DP_SELECT_INVALID; + + return retval; + } + + retval = swd_queue_dp_bankselect(dap, reg); + if (retval != ERROR_OK) + return retval; + + swd->write_reg(swd_cmd(false, false, reg), data, 0); + + return check_sync(dap); +} + + +static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr, + uint32_t *dlpidr_ptr, bool clear_sticky) +{ + int retval; + uint32_t dpidr, dlpidr; + + assert(dap_is_multidrop(dap)); + + swd_send_sequence(dap, LINE_RESET); + + retval = swd_queue_dp_write_inner(dap, DP_TARGETSEL, dap->multidrop_targetsel); + if (retval != ERROR_OK) + return retval; + + retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr); + if (retval != ERROR_OK) + return retval; + + if (clear_sticky) { + /* Clear all sticky errors (including ORUN) */ + swd_clear_sticky_errors(dap); + } else { + /* Ideally just clear ORUN flag which is set by reset */ + retval = swd_queue_dp_write_inner(dap, DP_ABORT, ORUNERRCLR); + if (retval != ERROR_OK) + return retval; + } + + retval = swd_queue_dp_read_inner(dap, DP_DLPIDR, &dlpidr); + if (retval != ERROR_OK) + return retval; + + retval = swd_run_inner(dap); + if (retval != ERROR_OK) + return retval; + + if ((dpidr & DP_DPIDR_VERSION_MASK) < (2UL << DP_DPIDR_VERSION_SHIFT)) { + LOG_INFO("Read DPIDR 0x%08" PRIx32 + " has version < 2. A non multidrop capable device connected?", + dpidr); + return ERROR_FAIL; + } + + /* TODO: check TARGETID if DLIPDR is same for more than one DP */ + uint32_t expected_dlpidr = DP_DLPIDR_PROTVSN | + (dap->multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK); + if (dlpidr != expected_dlpidr) { + LOG_INFO("Read incorrect DLPIDR 0x%08" PRIx32 + " (possibly CTRL/STAT value)", + dlpidr); + return ERROR_FAIL; + } + + LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel); + swd_multidrop_selected_dap = dap; + + if (dpidr_ptr) + *dpidr_ptr = dpidr; + + if (dlpidr_ptr) + *dlpidr_ptr = dlpidr; + + return retval; +} + +static int swd_multidrop_select(struct adiv5_dap *dap) +{ + if (!dap_is_multidrop(dap)) + return ERROR_OK; + + if (swd_multidrop_selected_dap == dap) + return ERROR_OK; + + int retval = ERROR_OK; + for (unsigned int retry = 0; ; retry++) { + bool clear_sticky = retry > 0; + + retval = swd_multidrop_select_inner(dap, NULL, NULL, clear_sticky); + if (retval == ERROR_OK) + break; + + swd_multidrop_selected_dap = NULL; + if (retry > 3) { + LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap)); + return retval; + } + + LOG_DEBUG("Failed to select multidrop %s, retrying...", + adiv5_dap_name(dap)); + } + + return retval; +} + +static int swd_connect_multidrop(struct adiv5_dap *dap) +{ + int retval; uint32_t dpidr = 0xdeadbeef; + uint32_t dlpidr = 0xdeadbeef; + int64_t timeout = timeval_ms() + 500; + + do { + swd_send_sequence(dap, JTAG_TO_DORMANT); + swd_send_sequence(dap, DORMANT_TO_SWD); + + /* Clear link state, including the SELECT cache. */ + dap->do_reconnect = false; + dap_invalidate_cache(dap); + swd_multidrop_selected_dap = NULL; + + retval = swd_multidrop_select_inner(dap, &dpidr, &dlpidr, true); + if (retval == ERROR_OK) + break; + + alive_sleep(1); + + } while (timeval_ms() < timeout); + + if (retval != ERROR_OK) { + swd_multidrop_selected_dap = NULL; + LOG_ERROR("Failed to connect multidrop %s", adiv5_dap_name(dap)); + return retval; + } + + LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32, + dpidr, dlpidr); + + return retval; +} + +static int swd_connect_single(struct adiv5_dap *dap) +{ + int retval; + uint32_t dpidr = 0xdeadbeef; + int64_t timeout = timeval_ms() + 500; + + do { + swd_send_sequence(dap, JTAG_TO_SWD); + + /* Clear link state, including the SELECT cache. */ + dap->do_reconnect = false; + dap_invalidate_cache(dap); + + retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr); + if (retval == ERROR_OK) { + retval = swd_run_inner(dap); + if (retval == ERROR_OK) + break; + } + + alive_sleep(1); + + } while (timeval_ms() < timeout); + + if (retval != ERROR_OK) { + LOG_ERROR("Error connecting DP: cannot read IDR"); + return retval; + } + + LOG_INFO("SWD DPIDR 0x%08" PRIx32, dpidr); + + do { + dap->do_reconnect = false; + + /* force clear all sticky faults */ + swd_clear_sticky_errors(dap); + + retval = swd_run_inner(dap); + if (retval != ERROR_WAIT) + break; + + alive_sleep(10); + + } while (timeval_ms() < timeout); + + return retval; +} + +static int swd_connect(struct adiv5_dap *dap) +{ int status; /* FIXME validate transport config ... is the * configured DAP present (check IDCODE)? - * Is *only* one DAP configured? - * - * MUST READ DPIDR */ /* Check if we should reset srst already when connecting, but not if reconnecting. */ @@ -118,48 +376,10 @@ static int swd_connect(struct adiv5_dap *dap) } } - - int64_t timeout = timeval_ms() + 500; - - do { - /* Note, debugport_init() does setup too */ - swd->switch_seq(JTAG_TO_SWD); - - /* Clear link state, including the SELECT cache. */ - dap->do_reconnect = false; - dap_invalidate_cache(dap); - - status = swd_queue_dp_read(dap, DP_DPIDR, &dpidr); - if (status == ERROR_OK) { - status = swd_run_inner(dap); - if (status == ERROR_OK) - break; - } - - alive_sleep(1); - - } while (timeval_ms() < timeout); - - if (status != ERROR_OK) { - LOG_ERROR("Error connecting DP: cannot read IDR"); - return status; - } - - LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr); - - do { - dap->do_reconnect = false; - - /* force clear all sticky faults */ - swd_clear_sticky_errors(dap); - - status = swd_run_inner(dap); - if (status != ERROR_WAIT) - break; - - alive_sleep(10); - - } while (timeval_ms() < timeout); + if (dap_is_multidrop(dap)) + status = swd_connect_multidrop(dap); + else + status = swd_connect_single(dap); /* IHI 0031E B4.3.2: * "A WAIT response must not be issued to the ... @@ -174,9 +394,11 @@ static int swd_connect(struct adiv5_dap *dap) dap->do_reconnect = false; - swd->write_reg(swd_cmd(false, false, DP_ABORT), - DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); - status = swd_run_inner(dap); + status = swd_queue_dp_write_inner(dap, DP_ABORT, + DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR); + + if (status == ERROR_OK) + status = swd_run_inner(dap); } if (status == ERROR_OK) @@ -185,19 +407,6 @@ static int swd_connect(struct adiv5_dap *dap) return status; } -static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) -{ - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - assert(swd); - - return swd->switch_seq(seq); -} - -static inline int check_sync(struct adiv5_dap *dap) -{ - return do_sync ? swd_run_inner(dap) : ERROR_OK; -} - static int swd_check_reconnect(struct adiv5_dap *dap) { if (dap->do_reconnect) @@ -211,51 +420,31 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) const struct swd_driver *swd = adiv5_dap_swd_driver(dap); assert(swd); - swd->write_reg(swd_cmd(false, false, DP_ABORT), + /* TODO: Send DAPABORT in swd_multidrop_select_inner() + * in the case the multidrop dap is not selected? + * swd_queue_ap_abort() is not currently used anyway... + */ + int retval = swd_multidrop_select(dap); + if (retval != ERROR_OK) + return retval; + + swd->write_reg(swd_cmd(false, false, DP_ABORT), DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); return check_sync(dap); } -/** Select the DP register bank matching bits 7:4 of reg. */ -static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg) -{ - /* Only register address 4 is banked. */ - if ((reg & 0xf) != 4) - return ERROR_OK; - - uint32_t select_dp_bank = (reg & 0x000000F0) >> 4; - uint32_t sel = select_dp_bank - | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK)); - - if (sel == dap->select) - return ERROR_OK; - - dap->select = sel; - - int retval = swd_queue_dp_write(dap, DP_SELECT, sel); - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; - - return retval; -} - static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - assert(swd); - int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; - retval = swd_queue_dp_bankselect(dap, reg); + retval = swd_multidrop_select(dap); if (retval != ERROR_OK) return retval; - swd->read_reg(swd_cmd(true, false, reg), data, 0); - - return check_sync(dap); + return swd_queue_dp_read_inner(dap, reg, data); } static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, @@ -268,26 +457,11 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, if (retval != ERROR_OK) return retval; - swd_finish_read(dap); - if (reg == DP_SELECT) { - dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK); - - swd->write_reg(swd_cmd(false, false, reg), data, 0); - - retval = check_sync(dap); - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; - - return retval; - } - - retval = swd_queue_dp_bankselect(dap, reg); + retval = swd_multidrop_select(dap); if (retval != ERROR_OK) return retval; - swd->write_reg(swd_cmd(false, false, reg), data, 0); - - return check_sync(dap); + return swd_queue_dp_write_inner(dap, reg, data); } /** Select the AP register bank matching bits 7:4 of reg. */ @@ -303,7 +477,7 @@ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) dap->select = sel; - int retval = swd_queue_dp_write(dap, DP_SELECT, sel); + int retval = swd_queue_dp_write_inner(dap, DP_SELECT, sel); if (retval != ERROR_OK) dap->select = DP_SELECT_INVALID; @@ -321,6 +495,10 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, if (retval != ERROR_OK) return retval; + retval = swd_multidrop_select(dap); + if (retval != ERROR_OK) + return retval; + retval = swd_queue_ap_bankselect(ap, reg); if (retval != ERROR_OK) return retval; @@ -342,7 +520,12 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, if (retval != ERROR_OK) return retval; + retval = swd_multidrop_select(dap); + if (retval != ERROR_OK) + return retval; + swd_finish_read(dap); + retval = swd_queue_ap_bankselect(ap, reg); if (retval != ERROR_OK) return retval; @@ -355,7 +538,12 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, /** Executes all queued DAP operations. */ static int swd_run(struct adiv5_dap *dap) { + int retval = swd_multidrop_select(dap); + if (retval != ERROR_OK) + return retval; + swd_finish_read(dap); + return swd_run_inner(dap); } @@ -363,9 +551,27 @@ static int swd_run(struct adiv5_dap *dap) static void swd_quit(struct adiv5_dap *dap) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + static bool done; - swd->switch_seq(SWD_TO_JTAG); - /* flush the queue before exit */ + /* There is no difference if the sequence is sent at the last + * or the first swd_quit() call, send it just once */ + if (done) + return; + + done = true; + if (dap_is_multidrop(dap)) { + swd->switch_seq(SWD_TO_DORMANT); + /* Revisit! + * Leaving DPs in dormant state was tested and offers some safety + * against DPs mismatch in case of unintentional use of non-multidrop SWD. + * To put SWJ-DPs to power-on state issue + * swd->switch_seq(DORMANT_TO_JTAG); + */ + } else { + swd->switch_seq(SWD_TO_JTAG); + } + + /* flush the queue to shift out the sequence before exit */ swd->run(); } diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 0e1b95f50..758cfa096 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -65,6 +65,10 @@ #define DLCR_TO_TRN(dlcr) ((uint32_t)(1 + ((3 & (dlcr)) >> 8))) /* 1..4 clocks */ +/* Fields of DP_DPIDR register */ +#define DP_DPIDR_VERSION_SHIFT 12 +#define DP_DPIDR_VERSION_MASK (0xFUL << DP_DPIDR_VERSION_SHIFT) + /* Fields of the DP's AP ABORT register */ #define DAPABORT (1UL << 0) #define STKCMPCLR (1UL << 1) /* SWD-only */ @@ -89,6 +93,8 @@ #define CSYSPWRUPREQ (1UL << 30) #define CSYSPWRUPACK (1UL << 31) +#define DP_DLPIDR_PROTVSN 1u + #define DP_SELECT_APSEL 0xFF000000 #define DP_SELECT_APBANK 0x000000F0 #define DP_SELECT_DPBANK 0x0000000F @@ -97,6 +103,11 @@ #define DP_APSEL_MAX (255) #define DP_APSEL_INVALID (-1) +#define DP_TARGETSEL_INVALID 0xFFFFFFFFU +#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU +#define DP_TARGETSEL_INSTANCEID_MASK 0xF0000000U +#define DP_TARGETSEL_INSTANCEID_SHIFT 28 + /* MEM-AP register addresses */ #define MEM_AP_REG_CSW 0x00 @@ -191,6 +202,7 @@ enum swd_special_seq { SWD_TO_JTAG, SWD_TO_DORMANT, DORMANT_TO_SWD, + DORMANT_TO_JTAG, }; /** @@ -323,6 +335,13 @@ struct adiv5_dap { /** Flag saying whether to ignore the syspwrupack flag in DAP. Some devices * do not set this bit until later in the bringup sequence */ bool ignore_syspwrupack; + + /** Value to select DP in SWD multidrop mode or DP_TARGETSEL_INVALID */ + uint32_t multidrop_targetsel; + /** TPARTNO and TDESIGNER fields of multidrop_targetsel have been configured */ + bool multidrop_dp_id_valid; + /** TINSTANCE field of multidrop_targetsel has been configured */ + bool multidrop_instance_id_valid; }; /** @@ -609,6 +628,12 @@ static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num) return &dap->ap[ap_num]; } +/** Check if SWD multidrop configuration is valid */ +static inline bool dap_is_multidrop(struct adiv5_dap *dap) +{ + return dap->multidrop_dp_id_valid && dap->multidrop_instance_id_valid; +} + /* Lookup CoreSight component */ int dap_lookup_cs_component(struct adiv5_ap *ap, target_addr_t dbgbase, uint8_t type, target_addr_t *addr, int32_t *idx); diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 94edfc09d..2dba45d0b 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -155,21 +155,24 @@ int dap_cleanup_all(void) enum dap_cfg_param { CFG_CHAIN_POSITION, CFG_IGNORE_SYSPWRUPACK, + CFG_DP_ID, + CFG_INSTANCE_ID, }; static const struct jim_nvp nvp_config_opts[] = { - { .name = "-chain-position", .value = CFG_CHAIN_POSITION }, + { .name = "-chain-position", .value = CFG_CHAIN_POSITION }, { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK }, + { .name = "-dp-id", .value = CFG_DP_ID }, + { .name = "-instance-id", .value = CFG_INSTANCE_ID }, { .name = NULL, .value = -1 } }; static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap) { - struct jtag_tap *tap = NULL; struct jim_nvp *n; int e; - /* parse config or cget options ... */ + /* parse config ... */ while (goi->argc > 0) { Jim_SetEmptyResult(goi->interp); @@ -184,31 +187,114 @@ static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap e = jim_getopt_obj(goi, &o_t); if (e != JIM_OK) return e; + + struct jtag_tap *tap; tap = jtag_tap_by_jim_obj(goi->interp, o_t); if (!tap) { Jim_SetResultString(goi->interp, "-chain-position is invalid", -1); return JIM_ERR; } + dap->dap.tap = tap; /* loop for more */ break; } case CFG_IGNORE_SYSPWRUPACK: dap->dap.ignore_syspwrupack = true; break; + case CFG_DP_ID: { + jim_wide w; + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) { + Jim_SetResultFormatted(goi->interp, + "create %s: bad parameter %s", + dap->name, n->name); + return JIM_ERR; + } + if (w < 0 || w > DP_TARGETSEL_DPID_MASK) { + Jim_SetResultFormatted(goi->interp, + "create %s: %s out of range", + dap->name, n->name); + return JIM_ERR; + } + dap->dap.multidrop_targetsel = + (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK) + | (w & DP_TARGETSEL_DPID_MASK); + dap->dap.multidrop_dp_id_valid = true; + break; + } + case CFG_INSTANCE_ID: { + jim_wide w; + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) { + Jim_SetResultFormatted(goi->interp, + "create %s: bad parameter %s", + dap->name, n->name); + return JIM_ERR; + } + if (w < 0 || w > 15) { + Jim_SetResultFormatted(goi->interp, + "create %s: %s out of range", + dap->name, n->name); + return JIM_ERR; + } + dap->dap.multidrop_targetsel = + (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK) + | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK); + dap->dap.multidrop_instance_id_valid = true; + break; + } default: break; } } - if (!tap) { - Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1); - return JIM_ERR; + return JIM_OK; +} + +static int dap_check_config(struct adiv5_dap *dap) +{ + if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla()) + return ERROR_OK; + + struct arm_dap_object *obj; + bool new_multidrop = dap_is_multidrop(dap); + bool had_multidrop = new_multidrop; + uint32_t targetsel = dap->multidrop_targetsel; + unsigned int non_multidrop_count = had_multidrop ? 0 : 1; + + list_for_each_entry(obj, &all_dap, lh) { + struct adiv5_dap *dap_it = &obj->dap; + + if (transport_is_swd()) { + if (dap_is_multidrop(dap_it)) { + had_multidrop = true; + if (new_multidrop && dap_it->multidrop_targetsel == targetsel) { + uint32_t dp_id = targetsel & DP_TARGETSEL_DPID_MASK; + uint32_t instance_id = targetsel >> DP_TARGETSEL_INSTANCEID_SHIFT; + LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08" + PRIx32 " and -instance-id 0x%" PRIx32, + obj->name, adiv5_dap_name(dap), + dp_id, instance_id); + return ERROR_FAIL; + } + } else { + non_multidrop_count++; + } + } else if (transport_is_dapdirect_swd()) { + non_multidrop_count++; + } } - dap_instance_init(&dap->dap); - dap->dap.tap = tap; + if (non_multidrop_count > 1) { + LOG_ERROR("Two or more SWD non multidrop DAPs are not supported"); + return ERROR_FAIL; + } + if (had_multidrop && non_multidrop_count) { + LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported"); + return ERROR_FAIL; + } - return JIM_OK; + return ERROR_OK; } static int dap_create(struct jim_getopt_info *goi) @@ -242,16 +328,28 @@ static int dap_create(struct jim_getopt_info *goi) if (!dap) return JIM_ERR; - e = dap_configure(goi, dap); - if (e != JIM_OK) { - free(dap); - return e; - } + dap_instance_init(&dap->dap); cp = Jim_GetString(new_cmd, NULL); dap->name = strdup(cp); - struct command_registration dap_commands[] = { + e = dap_configure(goi, dap); + if (e != JIM_OK) + goto err; + + if (!dap->dap.tap) { + Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1); + e = JIM_ERR; + goto err; + } + + e = dap_check_config(&dap->dap); + if (e != ERROR_OK) { + e = JIM_ERR; + goto err; + } + + struct command_registration dap_create_commands[] = { { .name = cp, .mode = COMMAND_ANY, @@ -264,15 +362,22 @@ static int dap_create(struct jim_getopt_info *goi) /* don't expose the instance commands when using hla */ if (transport_is_hla()) - dap_commands[0].chain = NULL; + dap_create_commands[0].chain = NULL; - e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap); - if (e != ERROR_OK) - return JIM_ERR; + e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap); + if (e != ERROR_OK) { + e = JIM_ERR; + goto err; + } list_add_tail(&dap->lh, &all_dap); return JIM_OK; + +err: + free(dap->name); + free(dap); + return e; } static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index ffc8ca875..0a51ad4d6 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -251,7 +251,7 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } -static uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) +uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) { switch (arm_reg_id) { case ARMV7M_R0 ... ARMV7M_R14: @@ -289,7 +289,7 @@ static uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) } } -static bool armv7m_map_reg_packing(unsigned int arm_reg_id, +bool armv7m_map_reg_packing(unsigned int arm_reg_id, unsigned int *reg32_id, uint32_t *offset) { diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 2816a9145..d33e57492 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -309,6 +309,11 @@ int armv7m_invalidate_core_regs(struct target *target); int armv7m_restore_context(struct target *target); +uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id); + +bool armv7m_map_reg_packing(unsigned int arm_reg_id, + unsigned int *reg32_id, uint32_t *offset); + int armv7m_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum); int armv7m_blank_check_memory(struct target *target, diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 3412c5677..649ee32f2 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -53,6 +53,9 @@ * any longer. */ +/* Timeout for register r/w */ +#define DHCSR_S_REGRDY_TIMEOUT (500) + /* Supported Cortex-M Cores */ static const struct cortex_m_part_info cortex_m_parts[] = { { @@ -118,12 +121,41 @@ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); static void cortex_m_dwt_free(struct target *target); +/** DCB DHCSR register contains S_RETIRE_ST and S_RESET_ST bits cleared + * on a read. Call this helper function each time DHCSR is read + * to preserve S_RESET_ST state in case of a reset event was detected. + */ +static inline void cortex_m_cumulate_dhcsr_sticky(struct cortex_m_common *cortex_m, + uint32_t dhcsr) +{ + cortex_m->dcb_dhcsr_cumulated_sticky |= dhcsr; +} + +/** Read DCB DHCSR register to cortex_m->dcb_dhcsr and cumulate + * sticky bits in cortex_m->dcb_dhcsr_cumulated_sticky + */ +static int cortex_m_read_dhcsr_atomic_sticky(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + + int retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, + &cortex_m->dcb_dhcsr); + if (retval != ERROR_OK) + return retval; + + cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr); + return ERROR_OK; +} + static int cortex_m_load_core_reg_u32(struct target *target, uint32_t regsel, uint32_t *value) { + struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = target_to_armv7m(target); int retval; - uint32_t dcrdr; + uint32_t dcrdr, tmp_value; + int64_t then; /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ @@ -137,9 +169,29 @@ static int cortex_m_load_core_reg_u32(struct target *target, if (retval != ERROR_OK) return retval; - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DCRDR, value); - if (retval != ERROR_OK) - return retval; + /* check if value from register is ready and pre-read it */ + then = timeval_ms(); + while (1) { + retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DHCSR, + &cortex_m->dcb_dhcsr); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DCRDR, + &tmp_value); + if (retval != ERROR_OK) + return retval; + cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr); + if (cortex_m->dcb_dhcsr & S_REGRDY) + break; + cortex_m->slow_register_read = true; /* Polling (still) needed. */ + if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { + LOG_ERROR("Timeout waiting for DCRDR transfer ready"); + return ERROR_TIMEOUT_REACHED; + } + keep_alive(); + } + + *value = tmp_value; if (target->dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a separate @@ -151,11 +203,53 @@ static int cortex_m_load_core_reg_u32(struct target *target, return retval; } -static int cortex_m_store_core_reg_u32(struct target *target, - uint32_t regsel, uint32_t value) +static int cortex_m_slow_read_all_regs(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + const unsigned int num_regs = armv7m->arm.core_cache->num_regs; + + /* Opportunistically restore fast read, it'll revert to slow + * if any register needed polling in cortex_m_load_core_reg_u32(). */ + cortex_m->slow_register_read = false; + + for (unsigned int reg_id = 0; reg_id < num_regs; reg_id++) { + struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id]; + if (r->exist) { + int retval = armv7m->arm.read_core_reg(target, r, reg_id, ARM_MODE_ANY); + if (retval != ERROR_OK) + return retval; + } + } + + if (!cortex_m->slow_register_read) + LOG_DEBUG("Switching back to fast register reads"); + + return ERROR_OK; +} + +static int cortex_m_queue_reg_read(struct target *target, uint32_t regsel, + uint32_t *reg_value, uint32_t *dhcsr) { struct armv7m_common *armv7m = target_to_armv7m(target); int retval; + + retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DHCSR, dhcsr); + if (retval != ERROR_OK) + return retval; + + return mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, reg_value); +} + +static int cortex_m_fast_read_all_regs(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + int retval; uint32_t dcrdr; /* because the DCB_DCRDR is used for the emulated dcc channel @@ -166,14 +260,157 @@ static int cortex_m_store_core_reg_u32(struct target *target, return retval; } + const unsigned int num_regs = armv7m->arm.core_cache->num_regs; + const unsigned int n_r32 = ARMV7M_LAST_REG - ARMV7M_CORE_FIRST_REG + 1 + + ARMV7M_FPU_LAST_REG - ARMV7M_FPU_FIRST_REG + 1; + /* we need one 32-bit word for each register except FP D0..D15, which + * need two words */ + uint32_t r_vals[n_r32]; + uint32_t dhcsr[n_r32]; + + unsigned int wi = 0; /* write index to r_vals and dhcsr arrays */ + unsigned int reg_id; /* register index in the reg_list, ARMV7M_R0... */ + for (reg_id = 0; reg_id < num_regs; reg_id++) { + struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id]; + if (!r->exist) + continue; /* skip non existent registers */ + + if (r->size <= 8) { + /* Any 8-bit or shorter register is unpacked from a 32-bit + * container register. Skip it now. */ + continue; + } + + uint32_t regsel = armv7m_map_id_to_regsel(reg_id); + retval = cortex_m_queue_reg_read(target, regsel, &r_vals[wi], + &dhcsr[wi]); + if (retval != ERROR_OK) + return retval; + wi++; + + assert(r->size == 32 || r->size == 64); + if (r->size == 32) + continue; /* done with 32-bit register */ + + assert(reg_id >= ARMV7M_FPU_FIRST_REG && reg_id <= ARMV7M_FPU_LAST_REG); + /* the odd part of FP register (S1, S3...) */ + retval = cortex_m_queue_reg_read(target, regsel + 1, &r_vals[wi], + &dhcsr[wi]); + if (retval != ERROR_OK) + return retval; + wi++; + } + + assert(wi <= n_r32); + + retval = dap_run(armv7m->debug_ap->dap); + if (retval != ERROR_OK) + return retval; + + if (target->dbg_msg_enabled) { + /* restore DCB_DCRDR - this needs to be in a separate + * transaction otherwise the emulated DCC channel breaks */ + retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr); + if (retval != ERROR_OK) + return retval; + } + + bool not_ready = false; + for (unsigned int i = 0; i < wi; i++) { + if ((dhcsr[i] & S_REGRDY) == 0) { + not_ready = true; + LOG_DEBUG("Register %u was not ready during fast read", i); + } + cortex_m_cumulate_dhcsr_sticky(cortex_m, dhcsr[i]); + } + + if (not_ready) { + /* Any register was not ready, + * fall back to slow read with S_REGRDY polling */ + return ERROR_TIMEOUT_REACHED; + } + + LOG_DEBUG("read %u 32-bit registers", wi); + + unsigned int ri = 0; /* read index from r_vals array */ + for (reg_id = 0; reg_id < num_regs; reg_id++) { + struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id]; + if (!r->exist) + continue; /* skip non existent registers */ + + r->dirty = false; + + unsigned int reg32_id; + uint32_t offset; + if (armv7m_map_reg_packing(reg_id, ®32_id, &offset)) { + /* Unpack a partial register from 32-bit container register */ + struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id]; + + /* The container register ought to precede all regs unpacked + * from it in the reg_list. So the value should be ready + * to unpack */ + assert(r32->valid); + buf_cpy(r32->value + offset, r->value, r->size); + + } else { + assert(r->size == 32 || r->size == 64); + buf_set_u32(r->value, 0, 32, r_vals[ri++]); + + if (r->size == 64) { + assert(reg_id >= ARMV7M_FPU_FIRST_REG && reg_id <= ARMV7M_FPU_LAST_REG); + /* the odd part of FP register (S1, S3...) */ + buf_set_u32(r->value + 4, 0, 32, r_vals[ri++]); + } + } + r->valid = true; + } + assert(ri == wi); + + return retval; +} + +static int cortex_m_store_core_reg_u32(struct target *target, + uint32_t regsel, uint32_t value) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + int retval; + uint32_t dcrdr; + int64_t then; + + /* because the DCB_DCRDR is used for the emulated dcc channel + * we have to save/restore the DCB_DCRDR when used */ + if (target->dbg_msg_enabled) { + retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr); + if (retval != ERROR_OK) + return retval; + } + retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR); + retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR); if (retval != ERROR_OK) return retval; + /* check if value is written into register */ + then = timeval_ms(); + while (1) { + retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, + &cortex_m->dcb_dhcsr); + if (retval != ERROR_OK) + return retval; + cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr); + if (cortex_m->dcb_dhcsr & S_REGRDY) + break; + if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { + LOG_ERROR("Timeout waiting for DCRDR transfer ready"); + return ERROR_TIMEOUT_REACHED; + } + keep_alive(); + } + if (target->dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a separate * transaction otherwise the emulated DCC channel breaks */ @@ -301,7 +538,6 @@ static int cortex_m_clear_halt(struct target *target) static int cortex_m_single_step_core(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); - struct armv7m_common *armv7m = &cortex_m->armv7m; int retval; /* Mask interrupts before clearing halt, if not done already. This avoids @@ -309,13 +545,11 @@ static int cortex_m_single_step_core(struct target *target) * HALT can put the core into an unknown state. */ if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) { - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, - DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN); + retval = cortex_m_write_debug_halt_mask(target, C_MASKINTS, 0); if (retval != ERROR_OK) return retval; } - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, - DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN); + retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); if (retval != ERROR_OK) return retval; LOG_DEBUG(" "); @@ -365,11 +599,12 @@ static int cortex_m_endreset_event(struct target *target) if (retval != ERROR_OK) return retval; - /* Enable debug requests */ - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) return retval; + if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { + /* Enable debug requests */ retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS); if (retval != ERROR_OK) return retval; @@ -431,7 +666,9 @@ static int cortex_m_endreset_event(struct target *target) register_cache_invalidate(armv7m->arm.core_cache); /* make sure we have latest dhcsr flags */ - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); + if (retval != ERROR_OK) + return retval; return retval; } @@ -540,7 +777,6 @@ static int cortex_m_examine_exception_reason(struct target *target) static int cortex_m_debug_entry(struct target *target) { - int i; uint32_t xPSR; int retval; struct cortex_m_common *cortex_m = target_to_cm(target); @@ -555,7 +791,8 @@ static int cortex_m_debug_entry(struct target *target) cortex_m_set_maskints_for_halt(target); cortex_m_clear_halt(target); - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) return retval; @@ -575,16 +812,21 @@ static int cortex_m_debug_entry(struct target *target) secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS; } - /* Examine target state and mode - * First load register accessible through core debug port */ - int num_regs = arm->core_cache->num_regs; - - for (i = 0; i < num_regs; i++) { - r = &armv7m->arm.core_cache->reg_list[i]; - if (r->exist && !r->valid) - arm->read_core_reg(target, r, i, ARM_MODE_ANY); + /* Load all registers to arm.core_cache */ + if (!cortex_m->slow_register_read) { + retval = cortex_m_fast_read_all_regs(target); + if (retval == ERROR_TIMEOUT_REACHED) { + cortex_m->slow_register_read = true; + LOG_DEBUG("Switched to slow register read"); + } } + if (cortex_m->slow_register_read) + retval = cortex_m_slow_read_all_regs(target); + + if (retval != ERROR_OK) + return retval; + r = arm->cpsr; xPSR = buf_get_u32(r->value, 0, 32); @@ -639,7 +881,7 @@ static int cortex_m_poll(struct target *target) struct armv7m_common *armv7m = &cortex_m->armv7m; /* Read from Debug Halting Control and Status Register */ - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; return retval; @@ -660,12 +902,13 @@ static int cortex_m_poll(struct target *target) detected_failure = ERROR_FAIL; /* refresh status bits */ - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) return retval; } - if (cortex_m->dcb_dhcsr & S_RESET_ST) { + if (cortex_m->dcb_dhcsr_cumulated_sticky & S_RESET_ST) { + cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST; if (target->state != TARGET_RESET) { target->state = TARGET_RESET; LOG_INFO("%s: external reset detected", target_name(target)); @@ -712,7 +955,12 @@ static int cortex_m_poll(struct target *target) } if (target->state == TARGET_UNKNOWN) { - /* check if processor is retiring instructions or sleeping */ + /* Check if processor is retiring instructions or sleeping. + * Unlike S_RESET_ST here we test if the target *is* running now, + * not if it has been running (possibly in the past). Instructions are + * typically processed much faster than OpenOCD polls DHCSR so S_RETIRE_ST + * is read always 1. That's the reason not to use dcb_dhcsr_cumulated_sticky. + */ if (cortex_m->dcb_dhcsr & S_RETIRE_ST || cortex_m->dcb_dhcsr & S_SLEEP) { target->state = TARGET_RUNNING; retval = ERROR_OK; @@ -779,7 +1027,6 @@ static int cortex_m_soft_reset_halt(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; - uint32_t dcb_dhcsr = 0; int retval, timeout = 0; /* on single cortex_m MCU soft_reset_halt should be avoided as same functionality @@ -815,25 +1062,23 @@ static int cortex_m_soft_reset_halt(struct target *target) register_cache_invalidate(cortex_m->armv7m.arm.core_cache); while (timeout < 100) { - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval == ERROR_OK) { retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_DFSR, &cortex_m->nvic_dfsr); if (retval != ERROR_OK) return retval; - if ((dcb_dhcsr & S_HALT) + if ((cortex_m->dcb_dhcsr & S_HALT) && (cortex_m->nvic_dfsr & DFSR_VCATCH)) { - LOG_DEBUG("system reset-halted, DHCSR 0x%08x, " - "DFSR 0x%08x", - (unsigned) dcb_dhcsr, - (unsigned) cortex_m->nvic_dfsr); + LOG_DEBUG("system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32, + cortex_m->dcb_dhcsr, cortex_m->nvic_dfsr); cortex_m_poll(target); /* FIXME restore user's vector catch config */ return ERROR_OK; } else LOG_DEBUG("waiting for system reset-halt, " - "DHCSR 0x%08x, %d ms", - (unsigned) dcb_dhcsr, timeout); + "DHCSR 0x%08" PRIx32 ", %d ms", + cortex_m->dcb_dhcsr, timeout); } timeout++; alive_sleep(1); @@ -1082,9 +1327,7 @@ static int cortex_m_step(struct target *target, int current, /* Wait for pending handlers to complete or timeout */ do { - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, - DCB_DHCSR, - &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; return retval; @@ -1119,7 +1362,7 @@ static int cortex_m_step(struct target *target, int current, } } - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) return retval; @@ -1197,8 +1440,8 @@ static int cortex_m_assert_reset(struct target *target) } /* Enable debug requests */ - int retval; - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); + int retval = cortex_m_read_dhcsr_atomic_sticky(target); + /* Store important errors instead of failing and proceed to reset assert */ if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN)) @@ -2142,11 +2385,13 @@ int cortex_m_examine(struct target *target) armv7m->debug_ap->tar_autoincr_block = (1 << 12); } - /* Enable debug requests */ retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; + cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr); + if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { + /* Enable debug requests */ uint32_t dhcsr = (cortex_m->dcb_dhcsr | C_DEBUGEN) & ~(C_HALT | C_STEP | C_MASKINTS); retval = target_write_u32(target, DCB_DHCSR, DBGKEY | (dhcsr & 0x0000FFFFUL)); @@ -2344,7 +2589,7 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp) static int cortex_m_verify_pointer(struct command_invocation *cmd, struct cortex_m_common *cm) { - if (cm->common_magic != CORTEX_M_COMMON_MAGIC) { + if (!is_cortex_m_with_dap_access(cm)) { command_print(cmd, "target is not a Cortex-M"); return ERROR_TARGET_INVALID; } diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 16fc8ab70..c2f836a35 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -213,6 +213,7 @@ struct cortex_m_common { /* Context information */ uint32_t dcb_dhcsr; + uint32_t dcb_dhcsr_cumulated_sticky; uint32_t nvic_dfsr; /* Debug Fault Status Register - shows reason for debug halt */ uint32_t nvic_icsr; /* Interrupt Control State Register - shows active and pending IRQ */ @@ -237,6 +238,8 @@ struct cortex_m_common { const struct cortex_m_part_info *core_info; struct armv7m_common armv7m; + bool slow_register_read; /* A register has not been ready, poll S_REGRDY */ + int apsel; /* Whether this target has the erratum that makes C_MASKINTS not apply to @@ -251,6 +254,19 @@ target_to_cm(struct target *target) struct cortex_m_common, armv7m); } +static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m) +{ + return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC; +} + +static inline bool is_cortex_m_with_dap_access(const struct cortex_m_common *cortex_m) +{ + if (!is_cortex_m_or_hla(cortex_m)) + return false; + + return !cortex_m->armv7m.is_hla_target; +} + int cortex_m_examine(struct target *target); int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint); int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); diff --git a/src/target/etm.c b/src/target/etm.c index e8bd20fef..119c0df5d 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -1416,8 +1416,7 @@ COMMAND_HANDLER(handle_etm_config_command) for (i = 0; etm_capture_drivers[i]; i++) { if (strcmp(CMD_ARGV[4], etm_capture_drivers[i]->name) == 0) { - int retval = register_commands(CMD_CTX, NULL, - etm_capture_drivers[i]->commands); + int retval = register_commands(CMD_CTX, NULL, etm_capture_drivers[i]->commands); if (retval != ERROR_OK) { free(etm_ctx); return retval; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index c67c9cc89..3e359b950 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -214,6 +214,8 @@ static int adapter_target_create(struct target *target, return ERROR_FAIL; } + cortex_m->common_magic = CORTEX_M_COMMON_MAGIC; + adapter_init_arch_info(target, cortex_m, target->tap); return ERROR_OK; @@ -621,7 +623,7 @@ static int adapter_write_memory(struct target *target, target_addr_t address, return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer); } -static const struct command_registration adapter_command_handlers[] = { +static const struct command_registration hla_command_handlers[] = { { .chain = arm_command_handlers, }, @@ -647,7 +649,7 @@ struct target_type hla_target = { .target_create = adapter_target_create, .target_jim_configure = adiv5_jim_configure, .examine = cortex_m_examine, - .commands = adapter_command_handlers, + .commands = hla_command_handlers, .poll = adapter_poll, .arch_state = armv7m_arch_state, diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 923cdf877..9f8762e34 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -70,6 +70,7 @@ #include #include +#include #include "mips32.h" #include "mips32_pracc.h" @@ -380,7 +381,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in } unsigned num_clocks = - ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; + ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); @@ -1010,7 +1011,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are unsigned num_clocks = 0; /* like in legacy code */ if (ejtag_info->mode != 0) - num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; + num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; for (int i = 0; i < count; i++) { jtag_add_clocks(num_clocks); diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index bb2af228d..81a4cfbfa 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -21,6 +21,7 @@ #include "mips64_pracc.h" #include +#include #define STACK_DEPTH 32 @@ -1386,7 +1387,7 @@ int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, /* like in legacy code */ unsigned num_clocks = 0; if (ejtag_info->mode != 0) - num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; + num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; LOG_DEBUG("num_clocks=%d", num_clocks); for (i = 0; i < count; i++) { jtag_add_clocks(num_clocks); diff --git a/src/target/target.c b/src/target/target.c index bc4fbf8df..fb2a79534 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -881,7 +881,7 @@ done: int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info) { int retval = ERROR_FAIL; @@ -925,7 +925,7 @@ done: int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_FAIL; diff --git a/src/target/target.h b/src/target/target.h index 779d139ae..6c383bedb 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -558,7 +558,7 @@ int target_run_algorithm(struct target *target, int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info); /** @@ -569,7 +569,7 @@ int target_start_algorithm(struct target *target, int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info); /** diff --git a/tcl/interface/cmsis-dap.cfg b/tcl/interface/cmsis-dap.cfg index 887d2d713..1bc91a527 100644 --- a/tcl/interface/cmsis-dap.cfg +++ b/tcl/interface/cmsis-dap.cfg @@ -7,4 +7,4 @@ adapter driver cmsis-dap # Optionally specify the serial number of CMSIS-DAP usb device. -#cmsis_dap_serial 02200201E6661E601B98E3B9 +# adapter serial 02200201E6661E601B98E3B9 diff --git a/tcl/interface/ftdi/flossjtag.cfg b/tcl/interface/ftdi/flossjtag.cfg index 2e3cfca48..c1506a2e9 100644 --- a/tcl/interface/ftdi/flossjtag.cfg +++ b/tcl/interface/ftdi/flossjtag.cfg @@ -20,7 +20,7 @@ echo "so it could be marked as working or fixed." adapter driver ftdi ftdi vid_pid 0x0403 0x6010 ftdi device_desc "FLOSS-JTAG" -#ftdi serial "FJ000001" +# adapter serial "FJ000001" ftdi layout_init 0x0008 0x180b ftdi layout_signal nTRST -data 0x0010 -oe 0x0010 diff --git a/tcl/interface/jlink.cfg b/tcl/interface/jlink.cfg index 51f420b7f..f9a18b05f 100644 --- a/tcl/interface/jlink.cfg +++ b/tcl/interface/jlink.cfg @@ -11,4 +11,4 @@ adapter driver jlink # # Example: Select J-Link with serial number 123456789 # -# jlink serial 123456789 +# adapter serial 123456789 diff --git a/tcl/interface/kitprog.cfg b/tcl/interface/kitprog.cfg index 29fce489b..933a05408 100644 --- a/tcl/interface/kitprog.cfg +++ b/tcl/interface/kitprog.cfg @@ -9,4 +9,4 @@ adapter driver kitprog # Optionally specify the serial number of the KitProg you want to use. -#kitprog_serial 1926402735485200 +# adapter serial 1926402735485200 diff --git a/tcl/interface/nds32-aice.cfg b/tcl/interface/nds32-aice.cfg index 3b21025b5..fcc33ec28 100644 --- a/tcl/interface/nds32-aice.cfg +++ b/tcl/interface/nds32-aice.cfg @@ -6,7 +6,7 @@ adapter driver aice aice desc "Andes AICE adapter" -aice serial "C001-42163" +# adapter serial "C001-42163" aice vid_pid 0x1CFC 0x0000 aice port aice_usb reset_config trst_and_srst diff --git a/tcl/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg index d912a5560..5a7d2e9ae 100644 --- a/tcl/interface/stlink-dap.cfg +++ b/tcl/interface/stlink-dap.cfg @@ -17,4 +17,4 @@ st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0 # Optionally specify the serial number of usb device # e.g. -# st-link serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" +# adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index cb8e00494..8ac9b579f 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -13,4 +13,4 @@ hla_vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374 # firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial # number reset issues. # eg. -#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" +# adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" diff --git a/tcl/interface/ti-icdi.cfg b/tcl/interface/ti-icdi.cfg index 8561a3182..5cf6e37be 100644 --- a/tcl/interface/ti-icdi.cfg +++ b/tcl/interface/ti-icdi.cfg @@ -14,4 +14,4 @@ hla_vid_pid 0x1cbe 0x00fd # Optionally specify the serial number of TI-ICDI devices, for when using # multiple devices. Serial numbers can be obtained using lsusb -v # Ex. -#hla_serial "0F003065" +# adapter serial "0F003065" diff --git a/tcl/interface/xds110.cfg b/tcl/interface/xds110.cfg index 51f4e28d3..74122c3e6 100644 --- a/tcl/interface/xds110.cfg +++ b/tcl/interface/xds110.cfg @@ -9,4 +9,4 @@ adapter driver xds110 # Use serial number option to use a specific XDS110 # when more than one are connected to the host. -#xds110 serial 00000000 +# adapter serial 00000000 diff --git a/tcl/target/gd32e23x.cfg b/tcl/target/gd32e23x.cfg new file mode 100644 index 000000000..250427413 --- /dev/null +++ b/tcl/target/gd32e23x.cfg @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for GigaDevice gd32e23x Cortex-M23 Series + +# https://www.gigadevice.com/microcontroller/gd32e230c8t6/ + +# +# gd32e23x devices support SWD transports only. +# +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME gd32e23x +} + +# Work-area is a space in RAM used for flash programming +# By default use 4kB (as found on some GD32E230s) +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +# Allow overriding the Flash bank size +if { [info exists FLASH_SIZE] } { + set _FLASH_SIZE $FLASH_SIZE +} else { + # autodetect size + set _FLASH_SIZE 0 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + # this is the SW-DP tap id not the jtag tap id + set _CPUTAPID 0x0bf11477 +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -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 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# flash size will be probed +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME + +# SWD speed (may be updated to higher value in board config file) +adapter speed 1000 + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +$_TARGETNAME configure -event examine-end { + # Debug clock enable + # RCU_APB2EN |= DBGMCUEN + mmw 0x40021018 0x00400000 0 + + # Stop watchdog counters during halt + # DBG_CTL0 |= WWDGT_HOLD | FWDGT_HOLD | STB_HOLD | DSLP_HOLD | SLP_HOLD + mmw 0x40015804 0x00000307 0 +} diff --git a/testing/build.test1/Makefile b/testing/build.test1/Makefile deleted file mode 100644 index 02b752307..000000000 --- a/testing/build.test1/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -# -*- mode: makefile -*- -# -default: _complain_ -include ./local.uses - -%: _complain_ - - -_complain_: - @echo "" - @echo " Try the target: cygwin.buildtest or linux.buildtest " - @echo "" - -remove.install: - rm -rf ${INSTALL_DIR} - -.PHONY: remove.install - -cygwin.buildtest: - ${MAKE} -f Makefile.ftd2xx clean all - ${MAKE} -f Makefile.openocd cygwin.easy.permutations - ${MAKE} -f Makefile.openocd mingw32.easy.permutations - ${MAKE} -f Makefile.libftdi all - ${MAKE} -f Makefile.openocd cygwin.libftdi - -linux.buildtest: - ${MAKE} linux.easy.buildtest - ${MAKE} linux.ftd2xx_installed - ${MAKE} linux.ft2232_libftdi - @echo "" - @echo "" - @echo "========================================" - @echo " Linux Build Tests Complete " - @echo "========================================" - @echo "" - @echo "" - - -linux.easy.buildtest: - @test -d openocd || (echo "Where the source to openocd?" && exit 1) - ${MAKE} -f Makefile.openocd bootstrap - ${MAKE} -f Makefile.ftd2xx all - ${MAKE} -f Makefile.openocd linux.easy.permutations - -linux.ftd2xx_installed: - ${MAKE} remove.install - ${MAKE} linux.ftd2xx_installed.setup - ${MAKE} -f Makefile.openocd $@ - - linux.ft2232_libftdi: - ${MAKE} remove.install - ${MAKE} -f Makefile.libusb all - ${MAKE} -f Makefile.confuse all - ${MAKE} -f Makefile.libftdi all - ${MAKE} -f Makefile.openocd $@ - -# This target is used to "install" files from -# the FTDICHIP.COM tar.gz unpack directory -# into "a proper place" - where they should be found. -linux.ftd2xx_installed.setup: - mkdir -p ${INSTALL_DIR}/include - mkdir -p ${EXEC_PREFIX}/lib - @# - @# Sanity check - make sure the .H file is findable - @# - @f=$(FTD2XX_LINUX_DIR)/ftd2xx.h && \ - test -f $$f || (echo "Error: $$f not found" ; exit 1) - @# - @# Header files are simple... just copy them. - @# - cp $(FTD2XX_LINUX_DIR)/ftd2xx.h $(PREFIX)/include/. - cp $(FTD2XX_LINUX_DIR)/WinTypes.h $(PREFIX)/include/. - @# - @# .SO files are harder. - @# (1) copy them, (2) make links - @# - cp $(FTD2XX_LINUX_DIR)/libftd2xx.so.$(FTD2XX_LINUX_VERSION) $(EXEC_PREFIX)/lib/. - cd $(EXEC_PREFIX)/lib && rm -f libftd2xx.so.0 - cd $(EXEC_PREFIX)/lib && ln -s libftd2xx.so.$(FTD2XX_LINUX_VERSION) libftd2xx.so.0 - cd $(EXEC_PREFIX)/lib && rm -f libftd2xx.so - cd $(EXEC_PREFIX)/lib && ln -s libftd2xx.so.$(FTD2XX_LINUX_VERSION) libftd2xx.so - - -all.download: - mkdir -p ${VIRGINS} - ${MAKE} -f Makefile.confuse download - ${MAKE} -f Makefile.libftdi download - ${MAKE} -f Makefile.ftd2xx download - ${MAKE} -f Makefile.libusb download - -.PHONY: linux.buildtest \ - linux.easy.buildtest \ - linux.ftd2xx_installed \ - linux.ft22232_libftdi \ - linux.ftd2xx_installed.setup diff --git a/testing/build.test1/Makefile.confuse b/testing/build.test1/Makefile.confuse deleted file mode 100644 index 9d5a0673f..000000000 --- a/testing/build.test1/Makefile.confuse +++ /dev/null @@ -1,46 +0,0 @@ -# -*- mode: makefile -*- -default: _complain_ -include ./local.uses - -TARFILE_LOCAL=${VIRGINS}/confuse-${LIBCONFUSE_VERSION}.tar.gz -TARFILE_URL =http://www.intra2net.com/de/produkte/opensource/ftdi/TGZ/confuse-${LIBCONFUSE_VERSION}.tar.gz - -CONFUSE_SRC_DIR =${HERE}/confuse-${LIBCONFUSE_VERSION} -CONFUSE_BUILD_DIR =${HERE}/confuse-build - -download: - wget -O ${TARFILE_LOCAL} ${TARFILE_URL} - -unpack: - rm -rf ${CONFUSE_SRC_DIR} - tar xfz ${TARFILE_LOCAL} - -clean:: - rm -rf ${CONFUSE_SRC_DIR} - -configure: - rm -rf ${CONFUSE_BUILD_DIR} - mkdir ${CONFUSE_BUILD_DIR} - cd ${CONFUSE_BUILD_DIR} && ${CONFUSE_SRC_DIR}/configure \ - --prefix=${PREFIX} \ - --exec-prefix=${EXEC_PREFIX} - -clean:: - rm -rf ${CONFUSE_BUILD_DIR} - -build: - cd ${CONFUSE_BUILD_DIR} && ${MAKE} - -install: - cd ${CONFUSE_BUILD_DIR} && ${MAKE} install - -all: unpack configure build install - -_complain_: - @echo "" - @echo "Please try one of these targets: bootstrap, clean, configure, build, install" - @echo " Or read the makefile and learn about the permutation test targets" - @echo "" - @echo "You also might find the download and unpack targets helpful." - @echo "" - @exit 1 diff --git a/testing/build.test1/Makefile.ftd2xx b/testing/build.test1/Makefile.ftd2xx deleted file mode 100644 index 3f19e7720..000000000 --- a/testing/build.test1/Makefile.ftd2xx +++ /dev/null @@ -1,88 +0,0 @@ -# -*- mode: makefile -*- -# -default: _complain_ - -include ./local.uses - -# WARNING... the file on the ftdi chip site has a SPACE in the filename GRRR!!! -# We fix that with the "-O" option to wget. -ZIPFILE_LOCAL=${VIRGINS}/cdm.${FTD2XX_WIN32_VERSION}.zip -ZIPFILE_URL ="http://www.ftdichip.com/Drivers/CDM/CDM ${FTD2XX_WIN32_VERSION}.zip" - -TARFILE_LOCAL=${VIRGINS}/libftd2xx${FTD2XX_LINUX_VERSION}.tar.gz -TARFILE_URL =http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx${FTD2XX_LINUX_VERSION}.tar.gz - -TARFILE_64_LOCAL=${VIRGINS}/libftd2xx${FTD2XX_LINUX_VERSION}_x86_64.tar.gz -TARFILE_64_URL =http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx${FTD2XX_LINUX_VERSION}_x86_64.tar.gz - - -download.win32: - mkdir -p ${VIRGINS} - wget -O ${ZIPFILE_LOCAL} ${ZIPFILE_URL} - -unpack.win32: - rm -rf ${FTD2XX_WIN32_DIR} - mkdir -p ${FTD2XX_WIN32_DIR} - cd ${FTD2XX_WIN32_DIR} && unzip ${ZIPFILE_LOCAL} - -clean:: - rm -rf ${FTD2XX_WIN32_DIR} - -download.linux: - mkdir -p ${VIRGINS} - wget -O ${TARFILE_LOCAL} ${TARFILE_URL} - -clean:: - rm -rf ${FTD2XX_LINUX_DIR} - -unpack.linux: - rm -rf ${FTD2XX_LINUX_DIR} - mkdir -p ${FTD2XX_LINUX_DIR} - tar xfz ${TARFILE_LOCAL} - -download.linux.x86_64: - mkdir -p ${VIRGINS} - wget -O ${TARFILE_LOCAL} ${TARFILE_URL} - -unpack.linux.x86_64: - rm -rf ${FTD2XX_LINUX_64_DIR} - mkdir -p ${FTD2XX_LINUX_64_DIR} - tar xfz ${TARFILE_64_LOCAL} - -clean:: - rm -rf ${FTD2XX_LINUX_64_DIR} - -download: download.win32 download.linux - -unpack.cygwin unpack.mingw32: unpack.win32 - -unpack: unpack.${BUILD_SYSNAME} - -# Nothing to do here -build: - @echo "Done" - -#Nothing to do here -configure: - @echo "Done" - -# Nothing to do here -install: - @echo "Done" - -all: unpack configure build install - -.PHONY: install - -# Nothing to do here -clean:: - @echo "Done" - -_complain_: - @echo "" - @echo "Please try one of these targets: bootstrap, clean, configure, build, install" - @echo " Or read the makefile and learn about the permutation test targets" - @echo "" - @echo "You also might find the download and unpack targets helpful." - @echo "" - @exit 1 diff --git a/testing/build.test1/Makefile.libftdi b/testing/build.test1/Makefile.libftdi deleted file mode 100644 index 1a9612c05..000000000 --- a/testing/build.test1/Makefile.libftdi +++ /dev/null @@ -1,51 +0,0 @@ -# -*- mode: makefile -*- -default: _complain_ -include ./local.uses - -TARFILE_LOCAL = ${VIRGINS}/libftdi-${LIBFTDI_VERSION}.tar.gz -TARFILE_URL = http://www.intra2net.com/de/produkte/opensource/ftdi/TGZ/libftdi-${LIBFTDI_VERSION}.tar.gz - -LIBFTDI_SRC_DIR = ${HERE}/libftdi-${LIBFTDI_VERSION} -LIBFTDI_BUILD_DIR= ${HERE}/libftdi-build - -download: - mkdir -p virgins - wget -O ${TARFILE_LOCAL} ${TARFILE_URL} - -clean:: - rm -rf ${LIBFTDI_SRC_DIR} - -unpack: - tar xf ${TARFILE_LOCAL} - -PATH := ${EXEC_PREFIX}/bin:${PATH} -export PATH - -clean:: - rm -rf ${LIBFTDI_BUILD_DIR} - -configure: - rm -rf ${LIBFTDI_BUILD_DIR} - mkdir -p ${LIBFTDI_BUILD_DIR} - cd ${LIBFTDI_BUILD_DIR} && ${LIBFTDI_SRC_DIR}/configure \ - --prefix=${PREFIX} \ - --exec-prefix=${EXEC_PREFIX} - -build: - cd ${LIBFTDI_BUILD_DIR} && ${MAKE} - -install: - cd ${LIBFTDI_BUILD_DIR} && ${MAKE} install - -all: unpack configure build install - -.PHONY: install - -_complain_: - @echo "" - @echo "Please try one of these targets: bootstrap, clean, configure, build, install" - @echo " Or read the makefile and learn about the permutation test targets" - @echo "" - @echo "You also might find the download and unpack targets helpful." - @echo "" - @exit 1 diff --git a/testing/build.test1/Makefile.libusb b/testing/build.test1/Makefile.libusb deleted file mode 100644 index 815592a18..000000000 --- a/testing/build.test1/Makefile.libusb +++ /dev/null @@ -1,55 +0,0 @@ -# -*- mode: makefile -*- -default: _complain_ - -include ./local.uses - -ifeq (x"$BUILD_SYSNAME",x"cygwin") -$(error Please use the Win32 specific port of LibUSB not the Unix version) -endif -ifeq (x"$BUILD_SYSNAME",x"mingw32") -$(error Please use the win32 specific port of LibUSB not the Unix version) -endif - -TARFILE_LOCAL = ${VIRGINS}/libusb-${LIBUSB_VERSION_linux}.tar.bz2 -TARFILE_URL = http://downloads.sourceforge.net/libusb/libusb-${LIBUSB_VERSION_linux}.tar.gz - -LIBUSB_SRC_DIR = ${HERE}/libusb-${LIBUSB_VERSION} -LIBUSB_BUILD_DIR = ${HERE}/libusb-build - -download: - wget -O ${TARFILE_LOCAL} ${TARFILE_URL} - -unpack: - rm -rf ${LIBUSB_SRC_DIR} - tar xfz ${TARFILE_LOCAL} - -clean:: - rm -rf ${LIBUSB_SRC_DIR} - -configure: - rm -rf ${LIBUSB_BUILD_DIR} - mkdir -p ${LIBUSB_BUILD_DIR} - cd ${LIBUSB_BUILD_DIR} && ${LIBUSB_SRC_DIR}/configure \ - --prefix=${PREFIX} --exec-prefix=${EXEC_PREFIX} - -clean:: - rm -rf ${LIBUSB_BUILD_DIR} - -build: - cd ${LIBUSB_BUILD_DIR} && ${MAKE} - -install: - cd ${LIBUSB_BUILD_DIR} && ${MAKE} install - -all: unpack configure build install - -.PHONY: install - -_complain_: - @echo "" - @echo "Please try one of these targets: bootstrap, clean, configure, build, install" - @echo " Or read the makefile and learn about the permutation test targets" - @echo "" - @echo "You also might find the download and unpack targets helpful." - @echo "" - @exit 1 diff --git a/testing/build.test1/Makefile.openocd b/testing/build.test1/Makefile.openocd deleted file mode 100644 index 6b0cb56ff..000000000 --- a/testing/build.test1/Makefile.openocd +++ /dev/null @@ -1,193 +0,0 @@ -# -*- mode: makefile -*- -# -default: _complain_ - -include ./local.uses - - -SRC_DIR ?= $(HERE)/openocd -BUILD_SUFFIX ?= $(BUILD_MACHINE) -BUILD_DIR =$(HERE)/openocd.$(BUILD_SUFFIX) - -checkout: - svn co https://svn.berlios.de/svnroot/repos/openocd/trunk openocd - -remove.install: - rm -rf ${INSTALL_DIR} - -#======================================== -# Win32 Build Permutations -# none -# parport -# ftd2xx - (ftdichip) -# libftd -CONFIG_OPTIONS_win32_none = -CONFIG_OPTIONS_win32_parport = --enable-parport -CONFIG_OPTIONS_win32_ftd2xx = --enable-parport --enable-ft2232_ftd2xx --with-ftd2xx-win32-zipdir=$(FTD2XX_WIN32_DIR) - -CYGWIN_EASY_PERMUTATIONS += none -CYGWIN_EASY_PERMUTATIONS += parport -CYGWIN_EASY_PERMUTATIONS += ftd2xx - -MINGW32_EASY_PERMUTATIONS += none -MINGW32_EASY_PERMUTATIONS += parport -MINGW32_EASY_PERMUTATIONS += ftd2xx - - -# This is not a possible permutation, it is manual :-( -# Why? Because "libftdi" installs things into install/include -# which would efect the 'ftd2xx' win32 build -CONFIG_OPTIONS_win32_libftdi = --enable-parport --enable-ft2232_libftdi - -# Default build for win32... is the ftd2xx type build. -PERMUTE_win32 ?= ftd2xx -CONFIG_OPTIONS_win32 ?= $(CONFIG_OPTIONS_win32_$(PERMUTE_win32)) -CONFIG_OPTIONS_cygwin = $(CONFIG_OPTIONS_win32) -CONFIG_OPTIONS_mingw32 = $(CONFIG_OPTIONS_win32) - -#======================================== -# Linux Build Permuatations -# none -# parport -# ft2232_ftd2xx -# ft2232_libftdi -CONFIG_OPTIONS_linux_none = -LINUX_EASY_PERMUTATIONS += none - -CONFIG_OPTIONS_linux_parport = --enable-parport -LINUX_EASY_PERMUTATIONS += parport - -CONFIG_OPTIONS_linux_ft2232_libftdi = --enable-parport --enable-ft2232-libftdi -#this cannot be done as part of the permutations. -#LINUX_EASY_PERMUTATIONS += ft2232_libftdi - -CONFIG_OPTIONS_linux_ft2232_ftd2xx_static = \ - --enable-parport \ - --enable-ft2232-ftd2xx --with-ftd2xx-lib=static --with-ftd2xx-linux-tardir=$(FTD2XX_LINUX_DIR) -LINUX_EASY_PERMUTATIONS += ft2232_ftd2xx_static - -# this is not a possible permutation it is manual :-( -# why? because it interfers with the other permutations -# by "installing files" in the $(INSTALL_DIR) -CONFIG_OPTIONS_linux_ftd2xx_installed = \ - --enable-parport \ - --enable-ft2232-ftd2xx \ - --with-ftd2xx-lib=shared - -# The default build permutation is -PERMUTE_linux ?= ft2232_ftd2xx_static -CONFIG_OPTIONS_linux = $(CONFIG_OPTIONS_linux_$(PERMUTE_linux)) - -CONFIG_OPTIONS_darwin=\ - --enable-ftd2232-libftdi - -# Which build are we doing? -CONFIG_OPTIONS := $(CONFIG_OPTIONS_$(BUILD_SYSNAME)) - -bootstrap: - cd $(SRC_DIR) && bash ./bootstrap - -clean:: - rm -rf $(BUILD_DIR) - -ifndef CFLAGS -_CFLAGS=true -else -_CFLAGS=export CFLAGS="${CFLAGS}" -endif - - -# if this was given... then pass it on -configure: - @echo " Build Sysname: $(BUILD_SYSNAME)" - @echo " Config Options: $(CONFIG_OPTIONS)" - rm -rf $(BUILD_DIR) - mkdir $(BUILD_DIR) - ${_CFLAGS} && \ - cd $(BUILD_DIR) && \ - $(SRC_DIR)/configure \ - --prefix=$(PREFIX) \ - --exec-prefix=$(EXEC_PREFIX) \ - $(CONFIG_OPTIONS) - -build: - cd $(BUILD_DIR) && $(MAKE) - -install: - cd $(BUILD_DIR) && $(MAKE) install - -all: configure build install - -.PHONY: install - -# The "cygwin.libftdi" requires that libftdi be built -# and installed *PRIOR* to running this target. -# it is not part of the permutations because ... -# it interfers with the ftd2xx based builds -cygwin.libftdi: - $(MAKE) -f Makefile.openocd bootstrap - $(MAKE) BUILD_SUFFIX=$@ PERMUTE_win32=libftdi -f Makefile.openocd all - -cygwin.easy.permutations: remove.install ${CYGWIN_EASY_PERMUTATIONS:%=_cygwin.%} - -_cygwin.%: - @echo "" - @echo "" - @echo "========================================" - @echo "Permutation Build... $@" - @echo "========================================" - @echo "" - @echo "" - $(MAKE) PERMUTE_win32=$* BUILD_SUFFIX=cygwin.$* -f Makefile.openocd all - $(EXEC_PREFIX)/bin/openocd -v - -mingw32.easy.permutations: remove.install ${MINGW32_EASY_PERMUTATIONS:%=_mingw32.%} - -# I (duane) build openocd-mingw32 via Cygwin. -# Sadly, the "mingw32" buid for cygwin does not include -# the required "elf.h" header files... so ... -# we have them in our own private helper place. -_mingw32.%: - @echo "" - @echo "" - @echo "========================================" - @echo "Permutation Build... $@" - @echo "========================================" - @echo "" - @echo "" - CFLAGS="-mno-cygwin -I$(HERE)/mingw32_help/include" \ - $(MAKE) -f Makefile.openocd all ;\ - $(EXEC_PREFIX)/bin/openocd -v - -win32.permutations: mingw32.permutations cygwin.permutations - - -# SMOKE TEST - Build every linux permuation... -# If "openocd -v" does exit(0) we are good enough. - -linux.easy.permutations: remove.install ${LINUX_EASY_PERMUTATIONS:%=_linux.%} - - -_linux.%: - @echo "" - @echo "" - @echo "========================================" - @echo "Permutation Build... $@" - @echo "========================================" - @echo "" - @echo "" - $(MAKE) PERMUTE_linux=$* BUILD_SUFFIX=linux.$* -f Makefile.openocd all - $(EXEC_PREFIX)/bin/openocd -v - -linux.ftd2xx_installed: - ${MAKE} -f Makefile.openocd _$@ - -linux.ft2232_libftdi: - ${MAKE} -f Makefile.openocd _$@ - -_complain_: - @echo "" - @echo "Please try one of these targets: bootstrap, clean, configure, build, install" - @echo " Or read the makefile and learn about the permutation test targets" - @echo "" - @exit 1 diff --git a/testing/build.test1/README.TXT b/testing/build.test1/README.TXT deleted file mode 100644 index 7f4d401e8..000000000 --- a/testing/build.test1/README.TXT +++ /dev/null @@ -1,38 +0,0 @@ --- Duane Ellis'es test case for building numerous openocd configurations... -Dec 26,2008 ---------------------------------------------------------------------------- - -1) Make a directory some where.. - - mkdir ~/test - -2) Change to that directory - - cd ~/test - -3) Checkout OpenOCD in that directory. - - cd ~/test - svn co https://svn.berlios.de/svnroot/repos/openocd/trunk openocd - -4) Copy the "build.test1" directory to the "~/work" directory. - - - cd ~/test - cp ~/openocd/testing/build.test1/. ~/test/. - -5) If needed, download various components. - - cd ~/work - make all.download - - -6) For Linux - type: - - cd ~/work - make linux.buildtest - -7) For Cygwin - type: - - cd ~/work - make cygwin.buildtest diff --git a/testing/build.test1/local.uses b/testing/build.test1/local.uses deleted file mode 100644 index 6c6795b54..000000000 --- a/testing/build.test1/local.uses +++ /dev/null @@ -1,39 +0,0 @@ -# -*- mode: makefile -*- -HERE := $(shell pwd) - -# Solve problems on systems with DASH.. Grrr... -SHELL=/bin/bash -export SHELL - -VIRGINS=${HERE}/virgins - -# Determine the build platform. -BUILD_SYSNAME_Linux =linux -BUILD_SYSNAME_linux =linux -BUILD_SYSNAME_CYGWIN_NT =cygwin -BUILD_SYSNAME_MINGW32_NT =mingw32 -BUILD_SYSNAME_Darwin =darwin -BUILD_SYSNAME_darwin =darwin -BUILD_SYSNAME :=$(BUILD_SYSNAME_$(shell uname --sysname | cut -d'-' -f1)) - -# And machine (ie: i686, x86_64, or what) -BUILD_MACHINE :=$(BUILD_SYSNAME).$(shell uname -m) - - -INSTALL_DIR := $(HERE)/install -PREFIX := ${INSTALL_DIR} -EXEC_PREFIX := ${INSTALL_DIR}/${BUILD_MACHINE} - -LIBFTDI_VERSION=0.14 -LIBCONFUSE_VERSION=2.5 - -LIBUSB_VERSION_linux=0.1.12 - -LIBUSB_VERSION=${LIBUSB_VERSION_${BUILD_SYSNAME}} - -FTD2XX_WIN32_VERSION=2.04.14 -FTD2XX_WIN32_DIR = ${HERE}/ftd2xx.win32 - -FTD2XX_LINUX_VERSION=0.4.16 -FTD2XX_LINUX_DIR = ${HERE}/libftd2xx${FTD2XX_LINUX_VERSION} -FTD2XX_LINUX_64_DIR = ${HERE}/libftd2xx${FTD2XX_LINUX_VERSION}_x86_64 diff --git a/testing/build.test1/mingw32_help/include/elf.h b/testing/build.test1/mingw32_help/include/elf.h deleted file mode 100644 index 23d4aa2d5..000000000 --- a/testing/build.test1/mingw32_help/include/elf.h +++ /dev/null @@ -1,38 +0,0 @@ -/* elf.h - - Copyright 2005 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef _ELF_H_ -#define _ELF_H_ - -#include - -typedef signed char int8_t; -typedef unsigned char u_int8_t; -typedef short int16_t; -typedef unsigned short u_int16_t; -typedef int int32_t; -typedef unsigned int u_int32_t; -typedef long long int64_t; -typedef unsigned long long u_int64_t; -typedef int32_t register_t; - - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include -#include -#ifdef __cplusplus -} -#endif - -#endif /*_ELF_H_*/ diff --git a/testing/build.test1/mingw32_help/include/sys/cdefs.h b/testing/build.test1/mingw32_help/include/sys/cdefs.h deleted file mode 100644 index 606205a58..000000000 --- a/testing/build.test1/mingw32_help/include/sys/cdefs.h +++ /dev/null @@ -1,22 +0,0 @@ -/* sys/cdefs.h - - Copyright 1998, 2000, 2001 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef _SYS_CDEFS_H -#define _SYS_CDEFS_H -#ifdef __cplusplus -#define __BEGIN_DECLS extern "C" { -#define __END_DECLS } -#else -#define __BEGIN_DECLS -#define __END_DECLS -#endif -#define __P(protos) protos /* full-blown ANSI C */ -#define __CONCAT(__x,__y) __x##__y -#endif diff --git a/testing/build.test1/mingw32_help/include/sys/elf32.h b/testing/build.test1/mingw32_help/include/sys/elf32.h deleted file mode 100644 index 5dfe9c8b0..000000000 --- a/testing/build.test1/mingw32_help/include/sys/elf32.h +++ /dev/null @@ -1,156 +0,0 @@ -/*- - * Copyright (c) 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf32.h,v 1.8 2002/05/30 08:32:18 dfr Exp $ - */ - -#ifndef _SYS_ELF32_H_ -#define _SYS_ELF32_H_ 1 - -#include - -/* - * ELF definitions common to all 32-bit architectures. - */ - -typedef u_int32_t Elf32_Addr; -typedef u_int16_t Elf32_Half; -typedef u_int32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef u_int32_t Elf32_Word; -typedef u_int32_t Elf32_Size; -typedef Elf32_Off Elf32_Hashelt; - -/* - * ELF header. - */ - -typedef struct { - unsigned char e_ident[EI_NIDENT]; /* File identification. */ - Elf32_Half e_type; /* File type. */ - Elf32_Half e_machine; /* Machine architecture. */ - Elf32_Word e_version; /* ELF format version. */ - Elf32_Addr e_entry; /* Entry point. */ - Elf32_Off e_phoff; /* Program header file offset. */ - Elf32_Off e_shoff; /* Section header file offset. */ - Elf32_Word e_flags; /* Architecture-specific flags. */ - Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ - Elf32_Half e_phentsize; /* Size of program header entry. */ - Elf32_Half e_phnum; /* Number of program header entries. */ - Elf32_Half e_shentsize; /* Size of section header entry. */ - Elf32_Half e_shnum; /* Number of section header entries. */ - Elf32_Half e_shstrndx; /* Section name strings section. */ -} Elf32_Ehdr; - -/* - * Section header. - */ - -typedef struct { - Elf32_Word sh_name; /* Section name (index into the - section header string table). */ - Elf32_Word sh_type; /* Section type. */ - Elf32_Word sh_flags; /* Section flags. */ - Elf32_Addr sh_addr; /* Address in memory image. */ - Elf32_Off sh_offset; /* Offset in file. */ - Elf32_Size sh_size; /* Size in bytes. */ - Elf32_Word sh_link; /* Index of a related section. */ - Elf32_Word sh_info; /* Depends on section type. */ - Elf32_Size sh_addralign; /* Alignment in bytes. */ - Elf32_Size sh_entsize; /* Size of each entry in section. */ -} Elf32_Shdr; - -/* - * Program header. - */ - -typedef struct { - Elf32_Word p_type; /* Entry type. */ - Elf32_Off p_offset; /* File offset of contents. */ - Elf32_Addr p_vaddr; /* Virtual address in memory image. */ - Elf32_Addr p_paddr; /* Physical address (not used). */ - Elf32_Size p_filesz; /* Size of contents in file. */ - Elf32_Size p_memsz; /* Size of contents in memory. */ - Elf32_Word p_flags; /* Access permission flags. */ - Elf32_Size p_align; /* Alignment in memory and file. */ -} Elf32_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf32_Sword d_tag; /* Entry type. */ - union { - Elf32_Size d_val; /* Integer value. */ - Elf32_Addr d_ptr; /* Address value. */ - } d_un; -} Elf32_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf32_Addr r_offset; /* Location to be relocated. */ - Elf32_Word r_info; /* Relocation type and symbol index. */ -} Elf32_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf32_Addr r_offset; /* Location to be relocated. */ - Elf32_Word r_info; /* Relocation type and symbol index. */ - Elf32_Sword r_addend; /* Addend. */ -} Elf32_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF32_R_SYM(info) ((info) >> 8) -#define ELF32_R_TYPE(info) ((unsigned char)(info)) - -/* Macro for constructing r_info from field values. */ -#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) - -/* - * Symbol table entries. - */ - -typedef struct { - Elf32_Word st_name; /* String table index of name. */ - Elf32_Addr st_value; /* Symbol value. */ - Elf32_Size st_size; /* Size of associated object. */ - unsigned char st_info; /* Type and binding information. */ - unsigned char st_other; /* Reserved (not used). */ - Elf32_Half st_shndx; /* Section index of symbol. */ -} Elf32_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF32_ST_BIND(info) ((info) >> 4) -#define ELF32_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -#endif /* !_SYS_ELF32_H_ */ diff --git a/testing/build.test1/mingw32_help/include/sys/elf64.h b/testing/build.test1/mingw32_help/include/sys/elf64.h deleted file mode 100644 index 48556be5f..000000000 --- a/testing/build.test1/mingw32_help/include/sys/elf64.h +++ /dev/null @@ -1,172 +0,0 @@ -/*- - * Copyright (c) 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf64.h,v 1.10 2002/05/30 08:32:18 dfr Exp $ - */ - -#ifndef _SYS_ELF64_H_ -#define _SYS_ELF64_H_ 1 - -#include - -/* - * ELF definitions common to all 64-bit architectures. - */ - -typedef uint64_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; -typedef uint64_t Elf64_Off; -typedef uint16_t Elf64_Section; -typedef Elf64_Half Elf64_Versym; -typedef uint16_t Elf64_Quarter; - -/* - * Types of dynamic symbol hash table bucket and chain elements. - * - * This is inconsistent among 64 bit architectures, so a machine dependent - * typedef is required. - */ - -#ifdef __alpha__ -typedef Elf64_Off Elf64_Hashelt; -#else -typedef Elf64_Half Elf64_Hashelt; -#endif - -/* - * ELF header. - */ - -typedef struct { - unsigned char e_ident[EI_NIDENT]; /* File identification. */ - Elf64_Half e_type; /* File type. */ - Elf64_Half e_machine; /* Machine architecture. */ - Elf64_Word e_version; /* ELF format version. */ - Elf64_Addr e_entry; /* Entry point. */ - Elf64_Off e_phoff; /* Program header file offset. */ - Elf64_Off e_shoff; /* Section header file offset. */ - Elf64_Word e_flags; /* Architecture-specific flags. */ - Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ - Elf64_Half e_phentsize; /* Size of program header entry. */ - Elf64_Half e_phnum; /* Number of program header entries. */ - Elf64_Half e_shentsize; /* Size of section header entry. */ - Elf64_Half e_shnum; /* Number of section header entries. */ - Elf64_Half e_shstrndx; /* Section name strings section. */ -} Elf64_Ehdr; - -/* - * Section header. - */ - -typedef struct { - Elf64_Word sh_name; /* Section name (index into the - section header string table). */ - Elf64_Word sh_type; /* Section type. */ - Elf64_Xword sh_flags; /* Section flags. */ - Elf64_Addr sh_addr; /* Address in memory image. */ - Elf64_Off sh_offset; /* Offset in file. */ - Elf64_Xword sh_size; /* Size in bytes. */ - Elf64_Word sh_link; /* Index of a related section. */ - Elf64_Word sh_info; /* Depends on section type. */ - Elf64_Xword sh_addralign; /* Alignment in bytes. */ - Elf64_Xword sh_entsize; /* Size of each entry in section. */ -} Elf64_Shdr; - -/* - * Program header. - */ - -typedef struct { - Elf64_Word p_type; /* Entry type. */ - Elf64_Word p_flags; /* Access permission flags. */ - Elf64_Off p_offset; /* File offset of contents. */ - Elf64_Addr p_vaddr; /* Virtual address in memory image. */ - Elf64_Addr p_paddr; /* Physical address (not used). */ - Elf64_Xword p_filesz; /* Size of contents in file. */ - Elf64_Xword p_memsz; /* Size of contents in memory. */ - Elf64_Xword p_align; /* Alignment in memory and file. */ -} Elf64_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf64_Sxword d_tag; /* Entry type. */ - union { - Elf64_Xword d_val; /* Integer value. */ - Elf64_Addr d_ptr; /* Address value. */ - } d_un; -} Elf64_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf64_Addr r_offset; /* Location to be relocated. */ - Elf64_Xword r_info; /* Relocation type and symbol index. */ -} Elf64_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf64_Addr r_offset; /* Location to be relocated. */ - Elf64_Xword r_info; /* Relocation type and symbol index. */ - Elf64_Sxword r_addend; /* Addend. */ -} Elf64_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF64_R_SYM(info) ((info) >> 32) -#define ELF64_R_TYPE(info) ((unsigned char)(info)) - -/* Macro for constructing r_info from field values. */ -#define ELF64_R_INFO(sym, type) (((sym) << 32) + (unsigned char)(type)) - -/* - * Symbol table entries. - */ - -typedef struct { - Elf64_Word st_name; /* String table index of name. */ - unsigned char st_info; /* Type and binding information. */ - unsigned char st_other; /* Reserved (not used). */ - Elf64_Section st_shndx; /* Section index of symbol. */ - Elf64_Addr st_value; /* Symbol value. */ - Elf64_Xword st_size; /* Size of associated object. */ -} Elf64_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF64_ST_BIND(info) ((info) >> 4) -#define ELF64_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -#endif /* !_SYS_ELF64_H_ */ diff --git a/testing/build.test1/mingw32_help/include/sys/elf_common.h b/testing/build.test1/mingw32_help/include/sys/elf_common.h deleted file mode 100644 index b864f0464..000000000 --- a/testing/build.test1/mingw32_help/include/sys/elf_common.h +++ /dev/null @@ -1,299 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf_common.h,v 1.15 2004/05/05 02:38:54 marcel Exp $ - */ - -#ifndef _SYS_ELF_COMMON_H_ -#define _SYS_ELF_COMMON_H_ 1 - -/* - * ELF definitions that are independent of architecture or word size. - */ - -/* - * Note header. The ".note" section contains an array of notes. Each - * begins with this header, aligned to a word boundary. Immediately - * following the note header is n_namesz bytes of name, padded to the - * next word boundary. Then comes n_descsz bytes of descriptor, again - * padded to a word boundary. The values of n_namesz and n_descsz do - * not include the padding. - */ - -typedef struct { - u_int32_t n_namesz; /* Length of name. */ - u_int32_t n_descsz; /* Length of descriptor. */ - u_int32_t n_type; /* Type of this note. */ -} Elf_Note; - -/* Indexes into the e_ident array. Keep synced with - http://www.sco.com/developer/gabi/ch4.eheader.html */ -#define EI_MAG0 0 /* Magic number, byte 0. */ -#define EI_MAG1 1 /* Magic number, byte 1. */ -#define EI_MAG2 2 /* Magic number, byte 2. */ -#define EI_MAG3 3 /* Magic number, byte 3. */ -#define EI_CLASS 4 /* Class of machine. */ -#define EI_DATA 5 /* Data format. */ -#define EI_VERSION 6 /* ELF format version. */ -#define EI_OSABI 7 /* Operating system / ABI identification */ -#define EI_ABIVERSION 8 /* ABI version */ -#define OLD_EI_BRAND 8 /* Start of architecture identification. */ -#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ -#define EI_NIDENT 16 /* Size of e_ident array. */ - -/* Values for the magic number bytes. */ -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" /* magic string */ -#define SELFMAG 4 /* magic string size */ - -/* Values for e_ident[EI_VERSION] and e_version. */ -#define EV_NONE 0 -#define EV_CURRENT 1 - -/* Values for e_ident[EI_CLASS]. */ -#define ELFCLASSNONE 0 /* Unknown class. */ -#define ELFCLASS32 1 /* 32-bit architecture. */ -#define ELFCLASS64 2 /* 64-bit architecture. */ - -/* Values for e_ident[EI_DATA]. */ -#define ELFDATANONE 0 /* Unknown data format. */ -#define ELFDATA2LSB 1 /* 2's complement little-endian. */ -#define ELFDATA2MSB 2 /* 2's complement big-endian. */ - -/* Values for e_ident[EI_OSABI]. */ -#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ -#define ELFOSABI_NONE ELFOSABI_SYSV /* symbol used in old spec */ -#define ELFOSABI_HPUX 1 /* HP-UX operating system */ -#define ELFOSABI_NETBSD 2 /* NetBSD */ -#define ELFOSABI_LINUX 3 /* GNU/Linux */ -#define ELFOSABI_HURD 4 /* GNU/Hurd */ -#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ -#define ELFOSABI_SOLARIS 6 /* Solaris */ -#define ELFOSABI_MONTEREY 7 /* Monterey */ -#define ELFOSABI_IRIX 8 /* IRIX */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD */ -#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -/* e_ident */ -#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ - (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ - (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ - (ehdr).e_ident[EI_MAG3] == ELFMAG3) - -/* Values for e_type. */ -#define ET_NONE 0 /* Unknown type. */ -#define ET_REL 1 /* Relocatable. */ -#define ET_EXEC 2 /* Executable. */ -#define ET_DYN 3 /* Shared object. */ -#define ET_CORE 4 /* Core file. */ - -/* Values for e_machine. */ -#define EM_NONE 0 /* Unknown machine. */ -#define EM_M32 1 /* AT&T WE32100. */ -#define EM_SPARC 2 /* Sun SPARC. */ -#define EM_386 3 /* Intel i386. */ -#define EM_68K 4 /* Motorola 68000. */ -#define EM_88K 5 /* Motorola 88000. */ -#define EM_486 6 /* Intel i486. */ -#define EM_860 7 /* Intel i860. */ -#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ - -/* Extensions. This list is not complete. */ -#define EM_S370 9 /* IBM System/370 */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ /* Depreciated */ -#define EM_PARISC 15 /* HPPA */ -#define EM_SPARC32PLUS 18 /* SPARC v8plus */ -#define EM_PPC 20 /* PowerPC 32-bit */ -#define EM_PPC64 21 /* PowerPC 64-bit */ -#define EM_ARM 40 /* ARM */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_IA_64 50 /* Intel IA-64 Processor */ -#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ -#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI */ - -/* Special section indexes. */ -#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ -#define SHN_LORESERVE 0xff00 /* First of reserved range. */ -#define SHN_LOPROC 0xff00 /* First processor-specific. */ -#define SHN_HIPROC 0xff1f /* Last processor-specific. */ -#define SHN_ABS 0xfff1 /* Absolute values. */ -#define SHN_COMMON 0xfff2 /* Common data. */ -#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ - -/* sh_type */ -#define SHT_NULL 0 /* inactive */ -#define SHT_PROGBITS 1 /* program defined information */ -#define SHT_SYMTAB 2 /* symbol table section */ -#define SHT_STRTAB 3 /* string table section */ -#define SHT_RELA 4 /* relocation section with addends */ -#define SHT_HASH 5 /* symbol hash table section */ -#define SHT_DYNAMIC 6 /* dynamic section */ -#define SHT_NOTE 7 /* note section */ -#define SHT_NOBITS 8 /* no space section */ -#define SHT_REL 9 /* relocation section - no addends */ -#define SHT_SHLIB 10 /* reserved - purpose unknown */ -#define SHT_DYNSYM 11 /* dynamic symbol table section */ -#define SHT_NUM 12 /* number of section types */ -#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ -#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ -#define SHT_LOPROC 0x70000000 /* reserved range for processor */ -#define SHT_HIPROC 0x7fffffff /* specific section header types */ -#define SHT_LOUSER 0x80000000 /* reserved range for application */ -#define SHT_HIUSER 0xffffffff /* specific indexes */ - -/* Flags for sh_flags. */ -#define SHF_WRITE 0x1 /* Section contains writable data. */ -#define SHF_ALLOC 0x2 /* Section occupies memory. */ -#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ -#define SHF_TLS 0x400 /* Section contains TLS data. */ -#define SHF_MASKPROC 0xf0000000 /* Reserved for processor-specific. */ - -/* Values for p_type. */ -#define PT_NULL 0 /* Unused entry. */ -#define PT_LOAD 1 /* Loadable segment. */ -#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ -#define PT_INTERP 3 /* Pathname of interpreter. */ -#define PT_NOTE 4 /* Auxiliary information. */ -#define PT_SHLIB 5 /* Reserved (not used). */ -#define PT_PHDR 6 /* Location of program header itself. */ -#define PT_TLS 7 /* Thread local storage segment */ - -#define PT_COUNT 8 /* Number of defined p_type values. */ - -#define PT_LOOS 0x60000000 /* OS-specific */ -#define PT_HIOS 0x6fffffff /* OS-specific */ -#define PT_LOPROC 0x70000000 /* First processor-specific type. */ -#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ - -/* Values for p_flags. */ -#define PF_X 0x1 /* Executable. */ -#define PF_W 0x2 /* Writable. */ -#define PF_R 0x4 /* Readable. */ - -/* Values for d_tag. */ -#define DT_NULL 0 /* Terminating entry. */ -#define DT_NEEDED 1 /* String table offset of a needed shared - library. */ -#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ -#define DT_PLTGOT 3 /* Processor-dependent address. */ -#define DT_HASH 4 /* Address of symbol hash table. */ -#define DT_STRTAB 5 /* Address of string table. */ -#define DT_SYMTAB 6 /* Address of symbol table. */ -#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ -#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ -#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ -#define DT_STRSZ 10 /* Size of string table. */ -#define DT_SYMENT 11 /* Size of each symbol table entry. */ -#define DT_INIT 12 /* Address of initialization function. */ -#define DT_FINI 13 /* Address of finalization function. */ -#define DT_SONAME 14 /* String table offset of shared object - name. */ -#define DT_RPATH 15 /* String table offset of library path. [sup] */ -#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ -#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ -#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ -#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ -#define DT_PLTREL 20 /* Type of relocation used for PLT. */ -#define DT_DEBUG 21 /* Reserved (not used). */ -#define DT_TEXTREL 22 /* Indicates there may be relocations in - non-writable segments. [sup] */ -#define DT_JMPREL 23 /* Address of PLT relocations. */ -#define DT_BIND_NOW 24 /* [sup] */ -#define DT_INIT_ARRAY 25 /* Address of the array of pointers to - initialization functions */ -#define DT_FINI_ARRAY 26 /* Address of the array of pointers to - termination functions */ -#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of - initialization functions. */ -#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of - terminationfunctions. */ -#define DT_RUNPATH 29 /* String table offset of a null-terminated - library search path string. */ -#define DT_FLAGS 30 /* Object specific flag values. */ -#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING - and less than DT_LOOS follow the rules for - the interpretation of the d_un union - as follows: even == 'd_ptr', even == 'd_val' - or none */ -#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to - pre-initialization functions. */ -#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of - pre-initialization functions. */ - -#define DT_COUNT 33 /* Number of defined d_tag values. */ - -#define DT_LOOS 0x6000000d /* First OS-specific */ -#define DT_HIOS 0x6fff0000 /* Last OS-specific */ -#define DT_LOPROC 0x70000000 /* First processor-specific type. */ -#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ - -/* Values for DT_FLAGS */ -#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may - make reference to the $ORIGIN substitution - string */ -#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ -#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in - non-writable segments. */ -#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should - process all relocations for the object - containing this entry before transferring - control to the program. */ -#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or - executable contains code using a static - thread-local storage scheme. */ - -/* Values for n_type. Used in core files. */ -#define NT_PRSTATUS 1 /* Process status. */ -#define NT_FPREGSET 2 /* Floating point registers. */ -#define NT_PRPSINFO 3 /* Process state info. */ - -/* Symbol Binding - ELFNN_ST_BIND - st_info */ -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* like global - lower precedence */ -#define STB_LOPROC 13 /* reserved range for processor */ -#define STB_HIPROC 15 /* specific symbol bindings */ - -/* Symbol type - ELFNN_ST_TYPE - st_info */ -#define STT_NOTYPE 0 /* Unspecified type. */ -#define STT_OBJECT 1 /* Data object. */ -#define STT_FUNC 2 /* Function. */ -#define STT_SECTION 3 /* Section. */ -#define STT_FILE 4 /* Source file. */ -#define STT_TLS 6 /* TLS object. */ -#define STT_LOPROC 13 /* reserved range for processor */ -#define STT_HIPROC 15 /* specific symbol types */ - -/* Special symbol table indexes. */ -#define STN_UNDEF 0 /* Undefined symbol index. */ - -#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/testing/build.test1/mingw32_help/include/sys/elf_generic.h b/testing/build.test1/mingw32_help/include/sys/elf_generic.h deleted file mode 100644 index dbe9f1e83..000000000 --- a/testing/build.test1/mingw32_help/include/sys/elf_generic.h +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf_generic.h,v 1.6 2002/07/20 02:56:11 peter Exp $ - */ - -#ifndef _SYS_ELF_GENERIC_H_ -#define _SYS_ELF_GENERIC_H_ 1 - -#include - -/* - * Definitions of generic ELF names which relieve applications from - * needing to know the word size. - */ - -#ifndef __ELF_WORD_SIZE -# define __ELF_WORD_SIZE 32 -#endif - -#if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64 -#error "__ELF_WORD_SIZE must be defined as 32 or 64" -#endif - -#define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE) - -#if BYTE_ORDER == LITTLE_ENDIAN -#define ELF_DATA ELFDATA2LSB -#elif BYTE_ORDER == BIG_ENDIAN -#define ELF_DATA ELFDATA2MSB -#else -#error "Unknown byte order" -#endif - -#if __ELF_WORD_SIZE == 32 -#define __elfN(x) elf32_##x -#define __ElfN(x) Elf32_##x -#define __ELFN(x) ELF32_##x -#else -#define __elfN(x) elf364_##x -#define __ElfN(x) Elf364_##x -#define __ELFN(x) ELF364_##x -#endif -#define __ElfType(x) typedef __ElfN(x) Elf_##x - -#define FOO -__ElfType(Addr); -__ElfType(Half); -__ElfType(Off); -__ElfType(Sword); -__ElfType(Word); -__ElfType(Size); -__ElfType(Hashelt); -__ElfType(Ehdr); -__ElfType(Shdr); -__ElfType(Phdr); -__ElfType(Dyn); -__ElfType(Rel); -__ElfType(Rela); -__ElfType(Sym); - -#define ELF_R_SYM __ELFN(R_SYM) -#define ELF_R_TYPE __ELFN(R_TYPE) -#define ELF_R_INFO __ELFN(R_INFO) -#define ELF_ST_BIND __ELFN(ST_BIND) -#define ELF_ST_TYPE __ELFN(ST_TYPE) -#define ELF_ST_INFO __ELFN(ST_INFO) - -#endif /* !_SYS_ELF_GENERIC_H_ */ diff --git a/testing/build.test2/Makefile b/testing/build.test2/Makefile deleted file mode 100644 index d4c428edd..000000000 --- a/testing/build.test2/Makefile +++ /dev/null @@ -1,193 +0,0 @@ -# -*- mode: makefile -*- -#======================================== -# DO NOT DELETE THE LINE BELOW -_default: default -# DO NOT DELETE THE LINE_ABOVE -#======================================== - -#======================================== -# -# There are no user configurable options here. -# -# All user configurable options are in local.uses -# -include ./local.uses -# -#======================================== - -#======================================== -# This is the USB driver for the FTDI2XX chips. -# It is a "closed" solution from FTDICHIP.COM -# Some claim it is faster then the open/free -# solution: win32-libusb+libftdi. -# -ftd2xx.download: - mkdir -p ${VIRGINS} - wget -O ${FTD2XX_ZIPFILE_LOCAL} \ - ${FTD2XX_ZIPFILE_URL} - -ftd2xx.unpack: - rm -rf ${FTD2XX_WIN32_DIR} - mkdir -p ${FTD2XX_WIN32_DIR} - cd ${FTD2XX_WIN32_DIR} && unzip \ - ${FTD2XX_ZIPFILE_LOCAL} - -ftd2xx.build: - @echo "Nothing to do for: $@" - -ftd2xx.configure: - @echo "Nothing to do for: $@" - -ftd2xx.install: - @echo "Nothing to do for: $@" - -clean:: - rm -rf ${FTD2XX_WIN32_DIR} - -ftd2xx.all: ftd2xx.unpack ftd2xx.configure \ - ftd2xx.build ftd2xx.install - - -#========================================- -# LIBFTDI - requires LIBCONFUSE.. -# So we handle it here :-( - -libconfuse.download: - mkdir -p virgins - wget -O ${LIBCONFUSE_TARFILE_LOCAL} \ - ${LIBCONFUSE_TARFILE_URL} - -libconfuse.unpack: - tar xfz ${LIBCONFUSE_TARFILE_LOCAL} - -clean:: - rm -rf ${LIBCONFUSE_SRC_DIR} - -libconfuse.configure: - rm -rf ${LIBCONFUSE_BUILD_DIR} - mkdir -p ${LIBCONFUSE_BUILD_DIR} - cd ${LIBCONFUSE_BUILD_DIR} && \ - ${LIBCONFUSE_SRC_DIR}/configure \ - --prefix=${PREFIX} - -clean:: - rm -rf ${LIBCONFUSE_BUILD_DIR} - -libconfuse.build: - cd ${LIBCONFUSE_BUILD_DIR} && ${MAKE} - -libconfuse.install: - cd ${LIBCONFUSE_BUILD_DIR} && ${MAKE} install - -libconfuse.all: libconfuse.unpack libconfuse.configure \ - libconfuse.build libconfuse.install - -#======================================== -# LIBFTDI - the open source (and free) -# alternative to (closed) FTD2XX drivers. - -libftdi.download: - mkdir -p virgins - wget -O ${LIBFTDI_TARFILE_LOCAL} \ - ${LIBFTDI_TARFILE_URL} - -libftdi.unpack: - tar xfz ${LIBFTDI_TARFILE_LOCAL} - -clean:: - rm -rf ${LIBFTDI_SRC_DIR} - -libftdi.configure: - rm -rf ${LIBFTDI_BUILD_DIR} - mkdir -p ${LIBFTDI_BUILD_DIR} - cd ${LIBFTDI_BUILD_DIR} && \ - ${LIBFTDI_SRC_DIR}/configure \ - --prefix=${PREFIX} - -clean:: - rm -rf ${LIBFTDI_BUILD_DIR} - -libftdi.build: - cd ${LIBFTDI_BUILD_DIR} && ${MAKE} - -libftdi.install: - cd ${LIBFTDI_BUILD_DIR} && ${MAKE} install - -libftdi.all: libftdi.unpack libftdi.configure \ - libftdi.build libftdi.install - -#======================================== -# Openocd... - -openocd.bootstrap: - cd ${OPENOCD_SRC_DIR} && bash ./bootstrap - -openocd.configure: - rm -rf ${OPENOCD_BUILD_DIR} - mkdir -p ${OPENOCD_BUILD_DIR} - cd ${OPENOCD_BUILD_DIR} && ${OPENOCD_SRC_DIR}/configure \ - --prefix=${INSTALL_DIR} \ - ${OPENOCD_CONFIG_OPTIONS} - -openocd.build: - cd ${OPENOCD_BUILD_DIR} && ${MAKE} - -openocd.docs: - cd ${OPENOCD_BUILD_DIR}/docs && ${MAKE} - -openocd.docs.pdf: - cd ${OPENOCD_BUILD_DIR}/docs && ${MAKE} pdf - -openocd.docs.html: - cd ${OPENOCD_BUILD_DIR}/docs && ${MAKE} html - -# fixme: -# need to add a "make one huge html file target" - -openocd.install: - cd ${OPENOCD_BUILD_DIR} && ${MAKE} install - -#======================================== -# The world... - -# Manual step. -download.all: \ - ftd2xx.download \ - libconfuse.download \ - libftdi.download - -ifeq (x"${FT2232_DRIVER}",x"ftd2xx") -prebuild: ftd2xx.all -endif - -ifeq (x"${FT2232_DRIVER}",x"libftdi") -prebuild: libconfuse.all libftdi.all -endif - -remake: \ - openocd.bootstrap \ - openocd.configure \ - openocd.build \ - openocd.install - -initial.build : download.all prebuild remake - -all: - @echo "" - @echo " This makefile does not support an 'all' target" - @echo "" - @echo " If this is your *FIRST* time building... " - @echo " Then use this command: \"make initial.build\"" - @echo "" - @echo " The \"default\" target is for openocd developers" - @echo " and rebuilds openocd completely.." - @echo "" - -default: - test -d ${OPENOCD_SRC_DIR} || (echo "Where is: The OPENOCD source?"; exit 1) - ${MAKE} remake - -whatis_%: - @echo "" - @echo "Makevariable: $* => ${${*}}" - @echo "" diff --git a/testing/build.test2/README.txt b/testing/build.test2/README.txt deleted file mode 100644 index 382105ef0..000000000 --- a/testing/build.test2/README.txt +++ /dev/null @@ -1,58 +0,0 @@ - -This makefile is how I Duane Ellis (openocd@duaneellis.com) builds -openocd test purposes on Cygwin. I have included it here so others -might also make use of the same configuration that I use to develop -Openocd. - ---Duane Ellis - -To make use of it do the following: - -(1) Check out openocd in the standard way. - -For example - in cygwin, type this: - - bash$ mkdir -p /home/duane/test - bash$ cd /home/duane/test - bash$ svn co https://svn.berlios.de/svnroot/repos/openocd/trunk openocd - -(2) COPY this folder "right above" where you have OpenOCD. - - bash$ cd /home/duane/test - bash$ cp ./openocd/testing/build.test2/* /home/duane/test/. - -(3) OPTIONALLY - - You might want to review the file "local.uses" - Change options and so forth at the top of the file. - -(4) Initially, you need to download some additional files. - These include "libftdi", "libconfuse", and the ftd2xx drivers. - -(5) You also need to build the supporting libraries and install them - (They are installed "locally" only) - - Type this command: - - bash$ cd /home/duane/test - - bash$ make initial.build - - which: (1) downloads files - (2) builds the libs - (3) builds OpenOCD - -(6) As you hack upon OpenOCD... to rebuild OpenOCD... - - bash$ cd /home/duane/test - - bash$ make remake - - which: (1) re-bootstraps - (2) re-configures - (3) re-builds - (4) re-installs. - -======= -**END** -======= diff --git a/testing/build.test2/local.uses b/testing/build.test2/local.uses deleted file mode 100644 index edde31b0c..000000000 --- a/testing/build.test2/local.uses +++ /dev/null @@ -1,161 +0,0 @@ -# -*- mode: makefile -*- -#======================================== -# DO NOT REMOVE THE LINE BELOW -HERE := $(shell pwd) -# DO NOT REMOVE THE LINE ABOVE -#======================================== - -# These are common CYGWIN build settings. -# Comment out things you do not want. -# Or unComment things you want. - -# PCs always have printer ports... -X86_PRINTER_PORT ?= y - -# Chose *ONE* of these three solutions. -#FTD2232_DRIVER = none -FT2232_DRIVER = ftd2xx -#FT2232_DRIVER = libftdi - -# Do you have "libusb" installed? -ifeq (x"${FT2232_DRIVER}",x"libftdi") -# With LIBFTDI... LIBUSB is manditory. -USE_LIBUSB = y -endif - -# By default... we assume libusb not present. -USE_LIBUSB ?= n - -#======================================== -# DO NOT EDIT SETTINGS BELOW THIS LINE -#======================================== - - - -#======================================== -# House keeping... - -# Solve problems on systems with DASH.. Grrr... -SHELL=/bin/bash -export SHELL - -VIRGINS ?= ${HERE}/virgins -INSTALL_DIR ?= $(HERE)/install -PREFIX ?= ${INSTALL_DIR} - -# Determine the build platform. -BUILD_SYSNAME_Linux =linux -BUILD_SYSNAME_linux =linux -BUILD_SYSNAME_CYGWIN_NT =cygwin -BUILD_SYSNAME_MINGW32_NT =mingw32 -BUILD_SYSNAME_Darwin =darwin -BUILD_SYSNAME_darwin =darwin -BUILD_SYSNAME :=$(BUILD_SYSNAME_$(shell uname --sysname | cut -d'-' -f1)) - -# And machine (ie: i686, x86_64, or what ever) -BUILD_MACHINE :=$(BUILD_SYSNAME).$(shell uname -m) - - -#======================================== -# - -FTD2XX_LINUX_VERSION=0.4.16 -FTD2XX_LINUX_DIR = ${HERE}/libftd2xx${FTD2XX_LINUX_VERSION} -FTD2XX_LINUX_64_DIR = ${HERE}/libftd2xx${FTD2XX_LINUX_VERSION}_x86_64 - - -# Wiggler type interfaces are here. -OPENOCD_CONFIG_OPTIONS_printer_y += --enable-parport -OPENOCD_CONFIG_OPTIONS_printer_y += --enable-parport-giveio -OPENOCD_CONFIG_OPTIONS_printer_y += --enable-gw16012 -OPENOCD_CONFIG_OPTIONS_printer_y += --enable-parport-giveio -OPENOCD_CONFIG_OPTIONS_printer_y += --enable-amtjtagaccel - - -# FTD2XX only supports these -OPENOCD_CONFIG_OPTIONS_ft2232_none = -OPENOCD_CONFIG_OPTIONS_ft2232_ftd2xx = --enable-ft2232_ftd2xx --enable-presto_ftd2xx --with-ftd2xx-win32-zipdir=${FTD2XX_WIN32_DIR} -OPENOCD_CONFIG_OPTIONS_ft2232_libftdi = --enable-ft2232_libftdi --enable-presto_libftdi - -# LIBUSB - adds support for these. -OPENOCD_CONFIG_OPTIONS_libusb_y += --enable-jlink -OPENOCD_CONFIG_OPTIONS_libusb_y += --enable-usbprog -OPENOCD_CONFIG_OPTIONS_libusb_y += --enable-rlink -OPENOCD_CONFIG_OPTIONS_libusb_y += --enable-vsllink -OPENOCD_CONFIG_OPTIONS_libusb_y += --enable-usbprog - -#======================================== -# EXPLICITY NOT SUPPORTED INTERFACES -# -# zy1000.c -# This is a standalone hardware box -# it is *NOT* a cygwin thing. -# -# at91rm9200.c -# This is a uC/Linux (or linux) that -# runs uC/Linux and uses the gpio pins -# to bit-bang JTAG stuff. -# -# ep93xx.c -# Just like at91rm9200 - different chip. - -#======================================== -# Build OPENOCD config options... -# Always enable "dummy" -OPENOCD_CONFIG_OPTIONS += --enable-dummy -# -# Today: Cannot enable 'oocd_trace' on cygwin. -# it assumes/uses termios functions like -# cfmakeraw() which do not exist on cygwin. -# -#OPENOCD_CONFIG_OPTIONS += --enable-oocd-trace -# -# Add printer options.. -OPENOCD_CONFIG_OPTIONS += ${OPENOCD_CONFIG_OPTIONS_printer_${X86_PRINTER_PORT}} - -# Add the FTD2232 based options. -OPENOCD_CONFIG_OPTIONS += ${OPENOCD_CONFIG_OPTIONS_ft2232_${FT2232_DRIVER}} - -# Add LIBUSB based options. -OPENOCD_CONFIG_OPTIONS += ${OPENOCD_CONFIG_OPTIONS_libusb_${USE_LIBUSB}} - - -#======================================== -# WARNING... the file on the ftdi chip site has a SPACE in the filename GRRR!!! -# We fix that with the "-O" option to wget. -FTD2XX_WIN32_VERSION=2.04.14 -FTD2XX_WIN32_DIR = ${HERE}/ftd2xx.win32 - -FTD2XX_ZIPFILE_LOCAL=${VIRGINS}/cdm.${FTD2XX_WIN32_VERSION}.zip -# Damn thing has a space in the F-ing filename! -FTD2XX_ZIPFILE_URL ="http://www.ftdichip.com/Drivers/CDM/CDM ${FTD2XX_WIN32_VERSION}.zip" - - -#======================================== -# LIBCONFUSE - used by LIBFTDI.. -LIBCONFUSE_VERSION=2.5 -LIBCONFUSE_TARFILE_LOCAL=${VIRGINS}/confuse-${LIBCONFUSE_VERSION}.tar.gz -LIBCONFUSE_TARFILE_URL =http://www.intra2net.com/de/produkte/opensource/ftdi/TGZ/confuse-${LIBCONFUSE_VERSION}.tar.gz - -LIBCONFUSE_SRC_DIR =${HERE}/confuse-${LIBCONFUSE_VERSION} -LIBCONFUSE_BUILD_DIR =${HERE}/confuse-build - - -#======================================== -# LIBFTDI... (which uses libusb, and libconfuse) -LIBFTDI_VERSION=0.14 -LIBFTDI_TARFILE_LOCAL = ${VIRGINS}/libftdi-${LIBFTDI_VERSION}.tar.gz -LIBFTDI_TARFILE_URL = http://www.intra2net.com/de/produkte/opensource/ftdi/TGZ/libftdi-${LIBFTDI_VERSION}.tar.gz - -LIBFTDI_SRC_DIR = ${HERE}/libftdi-${LIBFTDI_VERSION} -LIBFTDI_BUILD_DIR= ${HERE}/libftdi-build - -#======================================== -# Finally - OpenOCD... -# -OPENOCD_BUILD_DIR =${HERE}/openocd-build -OPENOCD_SRC_DIR =${HERE}/openocd - -#======================================== -# END .. -#========================================