Merge branch 'master' into from_upstream

Merged 1ad6ed38b6

Conflicts:
	src/rtos/rtos_standard_stackings.c

Change-Id: Ica8109135de0f9aa87455353a4538b161b844b04
This commit is contained in:
Tim Newsome 2021-11-30 10:36:49 -08:00
commit 61a3f65a0c
115 changed files with 3198 additions and 3298 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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 <channel> <data>}
@deffn {Command} {jlink emucom write} <channel> <data>
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 <channel> <length>}
@deffn {Command} {jlink emucom read} <channel> <length>
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} <serial number>
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.}

2
jimtcl

@ -1 +1 @@
Subproject commit 2d66360c61d2a89d4008e8bad12ae3aa5f0331e2
Subproject commit 70b007b63669a709b0e8aef34a22658047815cc2

View File

@ -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;
}

View File

@ -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. */

View File

@ -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 },

View File

@ -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 = &marker;
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,

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -21,7 +21,7 @@
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
#include <target/armv7m.h>
#include <target/cortex_m.h>
/* 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,

View File

@ -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(&reg_params[0], "r0", 32, PARAM_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
init_reg_param(&reg_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(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_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(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_params[4]);
return retval;
}

View File

@ -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);

View File

@ -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 }

View File

@ -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");

View File

@ -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
*/

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* 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 Hollenbeck <dick@softplc.com>
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>
* Copyright (C) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "adapter.h"
#include "jtag.h"
#include "minidriver.h"
#include "interface.h"
#include "interfaces.h"
#include <transport/transport.h>
#include <jtag/drivers/jtag_usb_common.h>
/**
* @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);
}

61
src/jtag/adapter.h Normal file
View File

@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de>
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#ifndef OPENOCD_JTAG_ADAPTER_H
#define OPENOCD_JTAG_ADAPTER_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
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 "<dev_bus>-<port_path[0]>[.<port_path[1]>[...]]" */
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 */

View File

@ -20,6 +20,7 @@
#include "config.h"
#endif
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <transport/transport.h>
@ -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 <serial-number>");
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,

View File

@ -107,8 +107,6 @@ struct aice_port_param_s {
/** */
const char *device_desc;
/** */
const char *serial;
/** */
uint16_t vid;
/** */
uint16_t pid;

View File

@ -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);
}
/* */

View File

@ -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)

View File

@ -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;
}

View File

@ -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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
#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 */

View File

@ -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 \

View File

@ -20,6 +20,7 @@
#include "config.h"
#endif
#include <jtag/adapter.h>
#include <jtag/interface.h>
#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)

View File

@ -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));

View File

@ -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)

View File

@ -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;
}
}

View File

@ -40,6 +40,7 @@
#include <transport/transport.h>
#include "helper/replacements.h"
#include <jtag/adapter.h>
#include <jtag/swd.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
@ -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 <serial-number>");
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,

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -26,6 +26,7 @@
#endif
/* project specific includes */
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <helper/time_support.h>
@ -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 <serial>");
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,

View File

@ -69,7 +69,7 @@
#endif
/* project specific includes */
#include <jtag/drivers/jtag_usb_common.h>
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <transport/transport.h>
@ -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;

View File

@ -38,7 +38,7 @@
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <jtag/commands.h>
#include <jtag/drivers/jtag_usb_common.h>
#include <jtag/adapter.h>
#include <helper/replacements.h>
#include <target/cortex_m.h>
@ -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 = "<serial number>"
},
{
.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;

View File

@ -1,82 +0,0 @@
/*
* SPDX-License-Identifier: GPL-2.0+
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#include <helper/log.h>
#include <string.h>
#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;
}

View File

@ -1,17 +0,0 @@
/*
* SPDX-License-Identifier: GPL-2.0+
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#ifndef OPENOCD_JTAG_USB_COMMON_H
#define OPENOCD_JTAG_USB_COMMON_H
#include <helper/replacements.h>
#include <helper/types.h>
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 */

View File

@ -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;
}

View File

@ -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 <serial-number>");
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 = "<cmd>",
.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,

View File

@ -20,8 +20,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <helper/log.h>
#include <jtag/drivers/jtag_usb_common.h>
#include <jtag/adapter.h>
#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);

View File

@ -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);

View File

@ -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;
}

View File

@ -22,6 +22,7 @@
/* project specific includes */
#include <helper/binarybuffer.h>
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/hla/hla_layout.h>
#include <jtag/hla/hla_transport.h>
@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -23,6 +23,7 @@
#include "config.h"
#endif
#include <jtag/adapter.h>
#include <jtag/interface.h>
#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");

View File

@ -29,6 +29,7 @@
#include "windows.h"
#endif
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <helper/time_support.h>
#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,

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
/* project specific includes */
#include <helper/binarybuffer.h>
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/hla/hla_layout.h>
#include <jtag/hla/hla_transport.h>
@ -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");

View File

@ -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...");
}

View File

@ -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;

View File

@ -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,

View File

@ -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));

View File

@ -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,
}
};

View File

@ -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;
};

View File

@ -24,6 +24,7 @@
#include "config.h"
#endif
#include <jtag/adapter.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <jtag/swd.h>
@ -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 = "<pid>",
},
{
.name = "usb_serial",
.handler = &vsllink_handle_usb_serial_command,
.mode = COMMAND_CONFIG,
.help = "Set or disable check for USB serial",
.usage = "[<serial>]",
},
{
.name = "usb_bulkin",
.handler = &vsllink_handle_usb_bulkin_command,

View File

@ -20,15 +20,13 @@
#endif
#include <transport/transport.h>
#include <jtag/adapter.h>
#include <jtag/swd.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <jtag/tcl.h>
#include <libusb.h>
/* 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,

View File

@ -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 <serial-number>");
}
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,

View File

@ -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 */

View File

@ -23,6 +23,7 @@
#define OPENOCD_JTAG_HLA_HLA_LAYOUT_H
#include <target/armv7m_trace.h>
#include <target/arm_tpiu_swo.h>
/** */
struct hl_interface_s;

View File

@ -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 = {

View File

@ -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);

View File

@ -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

View File

@ -18,6 +18,7 @@
#ifndef OPENOCD_JTAG_SWD_H
#define OPENOCD_JTAG_SWD_H
#include <helper/log.h>
#include <target/arm_adi_v5.h>
/* 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 <target/arm_adi_v5.h> */
/**
* 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

View File

@ -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;

View File

@ -27,7 +27,7 @@
#endif
#include "openocd.h"
#include <jtag/driver.h>
#include <jtag/adapter.h>
#include <jtag/jtag.h>
#include <transport/transport.h>
#include <helper/util.h>
@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -53,8 +53,24 @@
#include <jtag/swd.h>
/* 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();
}

View File

@ -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);

View File

@ -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)

View File

@ -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)
{

View File

@ -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,

View File

@ -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, &reg32_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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -70,6 +70,7 @@
#include <helper/align.h>
#include <helper/time_support.h>
#include <jtag/adapter.h>
#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);

View File

@ -21,6 +21,7 @@
#include "mips64_pracc.h"
#include <helper/time_support.h>
#include <jtag/adapter.h>
#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);

View File

@ -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;

View File

@ -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);
/**

View File

@ -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

View File

@ -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

View File

@ -11,4 +11,4 @@ adapter driver jlink
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789
# adapter serial 123456789

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

74
tcl/target/gd32e23x.cfg Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More