Merge commit '9f23a1d7c1e27c556ef9787b9d3f263f5c1ecf24' into from_upstream

Conflicts:
	HACKING
	src/target/riscv/riscv-013.c

Change-Id: I43ccb143cae8daa39212d66a8824ae3ad2af6fef
This commit is contained in:
Tim Newsome 2023-10-27 09:00:59 -07:00
commit f02fe0960c
91 changed files with 3934 additions and 776 deletions

15
HACKING
View File

@ -103,6 +103,21 @@ patch:
Now every time OpenOCD is run, coverage info in your build directory is
updated. Running `gcov src/path/file.c` will generate a report.
- Sparse Static Analyzer
Using this tool allows identifying some bug in C code.
In the future, OpenOCD would use the sparse attribute 'bitwise' to
detect incorrect endianness assignments.
Example usage:
@code
mkdir build-sparse; cd build-sparse
../configure CC=cgcc CFLAGS="-Wsparse-all -Wno-declaration-after-statement \
-Wno-unknown-attribute -Wno-transparent-union -Wno-tautological-compare \
-Wno-vla -Wno-flexible-array-array -D__FLT_EVAL_METHOD__=0"
make
@endcode
Please consider performing these additional checks where appropriate
(especially Clang Static Analyzer for big portions of new code) and
mention the results (e.g. "Valgrind-clean, no new Clang analyzer

View File

@ -3322,15 +3322,32 @@ GPIO numbers >= 32 can't be used for performance reasons. GPIO configuration is
handled by the generic command @ref{adapter gpio, @command{adapter gpio}}.
See @file{interface/raspberrypi-native.cfg} for a sample config and
pinout.
@file{interface/raspberrypi-gpio-connector.cfg} for pinout.
@deffn {Config Command} {bcm2835gpio speed_coeffs} @var{speed_coeff} @var{speed_offset}
Set SPEED_COEFF and SPEED_OFFSET for delay calculations. If unspecified,
speed_coeff defaults to 113714, and speed_offset defaults to 28.
@end deffn
@deffn {Config Command} {bcm2835gpio peripheral_mem_dev} @var{device}
Set the device path for access to the memory mapped GPIO control registers.
Uses @file{/dev/gpiomem} by default, this is also the preferred option with
respect to system security.
If overridden to @file{/dev/mem}:
@itemize @minus
@item OpenOCD needs @code{cap_sys_rawio} or run as root to open @file{/dev/mem}.
Please be aware of security issues imposed by running OpenOCD with
elevated user rights and by @file{/dev/mem} itself.
@item correct @command{peripheral_base} must be configured.
@item GPIO 0-27 pads are set to the limited slew rate
and drive strength is reduced to 4 mA (2 mA on RPi 4).
@end itemize
@end deffn
@deffn {Config Command} {bcm2835gpio peripheral_base} @var{base}
Set the peripheral base register address to access GPIOs. For the RPi1, use
Set the peripheral base register address to access GPIOs.
Ignored if @file{/dev/gpiomem} is used. For the RPi1, use
0x20000000. For RPi2 and RPi3, use 0x3F000000. For RPi4, use 0xFE000000. A full
list can be found in the
@uref{https://www.raspberrypi.org/documentation/hardware/raspberrypi/peripheral_addresses.md, official guide}.
@ -7355,6 +7372,116 @@ Note: only Main and Work flash regions support Erase operation.
@end deffn
@end deffn
@deffn {Flash Driver} {qn908x}
The NXP QN908x microcontrollers feature a Cortex-M4F with integrated Bluetooth
LE 5 support and an internal flash of up to 512 KiB. These chips only support
the SWD interface.
The @var{qn908x} driver uses the internal "Flash Memory Controller" block via
SWD to erase, program and read the internal flash. This driver does not
support the ISP (In-System Programming) mode which is an alternate way to
program the flash via UART, SPI or USB.
The internal flash is 512 KiB in size in all released chips and it starts at
the address 0x01000000, although it can be mapped to address 0 and it is
aliased to other addresses. This driver only recognizes the bank starting at
address 0x01000000.
The internal bootloader stored in ROM is in charge of loading and verifying
the image from flash, or enter ISP mode. The programmed image must start at
the beginning of the flash and contain a valid header and a matching CRC32
checksum. Additionally, the image header contains a "Code Read Protection"
(CRP) word which indicates whether SWD access is enabled, as well as whether
ISP mode is enabled. Therefore, it is possible to program an image that
disables SWD and ISP making it impossible to program another image in the
future through these interfaces, or even debug the current image. While this is
a valid use case for production deployments where the chips are locked down, by
default this driver doesn't allow such images that disable the SWD interface.
To program such images see the @command{qn908x allow_brick} command.
Apart from the CRP field which is located in the image header, the last page
of the flash memory contains a "Flash lock and protect" descriptor which allows
to individually protect each 2 KiB page, as well as disabling SWD access to the
flash and RAM. If this access is disabled it is not possible to read, erase or
program individual pages from the SWD interface or even access the read-only
"Flash information page" with information about the bootloader version and
flash size. However when this protection is in place, it is still possible to
mass erase the whole chip and then program a new image, for which you can use
the @command{qn908x mass_erase}.
Example:
@example
flash bank $FLASHNAME qn908x 0x01000000 0 0 0 $TARGETNAME calc_checksum
@end example
Parameters:
@itemize
@item @option{calc_checksum} optional parameter to compute the required
checksum of the first bytes in the vector table.
@quotation Note
If the checksum in the header of your image is invalid and you don't provide the
@option{calc_checksum} option the boot ROM will not boot your image and it may
render the flash inaccessible. On the other hand, if you use this option to
compute the checksum keep in mind that @command{verify_image} will fail on
those four bytes of the checksum since those bytes in the flash will have the
updated checksum.
@end quotation
@end itemize
@deffn {Command} {qn908x allow_brick}
Allow the qn908x driver to program images with a "Code Read Protection" byte
that disables the SWD access. Programming such image will cause OpenOCD to
not be able to reach the target over SWD anymore after the new image is
programmed and its configuration takes effect, e.g. after a reboot. After
executing @command{qn908x allow_brick} these images will be allowed to be
programmed when writing to the flash.
@end deffn
@deffn {Command} {qn908x disable_wdog}
Disable the watchdog timer (WDT) by resetting its CTRL field. The WDT starts
enabled after a @command{reset halt} and it doesn't run while the target is
halted. However, the verification process in this driver uses the generic
Cortex-M verification process which executes a payload in RAM and thus
requires the watchdog to be disabled before running @command{verify_image}
after a reset halt or any other condition where the watchdog is running.
Note that this is not done automatically and you must run this command in
those scenarios.
@end deffn
@deffn {Command} {qn908x mass_erase}
Erases the complete flash using the mass_erase method. Mass erase is only
allowed if enabled in the Lock Status Register 8 (LOCK_STAT_8) which is read
from the last sector of the flash on boot. However, this mass_erase lock
protection can be bypassed and this command does so automatically.
In the same LOCK_STAT_8 the flash and RAM access from SWD can be disabled by
setting two bits in this register. After a mass_erase, all the bits of the
flash would be set, making it the default to restrict SWD access to the flash
and RAM regions. This new after erase LOCK_STAT_8 value only takes effect after
being read from flash on the next reboot for example. After a mass_erase the
LOCK_STAT_8 register is changed by the hardware to allow access to flash and
RAM regardless of the value on flash, but only right after a mass_erase and
until the next boot. Therefore it is possible to perform a mass_erase, program
a new image, verify it and then reboot to a valid image that's locked from the
SWD access.
The @command{qn908x mass_erase} command clears the bits that would be loaded
from the flash into LOCK_STAT_8 after erasing the whole chip to allow SWD
access for debugging or re-flashing an image without a mass_erase by default.
If the image being programmed also programs the last page of the flash with its
own settings, this mass_erase behavior will interfere with that write since a
new erase of at least the last page would need to be performed before writing
to it again. For this reason the optional @option{keep_lock} argument can be
used to leave the flash and RAM lock set. For development environments, the
default behavior is desired.
The mass erase locking mechanism is independent from the individual page
locking bits, so it is possible that you can't erase a given page that is
locked and you can't unprotect that page because the locking bits are also
locked, but can still mass erase the whole flash.
@end deffn
@end deffn
@deffn {Flash Driver} {rp2040}
Supports RP2040 "Raspberry Pi Pico" microcontroller.
RP2040 is a dual-core device with two CM0+ cores. Both cores share the same
@ -11487,6 +11614,40 @@ w/o OpenOCD command and keeps only the latest data window which fit into the buf
Data will be stored to specified destination.
@end deffn
@deffn {Command} {esp sysview} (start file://<outfile1> [file://<outfile2>] [<poll_period> [<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
Starts @uref{https://www.segger.com/products/development-tools/systemview/, SEGGER SystemView}
compatible tracing. Data will be stored to specified destination.
For dual-core chips traces from every core will be saved to separate files.
Resulting files can be open in "SEGGER SystemView" application.
@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
The meaning of the arguments is identical to @command{esp apptrace start}.
@end deffn
@deffn {Command} {esp sysview} (stop)
Stops SystremView compatible tracing started with above command.
@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
@end deffn
@deffn {Command} {esp sysview} (status)
Requests ongoing SystremView compatible tracing status.
@url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#openocd-systemview-tracing-command-options}
@end deffn
@deffn {Command} {esp sysview_mcore} (start file://<outfile> [<poll_period> [<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
This command is identical to @command{esp sysview start}, but uses Espressif multi-core extension to
@uref{https://www.segger.com/products/development-tools/systemview/, SEGGER SystemView} data format.
Data will be stored to specified destination. Tracing data from all cores are saved in the same file.
The meaning of the arguments is identical to @command{esp sysview start}.
@end deffn
@deffn {Command} {esp sysview_mcore} (stop)
Stops Espressif multi-core SystremView tracing started with above command.
@end deffn
@deffn {Command} {esp sysview_mcore} (status)
Requests ongoing Espressif multi-core SystremView tracing status.
@end deffn
@anchor{softwaredebugmessagesandtracing}
@section Software Debug Messages and Tracing
@cindex Linux-ARM DCC support

View File

@ -179,6 +179,7 @@ enum oob_formats {
NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */
};
extern struct nand_device *nand_devices;
struct nand_device *get_nand_device_by_num(int num);
@ -202,6 +203,8 @@ int nand_calculate_ecc(struct nand_device *nand,
const uint8_t *dat, uint8_t *ecc_code);
int nand_calculate_ecc_kw(struct nand_device *nand,
const uint8_t *dat, uint8_t *ecc_code);
int nand_correct_data(struct nand_device *nand, u_char *dat,
u_char *read_ecc, u_char *calc_ecc);
int nand_register_commands(struct command_context *cmd_ctx);

View File

@ -24,8 +24,6 @@
static int lpc32xx_reset(struct nand_device *nand);
static int lpc32xx_controller_ready(struct nand_device *nand, int timeout);
static int lpc32xx_tc_ready(struct nand_device *nand, int timeout);
extern int nand_correct_data(struct nand_device *nand, u_char *dat,
u_char *read_ecc, u_char *calc_ecc);
/* These are offset with the working area in IRAM when using DMA to
* read/write data to the SLC controller.

View File

@ -17,9 +17,6 @@
#include "fileio.h"
#include <target/target.h>
/* to be removed */
extern struct nand_device *nand_devices;
COMMAND_HANDLER(handle_nand_list_command)
{
struct nand_device *p;

View File

@ -54,6 +54,7 @@ NOR_DRIVERS = \
%D%/psoc4.c \
%D%/psoc5lp.c \
%D%/psoc6.c \
%D%/qn908x.c \
%D%/renesas_rpchf.c \
%D%/rp2040.c \
%D%/rsl10.c \

View File

@ -252,6 +252,19 @@ int get_flash_bank_by_num(unsigned int num, struct flash_bank **bank);
*/
COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
struct flash_bank **bank);
/**
* Retrieves @a bank from a command argument, reporting errors parsing
* the bank identifier or retrieving the specified bank. The bank
* may be identified by its bank number or by @c name.instance, where
* @a instance is driver-specific.
* @param name_index The index to the string in args containing the
* bank identifier.
* @param bank On output, contains a pointer to the bank or NULL.
* @param do_probe Does auto-probing when set, otherwise without probing.
* @returns ERROR_OK on success, or an error indicating the problem.
*/
COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index,
struct flash_bank **bank, bool do_probe);
/**
* Returns the flash bank like get_flash_bank_by_num(), without probing.
* @param num The flash bank number.

View File

@ -285,6 +285,7 @@ extern const struct flash_driver psoc5lp_eeprom_flash;
extern const struct flash_driver psoc5lp_flash;
extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash;
extern const struct flash_driver qn908x_flash;
extern const struct flash_driver renesas_rpchf_flash;
extern const struct flash_driver rp2040_flash;
extern const struct flash_driver rsl10_flash;

View File

@ -62,6 +62,7 @@ static const struct flash_driver * const flash_drivers[] = {
&psoc5lp_eeprom_flash,
&psoc5lp_nvl_flash,
&psoc6_flash,
&qn908x_flash,
&renesas_rpchf_flash,
&rp2040_flash,
&sh_qspi_flash,

View File

@ -41,7 +41,11 @@ FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
bank->sectors = NULL;
bank->driver_priv = info;
info->tap = NULL;
if (!bank->target->tap) {
LOG_ERROR("Target has no JTAG tap");
return ERROR_FAIL;
}
info->tap = bank->target->tap;
info->probed = false;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
@ -161,7 +165,12 @@ COMMAND_HANDLER(jtagspi_handle_set)
return ERROR_COMMAND_SYNTAX_ERROR;
}
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
/* calling flash_command_get_bank without probing because handle_set is used
to set device parameters if not autodetected. So probing would fail
anyhow.
*/
retval = CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, 0,
&bank, false);
if (ERROR_OK != retval)
return retval;
info = bank->driver_priv;
@ -292,52 +301,50 @@ COMMAND_HANDLER(jtagspi_handle_set)
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;
const unsigned int max = 20;
uint8_t cmd_byte, num_read, write_buffer[max], read_buffer[1 << CHAR_BIT];
LOG_DEBUG("%s", __func__);
if (CMD_ARGC < 3) {
command_print(CMD, "jtagspi: not enough arguments");
if (CMD_ARGC < 3)
return ERROR_COMMAND_SYNTAX_ERROR;
}
num_write = CMD_ARGC - 2;
uint8_t num_write = CMD_ARGC - 3;
if (num_write > max) {
LOG_ERROR("at most %d bytes may be send", max);
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "at most %d bytes may be send", max);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
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);
/* calling flash_command_get_bank without probing because we like to be
able to send commands before auto-probing occurred. For example sending
"release from power down" is needed before probing when flash is in
power down mode.
*/
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, 0,
&bank, false);
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);
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], num_read);
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[2], cmd_byte);
for (unsigned int i = 0; i < num_write; i++)
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[i + 3], write_buffer[i]);
/* process command */
retval = jtagspi_cmd(bank, cmd_byte, write_buffer, num_write, read_buffer, -num_read);
if (retval != ERROR_OK)
return retval;
command_print_sameline(CMD, "spi: %02" PRIx8, cmd_byte);
for (unsigned int i = 0; i < num_write; i++)
command_print_sameline(CMD, " %02" PRIx8, write_buffer[i]);
command_print_sameline(CMD, " ->");
for (unsigned int i = 0; i < num_read; i++)
command_print_sameline(CMD, " %02" PRIx8, read_buffer[i]);
return ERROR_OK;
}
@ -381,12 +388,6 @@ static int jtagspi_probe(struct flash_bank *bank)
}
info->probed = false;
if (!bank->target->tap) {
LOG_ERROR("Target has no JTAG tap");
return ERROR_FAIL;
}
info->tap = bank->target->tap;
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);
@ -518,7 +519,7 @@ static int jtagspi_bulk_erase(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
jtagspi_cmd(bank, info->dev.chip_erase_cmd, NULL, 0, NULL, 0);
retval = jtagspi_cmd(bank, info->dev.chip_erase_cmd, NULL, 0, NULL, 0);
if (retval != ERROR_OK)
return retval;

View File

@ -779,7 +779,7 @@ static int psoc4_probe(struct flash_bank *bank)
flash_size_in_kb = psoc4_info->user_bank_size / 1024;
}
char macros_txt[20] = "";
char macros_txt[22] = "";
if (num_macros > 1)
snprintf(macros_txt, sizeof(macros_txt), " in %" PRIu32 " macros", num_macros);

1197
src/flash/nor/qn908x.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -91,7 +91,7 @@ static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16
}
static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv,
uint16_t func_offset, uint32_t argdata[], unsigned int n_args, int timeout_ms)
uint16_t func_offset, uint32_t argdata[], unsigned int n_args, unsigned int timeout_ms)
{
char *regnames[4] = { "r0", "r1", "r2", "r3" };
@ -312,7 +312,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig
an optional larger "block" (size and command provided in args).
*/
int timeout_ms = 2000 * (last - first) + 1000;
unsigned int timeout_ms = 2000 * (last - first) + 1000;
err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_erase,
args, ARRAY_SIZE(args), timeout_ms);

View File

@ -230,11 +230,11 @@ static int stm32x_otp_enable(struct flash_bank *bank)
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
if (!stm32x_info->otp_unlocked) {
LOG_INFO("OTP memory bank #%u is is enabled for write commands.",
LOG_INFO("OTP memory bank #%u is enabled for write commands.",
bank->bank_number);
stm32x_info->otp_unlocked = true;
} else {
LOG_WARNING("OTP memory bank #%u is is already enabled for write commands.",
LOG_WARNING("OTP memory bank #%u is already enabled for write commands.",
bank->bank_number);
}
return ERROR_OK;
@ -659,8 +659,10 @@ static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
}
if (stm32x_is_otp(bank)) {
if (!set)
if (!set) {
LOG_ERROR("OTP protection can only be enabled");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
return stm32x_otp_protect(bank, first, last);
}

View File

@ -80,6 +80,12 @@
* http://www.st.com/resource/en/reference_manual/dm00451556.pdf
*/
/* STM32C0xxx series for reference.
*
* RM0490 (STM32C0x1)
* http://www.st.com/resource/en/reference_manual/dm00781702.pdf
*/
/* STM32G0xxx series for reference.
*
* RM0444 (STM32G0x1)
@ -263,7 +269,7 @@ struct stm32l4_wrp {
};
/* human readable list of families this drivers supports (sorted alphabetically) */
static const char *device_families = "STM32G0/G4/L4/L4+/L5/U5/WB/WL";
static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U5/WB/WL";
static const struct stm32l4_rev stm32l47_l48xx_revs[] = {
{ 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" }
@ -273,6 +279,15 @@ static const struct stm32l4_rev stm32l43_l44xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
};
static const struct stm32l4_rev stm32c01xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" },
};
static const struct stm32l4_rev stm32c03xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" },
};
static const struct stm32l4_rev stm32g05_g06xx_revs[] = {
{ 0x1000, "A" },
};
@ -371,6 +386,30 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_base = 0x1FFF7000,
.otp_size = 1024,
},
{
.id = DEVID_STM32C01XX,
.revs = stm32c01xx_revs,
.num_revs = ARRAY_SIZE(stm32c01xx_revs),
.device_str = "STM32C01xx",
.max_flash_size_kb = 32,
.flags = F_NONE,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x1FFF75A0,
.otp_base = 0x1FFF7000,
.otp_size = 1024,
},
{
.id = DEVID_STM32C03XX,
.revs = stm32c03xx_revs,
.num_revs = ARRAY_SIZE(stm32c03xx_revs),
.device_str = "STM32C03xx",
.max_flash_size_kb = 32,
.flags = F_NONE,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x1FFF75A0,
.otp_base = 0x1FFF7000,
.otp_size = 1024,
},
{
.id = DEVID_STM32G05_G06XX,
.revs = stm32g05_g06xx_revs,
@ -1855,6 +1894,8 @@ static int stm32l4_probe(struct flash_bank *bank)
}
break;
case DEVID_STM32L43_L44XX:
case DEVID_STM32C01XX:
case DEVID_STM32C03XX:
case DEVID_STM32G05_G06XX:
case DEVID_STM32G07_G08XX:
case DEVID_STM32L45_L46XX:

View File

@ -87,6 +87,8 @@
/* Supported device IDs */
#define DEVID_STM32L47_L48XX 0x415
#define DEVID_STM32L43_L44XX 0x435
#define DEVID_STM32C01XX 0x443
#define DEVID_STM32C03XX 0x453
#define DEVID_STM32G05_G06XX 0x456
#define DEVID_STM32G07_G08XX 0x460
#define DEVID_STM32L49_L4AXX 0x461

View File

@ -19,7 +19,7 @@
* Implements Tcl commands used to access NOR flash facilities.
*/
static COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index,
COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index,
struct flash_bank **bank, bool do_probe)
{
const char *name = CMD_ARGV[name_index];
@ -51,7 +51,7 @@ static COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index,
COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
struct flash_bank **bank)
{
return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe,
return CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional,
name_index, bank, true);
}
@ -157,7 +157,7 @@ COMMAND_HANDLER(handle_flash_probe_command)
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
retval = CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, 0, &p, false);
retval = CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, 0, &p, false);
if (retval != ERROR_OK)
return retval;

View File

@ -8,6 +8,7 @@
#include <config.h>
#endif
#include <helper/log.h>
#include "hello.h"
COMMAND_HANDLER(handle_foo_command)
{

View File

@ -19,6 +19,7 @@
#include "command.h"
#include "replacements.h"
#include "time_support.h"
#include <server/gdb_server.h>
#include <server/server.h>
#include <stdarg.h>
@ -399,9 +400,7 @@ char *alloc_printf(const char *format, ...)
static void gdb_timeout_warning(int64_t delta_time)
{
extern int gdb_actual_connections;
if (gdb_actual_connections)
if (gdb_get_actual_connections())
LOG_WARNING("keep_alive() was not invoked in the "
"%d ms timelimit. GDB alive packet not "
"sent! (%" PRId64 " ms). Workaround: increase "

View File

@ -10,10 +10,18 @@
* Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk *
***************************************************************************/
/* DANGER!!!! These must be defined *BEFORE* replacements.h and the malloc() macro!!!! */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* define IN_REPLACEMENTS_C before include replacements.h */
#define IN_REPLACEMENTS_C
#include "replacements.h"
#include <stdlib.h>
#include <string.h>
/*
* clear_malloc
*
@ -41,10 +49,6 @@ void *fill_malloc(size_t size)
return t;
}
#define IN_REPLACEMENTS_C
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif

View File

@ -66,12 +66,10 @@ int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
#ifndef IN_REPLACEMENTS_C
/**** clear_malloc & fill_malloc ****/
void *clear_malloc(size_t size);
void *fill_malloc(size_t size);
#endif
#ifndef IN_REPLACEMENTS_C
/*
* Now you have 3 ways for the malloc function:
*
@ -100,6 +98,7 @@ void *fill_malloc(size_t size);
/* #define malloc(_a) clear_malloc(_a)
* #define malloc(_a) fill_malloc(_a) */
#endif /* IN_REPLACEMENTS_C */
/* GNU extensions to the C library that may be missing on some systems */
#ifndef HAVE_STRNDUP

View File

@ -177,44 +177,44 @@ static inline void h_u64_to_be(uint8_t *buf, uint64_t val)
static inline void h_u32_to_le(uint8_t *buf, uint32_t val)
{
buf[3] = (uint8_t) (val >> 24);
buf[2] = (uint8_t) (val >> 16);
buf[1] = (uint8_t) (val >> 8);
buf[0] = (uint8_t) (val >> 0);
buf[3] = (val >> 24) & 0xff;
buf[2] = (val >> 16) & 0xff;
buf[1] = (val >> 8) & 0xff;
buf[0] = (val >> 0) & 0xff;
}
static inline void h_u32_to_be(uint8_t *buf, uint32_t val)
{
buf[0] = (uint8_t) (val >> 24);
buf[1] = (uint8_t) (val >> 16);
buf[2] = (uint8_t) (val >> 8);
buf[3] = (uint8_t) (val >> 0);
buf[0] = (val >> 24) & 0xff;
buf[1] = (val >> 16) & 0xff;
buf[2] = (val >> 8) & 0xff;
buf[3] = (val >> 0) & 0xff;
}
static inline void h_u24_to_le(uint8_t *buf, unsigned int val)
{
buf[2] = (uint8_t) (val >> 16);
buf[1] = (uint8_t) (val >> 8);
buf[0] = (uint8_t) (val >> 0);
buf[2] = (val >> 16) & 0xff;
buf[1] = (val >> 8) & 0xff;
buf[0] = (val >> 0) & 0xff;
}
static inline void h_u24_to_be(uint8_t *buf, unsigned int val)
{
buf[0] = (uint8_t) (val >> 16);
buf[1] = (uint8_t) (val >> 8);
buf[2] = (uint8_t) (val >> 0);
buf[0] = (val >> 16) & 0xff;
buf[1] = (val >> 8) & 0xff;
buf[2] = (val >> 0) & 0xff;
}
static inline void h_u16_to_le(uint8_t *buf, uint16_t val)
{
buf[1] = (uint8_t) (val >> 8);
buf[0] = (uint8_t) (val >> 0);
buf[1] = (val >> 8) & 0xff;
buf[0] = (val >> 0) & 0xff;
}
static inline void h_u16_to_be(uint8_t *buf, uint16_t val)
{
buf[0] = (uint8_t) (val >> 8);
buf[1] = (uint8_t) (val >> 0);
buf[0] = (val >> 8) & 0xff;
buf[1] = (val >> 0) & 0xff;
}
/**

View File

@ -19,7 +19,8 @@
#include <sys/mman.h>
static uint32_t bcm2835_peri_base = 0x20000000;
static char *bcm2835_peri_mem_dev;
static off_t bcm2835_peri_base = 0x20000000;
#define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
#define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
@ -57,6 +58,14 @@ static struct initial_gpio_state {
} initial_gpio_state[ADAPTER_GPIO_IDX_NUM];
static uint32_t initial_drive_strength_etc;
static inline const char *bcm2835_get_mem_dev(void)
{
if (bcm2835_peri_mem_dev)
return bcm2835_peri_mem_dev;
return "/dev/gpiomem";
}
static inline void bcm2835_gpio_synchronize(void)
{
/* Ensure that previous writes to GPIO registers are flushed out of
@ -300,13 +309,29 @@ COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
return ERROR_OK;
}
COMMAND_HANDLER(bcm2835gpio_handle_peripheral_mem_dev)
{
if (CMD_ARGC == 1) {
free(bcm2835_peri_mem_dev);
bcm2835_peri_mem_dev = strdup(CMD_ARGV[0]);
}
command_print(CMD, "BCM2835 GPIO: peripheral_mem_dev = %s",
bcm2835_get_mem_dev());
return ERROR_OK;
}
COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bcm2835_peri_base);
uint64_t tmp_base;
if (CMD_ARGC == 1) {
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], tmp_base);
bcm2835_peri_base = (off_t)tmp_base;
}
command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08x",
bcm2835_peri_base);
tmp_base = bcm2835_peri_base;
command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08" PRIu64,
tmp_base);
return ERROR_OK;
}
@ -318,11 +343,18 @@ static const struct command_registration bcm2835gpio_subcommand_handlers[] = {
.help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
.usage = "[SPEED_COEFF SPEED_OFFSET]",
},
{
.name = "peripheral_mem_dev",
.handler = &bcm2835gpio_handle_peripheral_mem_dev,
.mode = COMMAND_CONFIG,
.help = "device to map memory mapped GPIOs from.",
.usage = "[device]",
},
{
.name = "peripheral_base",
.handler = &bcm2835gpio_handle_peripheral_base,
.mode = COMMAND_CONFIG,
.help = "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
.help = "peripheral base to access GPIOs, not needed with /dev/gpiomem.",
.usage = "[base]",
},
@ -409,13 +441,16 @@ static int bcm2835gpio_init(void)
return ERROR_JTAG_INIT_FAILED;
}
dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
bool is_gpiomem = strcmp(bcm2835_get_mem_dev(), "/dev/gpiomem") == 0;
bool pad_mapping_possible = !is_gpiomem;
dev_mem_fd = open(bcm2835_get_mem_dev(), O_RDWR | O_SYNC);
if (dev_mem_fd < 0) {
LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
}
if (dev_mem_fd < 0) {
LOG_ERROR("open: %s", strerror(errno));
LOG_ERROR("open %s: %s", bcm2835_get_mem_dev(), strerror(errno));
/* TODO: add /dev/mem specific doc and refer to it
* if (!is_gpiomem && (errno == EACCES || errno == EPERM))
* LOG_INFO("Consult the user's guide chapter 4.? how to set permissions and capabilities");
*/
return ERROR_JTAG_INIT_FAILED;
}
@ -428,21 +463,28 @@ static int bcm2835gpio_init(void)
return ERROR_JTAG_INIT_FAILED;
}
pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
/* TODO: move pads config to a separate utility */
if (pad_mapping_possible) {
pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27);
if (pads_base == MAP_FAILED) {
LOG_ERROR("mmap: %s", strerror(errno));
bcm2835gpio_munmap();
close(dev_mem_fd);
return ERROR_JTAG_INIT_FAILED;
if (pads_base == MAP_FAILED) {
LOG_ERROR("mmap pads: %s", strerror(errno));
LOG_WARNING("Continuing with unchanged GPIO pad settings (drive strength and slew rate)");
}
} else {
pads_base = MAP_FAILED;
}
close(dev_mem_fd);
/* set 4mA drive strength, slew rate limited, hysteresis on */
initial_drive_strength_etc = pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] & 0x1f;
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
if (pads_base != MAP_FAILED) {
/* set 4mA drive strength, slew rate limited, hysteresis on */
initial_drive_strength_etc = pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] & 0x1f;
LOG_INFO("initial pads conf %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]);
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]);
}
/* Configure JTAG/SWD signals. Default directions and initial states are handled
* by adapter.c and "adapter gpio" command.
@ -513,9 +555,12 @@ static int bcm2835gpio_quit(void)
restore_gpio(ADAPTER_GPIO_IDX_SRST);
restore_gpio(ADAPTER_GPIO_IDX_LED);
/* Restore drive strength. MSB is password ("5A") */
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc;
if (pads_base != MAP_FAILED) {
/* Restore drive strength. MSB is password ("5A") */
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc;
}
bcm2835gpio_munmap();
free(bcm2835_peri_mem_dev);
return ERROR_OK;
}

View File

@ -53,7 +53,7 @@
#include "helper/log.h"
#include "helper/list.h"
#define VD_VERSION 44
#define VD_VERSION 46
#define VD_BUFFER_LEN 4024
#define VD_CHEADER_LEN 24
#define VD_SHEADER_LEN 16
@ -272,7 +272,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port)
LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr, vdebug_socket_error());
rc = VD_ERR_SOC_ADDR;
} else {
buf_set_u32((uint8_t *)ainfo->ai_addr->sa_data, 0, 16, htons(port));
h_u16_to_be((uint8_t *)ainfo->ai_addr->sa_data, port);
if (connect(hsock, ainfo->ai_addr, sizeof(struct sockaddr)) < 0) {
LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr, port, vdebug_socket_error());
rc = VD_ERR_SOC_CONN;
@ -942,10 +942,10 @@ static int vdebug_jtag_tlr(tap_state_t state, uint8_t f_flush)
{
int rc = ERROR_OK;
uint8_t cur = tap_get_state();
tap_state_t cur = tap_get_state();
uint8_t tms_pre = tap_get_tms_path(cur, state);
uint8_t num_pre = tap_get_tms_path_len(cur, state);
LOG_INFO("tlr from %" PRIx8 " to %" PRIx8, cur, state);
LOG_INFO("tlr from %x to %x", cur, state);
if (cur != state) {
rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, 0, NULL, 0, 0, NULL, f_flush);
tap_set_state(state);
@ -958,7 +958,7 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush)
{
int rc = ERROR_OK;
uint8_t cur = tap_get_state();
tap_state_t cur = tap_get_state();
uint8_t state = cmd->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT;
uint8_t tms_pre = tap_get_tms_path(cur, state);
uint8_t num_pre = tap_get_tms_path_len(cur, state);
@ -988,7 +988,7 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush)
static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush)
{
uint8_t cur = tap_get_state();
tap_state_t cur = tap_get_state();
uint8_t tms_pre = tap_get_tms_path(cur, state);
uint8_t num_pre = tap_get_tms_path_len(cur, state);
LOG_DEBUG("idle len:%d state cur:%x end:%x", cycles, cur, state);
@ -1125,7 +1125,7 @@ static int vdebug_dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
static int vdebug_dap_run(struct adiv5_dap *dap)
{
if (pbuf->waddr)
if (le_to_h_u16(pbuf->waddr))
return vdebug_run_reg_queue(vdc.hsocket, pbuf, le_to_h_u16(pbuf->waddr));
return ERROR_OK;

View File

@ -37,8 +37,15 @@ static const struct command_registration hl_swd_transport_subcommand_handlers[]
{
.name = "newdap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_jtag_newtap,
.handler = handle_jtag_newtap,
.help = "declare a new SWD DAP",
.usage = "basename dap_type ['-irlen' count] "
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
};
@ -58,11 +65,16 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[]
{
.name = "newtap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_jtag_newtap,
.handler = handle_jtag_newtap,
.help = "Create a new TAP instance named basename.tap_type, "
"and appends it to the scan chain.",
.usage = "basename tap_type '-irlen' count "
"['-expected_id' number]",
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-mask' number]",
},
{
.name = "init",
@ -85,12 +97,18 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[]
{
.name = "tapisenabled",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Returns a Tcl boolean (0/1) indicating whether "
"the TAP is enabled (1) or not (0).",
.usage = "tap_name",
},
{
.name = "tapenable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Try to enable the specified TAP using the "
"'tap-enable' TAP event.",
.usage = "tap_name",
},
{
.name = "tapdisable",

View File

@ -372,7 +372,7 @@ tap_state_t tap_state_by_name(const char *name)
tap_state_name(a), tap_state_name(b), astr, bstr)
tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf,
unsigned tap_bits, tap_state_t next_state)
unsigned int tap_bits, tap_state_t next_state)
{
const uint8_t *tms_buffer;
const uint8_t *tdi_buffer;

View File

@ -147,6 +147,8 @@ void tap_use_new_tms_table(bool use_new);
/** @returns True if new TMS table is active; false otherwise. */
bool tap_uses_new_tms_table(void);
tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf,
unsigned int tap_len, tap_state_t start_tap_state);
/**
* @brief Prints verbose TAP state transitions for the given TMS/TDI buffers.
@ -159,10 +161,6 @@ bool tap_uses_new_tms_table(void);
static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state)
{
/* Private declaration */
tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf,
unsigned tap_len, tap_state_t start_tap_state);
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO))
return jtag_debug_state_machine_(tms_buf, tdi_buf, tap_len, start_tap_state);
else
@ -364,4 +362,42 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
unsigned int traceclkin_freq, uint16_t *prescaler);
int adapter_poll_trace(uint8_t *buf, size_t *size);
extern struct adapter_driver am335xgpio_adapter_driver;
extern struct adapter_driver amt_jtagaccel_adapter_driver;
extern struct adapter_driver armjtagew_adapter_driver;
extern struct adapter_driver at91rm9200_adapter_driver;
extern struct adapter_driver bcm2835gpio_adapter_driver;
extern struct adapter_driver buspirate_adapter_driver;
extern struct adapter_driver cmsis_dap_adapter_driver;
extern struct adapter_driver dummy_adapter_driver;
extern struct adapter_driver ep93xx_adapter_driver;
extern struct adapter_driver esp_usb_adapter_driver;
extern struct adapter_driver ft232r_adapter_driver;
extern struct adapter_driver ftdi_adapter_driver;
extern struct adapter_driver gw16012_adapter_driver;
extern struct adapter_driver hl_adapter_driver;
extern struct adapter_driver imx_gpio_adapter_driver;
extern struct adapter_driver jlink_adapter_driver;
extern struct adapter_driver jtag_dpi_adapter_driver;
extern struct adapter_driver jtag_vpi_adapter_driver;
extern struct adapter_driver kitprog_adapter_driver;
extern struct adapter_driver linuxgpiod_adapter_driver;
extern struct adapter_driver opendous_adapter_driver;
extern struct adapter_driver openjtag_adapter_driver;
extern struct adapter_driver osbdm_adapter_driver;
extern struct adapter_driver parport_adapter_driver;
extern struct adapter_driver presto_adapter_driver;
extern struct adapter_driver remote_bitbang_adapter_driver;
extern struct adapter_driver rlink_adapter_driver;
extern struct adapter_driver rshim_dap_adapter_driver;
extern struct adapter_driver stlink_dap_adapter_driver;
extern struct adapter_driver sysfsgpio_adapter_driver;
extern struct adapter_driver ulink_adapter_driver;
extern struct adapter_driver usb_blaster_adapter_driver;
extern struct adapter_driver usbprog_adapter_driver;
extern struct adapter_driver vdebug_adapter_driver;
extern struct adapter_driver vsllink_adapter_driver;
extern struct adapter_driver xds110_adapter_driver;
extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
#endif /* OPENOCD_JTAG_INTERFACE_H */

View File

@ -24,125 +24,13 @@
#include "interfaces.h"
/** @file
* This file includes declarations for all built-in jtag interfaces,
* which are then listed in the adapter_drivers array.
* This file collects all the built-in JTAG interfaces in the adapter_drivers
* array.
*
* Dynamic loading can be implemented be searching for shared libraries
* that contain an adapter_driver structure that can added to this list.
*/
#if BUILD_PARPORT == 1
extern struct adapter_driver parport_adapter_driver;
#endif
#if BUILD_DUMMY == 1
extern struct adapter_driver dummy_adapter_driver;
#endif
#if BUILD_FTDI == 1
extern struct adapter_driver ftdi_adapter_driver;
#endif
#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1
extern struct adapter_driver usb_blaster_adapter_driver;
#endif
#if BUILD_ESP_USB_JTAG == 1
extern struct adapter_driver esp_usb_adapter_driver;
#endif
#if BUILD_JTAG_VPI == 1
extern struct adapter_driver jtag_vpi_adapter_driver;
#endif
#if BUILD_VDEBUG == 1
extern struct adapter_driver vdebug_adapter_driver;
#endif
#if BUILD_JTAG_DPI == 1
extern struct adapter_driver jtag_dpi_adapter_driver;
#endif
#if BUILD_FT232R == 1
extern struct adapter_driver ft232r_adapter_driver;
#endif
#if BUILD_AMTJTAGACCEL == 1
extern struct adapter_driver amt_jtagaccel_adapter_driver;
#endif
#if BUILD_EP93XX == 1
extern struct adapter_driver ep93xx_adapter_driver;
#endif
#if BUILD_AT91RM9200 == 1
extern struct adapter_driver at91rm9200_adapter_driver;
#endif
#if BUILD_GW16012 == 1
extern struct adapter_driver gw16012_adapter_driver;
#endif
#if BUILD_PRESTO
extern struct adapter_driver presto_adapter_driver;
#endif
#if BUILD_USBPROG == 1
extern struct adapter_driver usbprog_adapter_driver;
#endif
#if BUILD_OPENJTAG == 1
extern struct adapter_driver openjtag_adapter_driver;
#endif
#if BUILD_JLINK == 1
extern struct adapter_driver jlink_adapter_driver;
#endif
#if BUILD_VSLLINK == 1
extern struct adapter_driver vsllink_adapter_driver;
#endif
#if BUILD_RLINK == 1
extern struct adapter_driver rlink_adapter_driver;
#endif
#if BUILD_ULINK == 1
extern struct adapter_driver ulink_adapter_driver;
#endif
#if BUILD_ARMJTAGEW == 1
extern struct adapter_driver armjtagew_adapter_driver;
#endif
#if BUILD_BUSPIRATE == 1
extern struct adapter_driver buspirate_adapter_driver;
#endif
#if BUILD_REMOTE_BITBANG == 1
extern struct adapter_driver remote_bitbang_adapter_driver;
#endif
#if BUILD_HLADAPTER == 1
extern struct adapter_driver hl_adapter_driver;
#endif
#if BUILD_OSBDM == 1
extern struct adapter_driver osbdm_adapter_driver;
#endif
#if BUILD_OPENDOUS == 1
extern struct adapter_driver opendous_adapter_driver;
#endif
#if BUILD_SYSFSGPIO == 1
extern struct adapter_driver sysfsgpio_adapter_driver;
#endif
#if BUILD_LINUXGPIOD == 1
extern struct adapter_driver linuxgpiod_adapter_driver;
#endif
#if BUILD_XLNX_PCIE_XVC == 1
extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
#endif
#if BUILD_BCM2835GPIO == 1
extern struct adapter_driver bcm2835gpio_adapter_driver;
#endif
#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1
extern struct adapter_driver cmsis_dap_adapter_driver;
#endif
#if BUILD_KITPROG == 1
extern struct adapter_driver kitprog_adapter_driver;
#endif
#if BUILD_IMX_GPIO == 1
extern struct adapter_driver imx_gpio_adapter_driver;
#endif
#if BUILD_XDS110 == 1
extern struct adapter_driver xds110_adapter_driver;
#endif
#if BUILD_HLADAPTER_STLINK == 1
extern struct adapter_driver stlink_dap_adapter_driver;
#endif
#if BUILD_RSHIM == 1
extern struct adapter_driver rshim_dap_adapter_driver;
#endif
#if BUILD_AM335XGPIO == 1
extern struct adapter_driver am335xgpio_adapter_driver;
#endif
/**
* The list of built-in JTAG interfaces, containing entries for those
* drivers that were enabled by the @c configure script.

View File

@ -12,6 +12,7 @@
#define OPENOCD_JTAG_JTAG_H
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <helper/log.h>
#include <helper/replacements.h>
@ -602,6 +603,6 @@ void jtag_poll_unmask(bool saved);
#include <jtag/minidriver.h>
int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
__COMMAND_HANDLER(handle_jtag_newtap);
#endif /* OPENOCD_JTAG_JTAG_H */

View File

@ -31,6 +31,8 @@
#include <strings.h>
#endif
#include <helper/command.h>
#include <helper/nvp.h>
#include <helper/time_support.h>
#include "transport/transport.h"
@ -376,39 +378,6 @@ static int jtag_tap_configure_cmd(struct jim_getopt_info *goi, struct jtag_tap *
return JIM_OK;
}
static int is_bad_irval(int ir_length, jim_wide w)
{
jim_wide v = 1;
v <<= ir_length;
v -= 1;
v = ~v;
return (w & v) != 0;
}
static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
struct jtag_tap *tap)
{
jim_wide w;
int e = jim_getopt_wide(goi, &w);
if (e != JIM_OK) {
Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name);
return e;
}
uint32_t *p = realloc(tap->expected_ids,
(tap->expected_ids_cnt + 1) * sizeof(uint32_t));
if (!p) {
Jim_SetResultFormatted(goi->interp, "no memory");
return JIM_ERR;
}
tap->expected_ids = p;
tap->expected_ids[tap->expected_ids_cnt++] = w;
return JIM_OK;
}
#define NTAP_OPT_IRLEN 0
#define NTAP_OPT_IRMASK 1
#define NTAP_OPT_IRCAPTURE 2
@ -418,166 +387,155 @@ static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi
#define NTAP_OPT_VERSION 6
#define NTAP_OPT_BYPASS 7
static int jim_newtap_ir_param(struct jim_nvp *n, struct jim_getopt_info *goi,
struct jtag_tap *tap)
static const struct nvp jtag_newtap_opts[] = {
{ .name = "-irlen", .value = NTAP_OPT_IRLEN },
{ .name = "-irmask", .value = NTAP_OPT_IRMASK },
{ .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
{ .name = "-enable", .value = NTAP_OPT_ENABLED },
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
{ .name = NULL, .value = -1 },
};
static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap)
{
jim_wide w;
int e = jim_getopt_wide(goi, &w);
if (e != JIM_OK) {
Jim_SetResultFormatted(goi->interp,
"option: %s bad parameter", n->name);
return e;
/* we expect CHIP + TAP + OPTIONS */
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
tap->chip = strdup(CMD_ARGV[0]);
tap->tapname = strdup(CMD_ARGV[1]);
tap->dotted_name = alloc_printf("%s.%s", CMD_ARGV[0], CMD_ARGV[1]);
if (!tap->chip || !tap->tapname || !tap->dotted_name) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
switch (n->value) {
case NTAP_OPT_IRLEN:
if (w > (jim_wide) (8 * sizeof(tap->ir_capture_value))) {
LOG_WARNING("%s: huge IR length %d",
tap->dotted_name, (int) w);
}
tap->ir_length = w;
break;
case NTAP_OPT_IRMASK:
if (is_bad_irval(tap->ir_length, w)) {
LOG_ERROR("%s: IR mask %x too big",
tap->dotted_name,
(int) w);
return JIM_ERR;
}
if ((w & 3) != 3)
LOG_WARNING("%s: nonstandard IR mask", tap->dotted_name);
tap->ir_capture_mask = w;
break;
case NTAP_OPT_IRCAPTURE:
if (is_bad_irval(tap->ir_length, w)) {
LOG_ERROR("%s: IR capture %x too big",
tap->dotted_name, (int) w);
return JIM_ERR;
}
if ((w & 3) != 1)
LOG_WARNING("%s: nonstandard IR value",
tap->dotted_name);
tap->ir_capture_value = w;
break;
default:
return JIM_ERR;
}
return JIM_OK;
}
static int jim_newtap_cmd(struct jim_getopt_info *goi)
{
struct jtag_tap *tap;
int x;
int e;
struct jim_nvp *n;
char *cp;
const struct jim_nvp opts[] = {
{ .name = "-irlen", .value = NTAP_OPT_IRLEN },
{ .name = "-irmask", .value = NTAP_OPT_IRMASK },
{ .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
{ .name = "-enable", .value = NTAP_OPT_ENABLED },
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
{ .name = NULL, .value = -1 },
};
tap = calloc(1, sizeof(struct jtag_tap));
if (!tap) {
Jim_SetResultFormatted(goi->interp, "no memory");
return JIM_ERR;
}
/*
* we expect CHIP + TAP + OPTIONS
* */
if (goi->argc < 3) {
Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ....");
free(tap);
return JIM_ERR;
}
const char *tmp;
jim_getopt_string(goi, &tmp, NULL);
tap->chip = strdup(tmp);
jim_getopt_string(goi, &tmp, NULL);
tap->tapname = strdup(tmp);
/* name + dot + name + null */
x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
cp = malloc(x);
sprintf(cp, "%s.%s", tap->chip, tap->tapname);
tap->dotted_name = cp;
CMD_ARGC -= 2;
CMD_ARGV += 2;
LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
tap->chip, tap->tapname, tap->dotted_name, goi->argc);
tap->chip, tap->tapname, tap->dotted_name, CMD_ARGC);
/* IEEE specifies that the two LSBs of an IR scan are 01, so make
/*
* IEEE specifies that the two LSBs of an IR scan are 01, so make
* that the default. The "-ircapture" and "-irmask" options are only
* needed to cope with nonstandard TAPs, or to specify more bits.
*/
tap->ir_capture_mask = 0x03;
tap->ir_capture_value = 0x01;
while (goi->argc) {
e = jim_getopt_nvp(goi, opts, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(goi, opts, 0);
free(cp);
free(tap);
return e;
}
LOG_DEBUG("Processing option: %s", n->name);
while (CMD_ARGC) {
const struct nvp *n = nvp_name2value(jtag_newtap_opts, CMD_ARGV[0]);
CMD_ARGC--;
CMD_ARGV++;
switch (n->value) {
case NTAP_OPT_ENABLED:
tap->disabled_after_reset = false;
break;
case NTAP_OPT_DISABLED:
tap->disabled_after_reset = true;
break;
case NTAP_OPT_EXPECTED_ID:
e = jim_newtap_expected_id(n, goi, tap);
if (e != JIM_OK) {
free(cp);
free(tap);
return e;
}
break;
case NTAP_OPT_IRLEN:
case NTAP_OPT_IRMASK:
case NTAP_OPT_IRCAPTURE:
e = jim_newtap_ir_param(n, goi, tap);
if (e != JIM_OK) {
free(cp);
free(tap);
return e;
}
break;
case NTAP_OPT_VERSION:
tap->ignore_version = true;
break;
case NTAP_OPT_BYPASS:
tap->ignore_bypass = true;
break;
} /* switch (n->value) */
} /* while (goi->argc) */
case NTAP_OPT_ENABLED:
tap->disabled_after_reset = false;
break;
case NTAP_OPT_DISABLED:
tap->disabled_after_reset = true;
break;
case NTAP_OPT_EXPECTED_ID:
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;
tap->expected_ids = realloc(tap->expected_ids,
(tap->expected_ids_cnt + 1) * sizeof(uint32_t));
if (!tap->expected_ids) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
uint32_t id;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], id);
CMD_ARGC--;
CMD_ARGV++;
tap->expected_ids[tap->expected_ids_cnt++] = id;
break;
case NTAP_OPT_IRLEN:
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tap->ir_length);
CMD_ARGC--;
CMD_ARGV++;
if (tap->ir_length > (int)(8 * sizeof(tap->ir_capture_value)))
LOG_WARNING("%s: huge IR length %d", tap->dotted_name, tap->ir_length);
break;
case NTAP_OPT_IRMASK:
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], tap->ir_capture_mask);
CMD_ARGC--;
CMD_ARGV++;
if ((tap->ir_capture_mask & 3) != 3)
LOG_WARNING("%s: nonstandard IR mask", tap->dotted_name);
break;
case NTAP_OPT_IRCAPTURE:
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], tap->ir_capture_value);
CMD_ARGC--;
CMD_ARGV++;
if ((tap->ir_capture_value & 3) != 1)
LOG_WARNING("%s: nonstandard IR value", tap->dotted_name);
break;
case NTAP_OPT_VERSION:
tap->ignore_version = true;
break;
case NTAP_OPT_BYPASS:
tap->ignore_bypass = true;
break;
default:
nvp_unknown_command_print(CMD, jtag_newtap_opts, NULL, CMD_ARGV[-1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
/* default is enabled-after-reset */
tap->enabled = !tap->disabled_after_reset;
/* Did all the required option bits get cleared? */
if (!transport_is_jtag() || tap->ir_length != 0) {
jtag_tap_init(tap);
return JIM_OK;
if (transport_is_jtag() && tap->ir_length == 0) {
command_print(CMD, "newtap: %s missing IR length", tap->dotted_name);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
Jim_SetResultFormatted(goi->interp,
"newtap: %s missing IR length",
tap->dotted_name);
jtag_tap_free(tap);
return JIM_ERR;
return ERROR_OK;
}
__COMMAND_HANDLER(handle_jtag_newtap)
{
struct jtag_tap *tap = calloc(1, sizeof(struct jtag_tap));
if (!tap) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
int retval = CALL_COMMAND_HANDLER(handle_jtag_newtap_args, tap);
if (retval != ERROR_OK) {
free(tap->chip);
free(tap->tapname);
free(tap->dotted_name);
free(tap->expected_ids);
free(tap);
return retval;
}
jtag_tap_init(tap);
return ERROR_OK;
}
static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
@ -643,17 +601,10 @@ COMMAND_HANDLER(handle_jtag_arp_init_reset)
return ERROR_OK;
}
int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc-1, argv + 1);
return jim_newtap_cmd(&goi);
}
static bool jtag_tap_enable(struct jtag_tap *t)
{
if (t->enabled)
return false;
return true;
jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
if (!t->enabled)
return false;
@ -668,7 +619,7 @@ static bool jtag_tap_enable(struct jtag_tap *t)
static bool jtag_tap_disable(struct jtag_tap *t)
{
if (!t->enabled)
return false;
return true;
jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
if (t->enabled)
return false;
@ -681,42 +632,36 @@ static bool jtag_tap_disable(struct jtag_tap *t)
return true;
}
int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
__COMMAND_HANDLER(handle_jtag_tap_enabler)
{
struct command *c = jim_to_command(interp);
const char *cmd_name = c->name;
struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc-1, argv + 1);
if (goi.argc != 1) {
Jim_SetResultFormatted(goi.interp, "usage: %s <name>", cmd_name);
return JIM_ERR;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *t = jtag_tap_by_string(CMD_ARGV[0]);
if (!t) {
command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[0]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
struct jtag_tap *t;
t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
if (!t)
return JIM_ERR;
if (strcasecmp(cmd_name, "tapisenabled") == 0) {
if (strcmp(CMD_NAME, "tapisenabled") == 0) {
/* do nothing, just return the value */
} else if (strcasecmp(cmd_name, "tapenable") == 0) {
} else if (strcmp(CMD_NAME, "tapenable") == 0) {
if (!jtag_tap_enable(t)) {
LOG_WARNING("failed to enable tap %s", t->dotted_name);
return JIM_ERR;
command_print(CMD, "failed to enable tap %s", t->dotted_name);
return ERROR_FAIL;
}
} else if (strcasecmp(cmd_name, "tapdisable") == 0) {
} else if (strcmp(CMD_NAME, "tapdisable") == 0) {
if (!jtag_tap_disable(t)) {
LOG_WARNING("failed to disable tap %s", t->dotted_name);
return JIM_ERR;
command_print(CMD, "failed to disable tap %s", t->dotted_name);
return ERROR_FAIL;
}
} else {
LOG_ERROR("command '%s' unknown", cmd_name);
return JIM_ERR;
command_print(CMD, "command '%s' unknown", CMD_NAME);
return ERROR_FAIL;
}
bool e = t->enabled;
Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
return JIM_OK;
command_print(CMD, "%d", t->enabled ? 1 : 0);
return ERROR_OK;
}
int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@ -798,7 +743,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
{
.name = "newtap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_jtag_newtap,
.handler = handle_jtag_newtap,
.help = "Create a new TAP instance named basename.tap_type, "
"and appends it to the scan chain.",
.usage = "basename tap_type '-irlen' count "
@ -812,7 +757,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
{
.name = "tapisenabled",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Returns a Tcl boolean (0/1) indicating whether "
"the TAP is enabled (1) or not (0).",
.usage = "tap_name",
@ -820,7 +765,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
{
.name = "tapenable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Try to enable the specified TAP using the "
"'tap-enable' TAP event.",
.usage = "tap_name",
@ -828,7 +773,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
{
.name = "tapdisable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Try to disable the specified TAP using the "
"'tap-disable' TAP event.",
.usage = "tap_name",

View File

@ -18,9 +18,10 @@
#ifndef OPENOCD_JTAG_TCL_H
#define OPENOCD_JTAG_TCL_H
#include <helper/command.h>
int jim_jtag_configure(Jim_Interp *interp, int argc,
Jim_Obj * const *argv);
int jim_jtag_tap_enabler(Jim_Interp *interp, int argc,
Jim_Obj * const *argv);
__COMMAND_HANDLER(handle_jtag_tap_enabler);
#endif /* OPENOCD_JTAG_TCL_H */

View File

@ -29,7 +29,7 @@ static int lattice_read_bit_file(struct lattice_bit_file *bit_file, const char *
if (retval != ERROR_OK)
return retval;
bit_file->part = 0;
bit_file->part = NULL;
bit_file->has_id = false;
enum read_bit_state state = SEEK_HEADER_START;
for (size_t pos = 1; pos < bit_file->raw_bit.length && state != DONE; ++pos) {

View File

@ -156,8 +156,6 @@ COMMAND_HANDLER(handle_pld_load_command)
if (retval != ERROR_OK) {
command_print(CMD, "failed loading file %s to pld device %u",
CMD_ARGV[1], dev_id);
switch (retval) {
}
return retval;
} else {
gettimeofday(&end, NULL);

View File

@ -241,9 +241,13 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
return ERROR_FAIL;
}
virtex2_read_stat(device, &status);
int retval = virtex2_read_stat(device, &status);
if (retval != ERROR_OK) {
command_print(CMD, "cannot read virtex2 status register");
return retval;
}
command_print(CMD, "virtex2 status register: 0x%8.8" PRIx32 "", status);
command_print(CMD, "virtex2 status register: 0x%8.8" PRIx32, status);
return ERROR_OK;
}

View File

@ -1161,9 +1161,6 @@ static bool ecos_detect_rtos(struct target *target)
return false;
}
extern int rtos_thread_packet(struct connection *connection,
const char *packet, int packet_size);
/* Since we should never have 0 as a valid eCos thread ID we use $Hg0 as the
* indicator of a new session as regards flushing any cached state. */
static int ecos_packet_hook(struct connection *connection,

View File

@ -35,8 +35,6 @@ struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address,
#define HW_THREAD_NAME_STR_SIZE (32)
extern int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
static inline threadid_t threadid_from_target(const struct target *target)
{
return target->coreid + 1;

View File

@ -37,8 +37,6 @@ static const struct rtos_type *rtos_types[] = {
static int rtos_try_next(struct target *target);
int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
int rtos_smp_init(struct target *target)
{
if (target->rtos->type->smp_init)

View File

@ -157,6 +157,7 @@ int rtos_generic_stack_write_reg(struct target *target,
target_addr_t stack_ptr,
uint32_t reg_num, uint8_t *reg_value);
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size);
int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
int rtos_get_gdb_reg(struct connection *connection, int reg_num);
int rtos_get_gdb_reg_list(struct connection *connection);
int rtos_update_threads(struct target *target);

View File

@ -29,6 +29,12 @@
struct ucos_iii_params {
const char *target_name;
const unsigned char pointer_width;
size_t threadid_start;
const struct rtos_register_stacking *stacking_info;
};
struct ucos_iii_private {
const struct ucos_iii_params *params;
symbol_address_t thread_stack_offset;
symbol_address_t thread_name_offset;
symbol_address_t thread_state_offset;
@ -36,40 +42,22 @@ struct ucos_iii_params {
symbol_address_t thread_prev_offset;
symbol_address_t thread_next_offset;
bool thread_offsets_updated;
size_t threadid_start;
const struct rtos_register_stacking *stacking_info;
size_t num_threads;
symbol_address_t threads[];
symbol_address_t threads[UCOS_III_MAX_THREADS];
};
static const struct ucos_iii_params ucos_iii_params_list[] = {
{
"cortex_m", /* target_name */
sizeof(uint32_t), /* pointer_width */
0, /* thread_stack_offset */
0, /* thread_name_offset */
0, /* thread_state_offset */
0, /* thread_priority_offset */
0, /* thread_prev_offset */
0, /* thread_next_offset */
false, /* thread_offsets_updated */
1, /* threadid_start */
&rtos_ucos_iii_cortex_m_stacking, /* stacking_info */
0, /* num_threads */
.target_name = "cortex_m",
.pointer_width = sizeof(uint32_t),
.threadid_start = 1,
.stacking_info = &rtos_ucos_iii_cortex_m_stacking,
},
{
"esirisc", /* target_name */
sizeof(uint32_t), /* pointer_width */
0, /* thread_stack_offset */
0, /* thread_name_offset */
0, /* thread_state_offset */
0, /* thread_priority_offset */
0, /* thread_prev_offset */
0, /* thread_next_offset */
false, /* thread_offsets_updated */
1, /* threadid_start */
&rtos_ucos_iii_esi_risc_stacking, /* stacking_info */
0, /* num_threads */
.target_name = "esirisc",
.pointer_width = sizeof(uint32_t),
.threadid_start = 1,
.stacking_info = &rtos_ucos_iii_esi_risc_stacking,
},
};
@ -118,7 +106,7 @@ static const char * const ucos_iii_thread_state_list[] = {
static int ucos_iii_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address,
threadid_t *threadid)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
size_t thread_index;
for (thread_index = 0; thread_index < params->num_threads; thread_index++)
@ -133,17 +121,17 @@ static int ucos_iii_find_or_create_thread(struct rtos *rtos, symbol_address_t th
params->threads[thread_index] = thread_address;
params->num_threads++;
found:
*threadid = thread_index + params->threadid_start;
*threadid = thread_index + params->params->threadid_start;
return ERROR_OK;
}
static int ucos_iii_find_thread_address(struct rtos *rtos, threadid_t threadid,
symbol_address_t *thread_address)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
size_t thread_index;
thread_index = threadid - params->threadid_start;
thread_index = threadid - params->params->threadid_start;
if (thread_index >= params->num_threads) {
LOG_ERROR("uCOS-III: failed to find thread address");
return ERROR_FAIL;
@ -155,7 +143,7 @@ static int ucos_iii_find_thread_address(struct rtos *rtos, threadid_t threadid,
static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
int retval;
/* read the thread list head */
@ -163,7 +151,7 @@ static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t
retval = target_read_memory(rtos->target,
rtos->symbols[UCOS_III_VAL_OS_TASK_DBG_LIST_PTR].address,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&thread_list_address);
if (retval != ERROR_OK) {
@ -177,7 +165,7 @@ static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t
retval = target_read_memory(rtos->target,
thread_list_address + params->thread_next_offset,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&thread_list_address);
if (retval != ERROR_OK) {
@ -191,7 +179,7 @@ static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t
static int ucos_iii_update_thread_offsets(struct rtos *rtos)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
if (params->thread_offsets_updated)
return ERROR_OK;
@ -231,7 +219,7 @@ static int ucos_iii_update_thread_offsets(struct rtos *rtos)
int retval = target_read_memory(rtos->target,
rtos->symbols[thread_offset_map->symbol_value].address,
params->pointer_width,
params->params->pointer_width,
1,
(void *)thread_offset_map->thread_offset);
if (retval != ERROR_OK) {
@ -252,7 +240,7 @@ static bool ucos_iii_detect_rtos(struct target *target)
static int ucos_iii_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
{
struct ucos_iii_params *params = target->rtos->rtos_specific_params;
struct ucos_iii_private *params = target->rtos->rtos_specific_params;
params->thread_offsets_updated = false;
params->num_threads = 0;
@ -262,17 +250,17 @@ static int ucos_iii_reset_handler(struct target *target, enum target_reset_mode
static int ucos_iii_create(struct target *target)
{
struct ucos_iii_params *params;
struct ucos_iii_private *params;
for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_params_list); i++)
if (strcmp(ucos_iii_params_list[i].target_name, target->type->name) == 0) {
params = malloc(sizeof(*params) + (UCOS_III_MAX_THREADS * sizeof(*params->threads)));
params = calloc(1, sizeof(*params));
if (!params) {
LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL;
}
memcpy(params, &ucos_iii_params_list[i], sizeof(ucos_iii_params_list[i]));
params->params = &ucos_iii_params_list[i];
target->rtos->rtos_specific_params = (void *)params;
target_register_reset_callback(ucos_iii_reset_handler, NULL);
@ -286,7 +274,7 @@ static int ucos_iii_create(struct target *target)
static int ucos_iii_update_threads(struct rtos *rtos)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
int retval;
if (!rtos->symbols) {
@ -340,7 +328,7 @@ static int ucos_iii_update_threads(struct rtos *rtos)
retval = target_read_memory(rtos->target,
rtos->symbols[UCOS_III_VAL_OS_TCB_CUR_PTR].address,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&current_thread_address);
if (retval != ERROR_OK) {
@ -396,7 +384,7 @@ static int ucos_iii_update_threads(struct rtos *rtos)
retval = target_read_memory(rtos->target,
thread_address + params->thread_name_offset,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&thread_name_address);
if (retval != ERROR_OK) {
@ -450,7 +438,7 @@ static int ucos_iii_update_threads(struct rtos *rtos)
/* read previous thread address */
retval = target_read_memory(rtos->target,
thread_address + params->thread_prev_offset,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&thread_address);
if (retval != ERROR_OK) {
@ -465,7 +453,7 @@ static int ucos_iii_update_threads(struct rtos *rtos)
static int ucos_iii_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
struct rtos_reg **reg_list, int *num_regs)
{
struct ucos_iii_params *params = rtos->rtos_specific_params;
struct ucos_iii_private *params = rtos->rtos_specific_params;
int retval;
/* find thread address for threadid */
@ -482,7 +470,7 @@ static int ucos_iii_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
retval = target_read_memory(rtos->target,
thread_address + params->thread_stack_offset,
params->pointer_width,
params->params->pointer_width,
1,
(void *)&stack_address);
if (retval != ERROR_OK) {
@ -491,7 +479,7 @@ static int ucos_iii_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
}
return rtos_generic_stack_read(rtos->target,
params->stacking_info,
params->params->stacking_info,
stack_address,
reg_list,
num_regs);

View File

@ -117,7 +117,7 @@ static void gdb_sig_halted(struct connection *connection);
/* number of gdb connections, mainly to suppress gdb related debugging spam
* in helper/log.c when no gdb connections are actually active */
int gdb_actual_connections;
static int gdb_actual_connections;
/* set if we are sending a memory map to gdb
* via qXfer:memory-map:read packet */
@ -186,6 +186,9 @@ static bool gdb_connection_includes_target(struct connection *connection, struct
static int gdb_last_signal(struct target *target)
{
LOG_TARGET_DEBUG(target, "Debug reason is: %s",
target_debug_reason_str(target->debug_reason));
switch (target->debug_reason) {
case DBG_REASON_DBGRQ:
return 0x2; /* SIGINT */
@ -200,8 +203,9 @@ static int gdb_last_signal(struct target *target)
case DBG_REASON_NOTHALTED:
return 0x0; /* no signal... shouldn't happen */
default:
LOG_USER("undefined debug reason %d - target needs reset",
target->debug_reason);
LOG_USER("undefined debug reason %d (%s) - target needs reset",
target->debug_reason,
target_debug_reason_str(target->debug_reason));
return 0x0;
}
}
@ -272,39 +276,20 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char)
}
#ifdef _WIN32
errno = WSAGetLastError();
switch (errno) {
case WSAEWOULDBLOCK:
usleep(1000);
break;
case WSAECONNABORTED:
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
case WSAECONNRESET:
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
default:
LOG_ERROR("read: %d", errno);
exit(-1);
}
bool retry = (WSAGetLastError() == WSAEWOULDBLOCK);
#else
switch (errno) {
case EAGAIN:
usleep(1000);
break;
case ECONNABORTED:
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
case ECONNRESET:
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
default:
LOG_ERROR("read: %s", strerror(errno));
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
bool retry = (errno == EAGAIN);
#endif
if (retry) {
// Try again after a delay
usleep(1000);
} else {
// Print error and close the socket
log_socket_error("GDB");
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
}
#ifdef _DEBUG_GDB_IO_
@ -844,6 +829,7 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
}
if (gdb_connection->ctrl_c) {
LOG_TARGET_DEBUG(target, "Responding with signal 2 (SIGINT) to debugger due to Ctrl-C");
signal_var = 0x2;
} else
signal_var = gdb_last_signal(ct);
@ -4201,3 +4187,8 @@ void gdb_service_free(void)
free(gdb_port);
free(gdb_port_next);
}
int gdb_get_actual_connections(void)
{
return gdb_actual_connections;
}

View File

@ -20,6 +20,7 @@
struct image;
struct reg;
#include <target/target.h>
#include <server/server.h>
#define GDB_BUFFER_SIZE 16384
@ -29,6 +30,8 @@ void gdb_service_free(void);
int gdb_put_packet(struct connection *connection, char *buffer, int len);
int gdb_get_actual_connections(void);
static inline struct target *get_target_from_connection(struct connection *connection)
{
struct gdb_service *gdb_service = connection->service->priv;

View File

@ -58,8 +58,15 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] =
{
.name = "newtap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_jtag_newtap,
.help = "declare a new TAP"
.handler = handle_jtag_newtap,
.help = "declare a new TAP",
.usage = "basename tap_type '-irlen' count "
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-mask' number]",
},
{
.name = "init",
@ -82,12 +89,18 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] =
{
.name = "tapisenabled",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Returns a Tcl boolean (0/1) indicating whether "
"the TAP is enabled (1) or not (0).",
.usage = "tap_name",
},
{
.name = "tapenable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.handler = handle_jtag_tap_enabler,
.help = "Try to enable the specified TAP using the "
"'tap-enable' TAP event.",
.usage = "tap_name",
},
{
.name = "tapdisable",
@ -135,8 +148,15 @@ static const struct command_registration dapdirect_swd_subcommand_handlers[] = {
{
.name = "newdap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_jtag_newtap,
.handler = handle_jtag_newtap,
.help = "declare a new SWD DAP",
.usage = "basename dap_type ['-irlen' count] "
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
};

View File

@ -657,9 +657,16 @@ static const struct command_registration swd_commands[] = {
* REVISIT can we verify "just one SWD DAP" here/early?
*/
.name = "newdap",
.jim_handler = jim_jtag_newtap,
.handler = handle_jtag_newtap,
.mode = COMMAND_CONFIG,
.help = "declare a new SWD DAP"
.help = "declare a new SWD DAP",
.usage = "basename dap_type ['-irlen' count] "
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
};

View File

@ -292,14 +292,14 @@ int armv4_5_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
int armv4_5_run_algorithm_inner(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,
int timeout_ms, void *arch_info,
unsigned int timeout_ms, void *arch_info,
int (*run_it)(struct target *target, uint32_t exit_point,
int timeout_ms, void *arch_info));
unsigned int timeout_ms, void *arch_info));
int arm_checksum_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *checksum);

View File

@ -2518,7 +2518,7 @@ static const uint8_t *dcc_buffer;
static int arm7_9_dcc_completion(struct target *target,
uint32_t exit_point,
int timeout_ms,
unsigned int timeout_ms,
void *arch_info)
{
int retval = ERROR_OK;

View File

@ -455,6 +455,9 @@ enum ap_type {
AP_TYPE_AHB5H_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 8), /* AHB5 with enhanced HPROT Memory-AP */
};
extern const struct dap_ops jtag_dp_ops;
extern const struct dap_ops swd_dap_ops;
/* Check the ap->cfg_reg Long Address field (bit 1)
*
* 0b0: The AP only supports physical addresses 32 bits or smaller

View File

@ -20,8 +20,6 @@
static LIST_HEAD(all_dap);
extern const struct dap_ops swd_dap_ops;
extern const struct dap_ops jtag_dp_ops;
extern struct adapter_driver *adapter_driver;
/* DAP command support */

View File

@ -1050,7 +1050,7 @@ int arm_dpm_setup(struct arm_dpm *dpm)
{
struct arm *arm = dpm->arm;
struct target *target = arm->target;
struct reg_cache *cache = 0;
struct reg_cache *cache = NULL;
arm->dpm = dpm;

View File

@ -1252,7 +1252,7 @@ int arm_get_gdb_reg_list(struct target *target,
/* wait for execution to complete and check exit point */
static int armv4_5_run_algorithm_completion(struct target *target,
uint32_t exit_point,
int timeout_ms,
unsigned int timeout_ms,
void *arch_info)
{
int retval;
@ -1286,9 +1286,9 @@ int armv4_5_run_algorithm_inner(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,
int timeout_ms, void *arch_info,
unsigned int timeout_ms, void *arch_info,
int (*run_it)(struct target *target, uint32_t exit_point,
int timeout_ms, void *arch_info))
unsigned int timeout_ms, void *arch_info))
{
struct arm *arm = target_to_arm(target);
struct arm_algorithm *arm_algorithm_info = arch_info;
@ -1474,7 +1474,7 @@ int armv4_5_run_algorithm(struct target *target,
struct reg_param *reg_params,
target_addr_t entry_point,
target_addr_t exit_point,
int timeout_ms,
unsigned int timeout_ms,
void *arch_info)
{
return armv4_5_run_algorithm_inner(target,
@ -1535,7 +1535,7 @@ int arm_checksum_memory(struct target *target,
buf_set_u32(reg_params[1].value, 0, 32, count);
/* 20 second timeout/megabyte */
int timeout = 20000 * (1 + (count / (1024 * 1024)));
unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
/* armv4 must exit using a hardware breakpoint */
if (arm->arch == ARM_ARCH_V4)

View File

@ -484,7 +484,7 @@ int armv7m_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info)
unsigned int timeout_ms, void *arch_info)
{
int retval;
@ -622,7 +622,7 @@ int armv7m_start_algorithm(struct target *target,
int armv7m_wait_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t exit_point, int timeout_ms,
target_addr_t exit_point, unsigned int timeout_ms,
void *arch_info)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
@ -909,7 +909,7 @@ int armv7m_checksum_memory(struct target *target,
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[1].value, 0, 32, count);
int timeout = 20000 * (1 + (count / (1024 * 1024)));
unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
@ -1016,7 +1016,7 @@ int armv7m_blank_check_memory(struct target *target,
buf_set_u32(reg_params[1].value, 0, 32, erased_word);
/* assume CPU clk at least 1 MHz */
int timeout = (timed_out ? 30000 : 2000) + total_size * 3 / 1000;
unsigned int timeout = (timed_out ? 30000 : 2000) + total_size * 3 / 1000;
retval = target_run_algorithm(target,
0, NULL,

View File

@ -314,7 +314,7 @@ int armv7m_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
int armv7m_start_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
@ -325,7 +325,7 @@ int armv7m_start_algorithm(struct target *target,
int armv7m_wait_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t exit_point, int timeout_ms,
target_addr_t exit_point, unsigned int timeout_ms,
void *arch_info);
int armv7m_invalidate_core_regs(struct target *target);

View File

@ -1682,7 +1682,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
LOG_ERROR("unable to allocate reg type list");
if (i == ARMV8_PAUTH_CMASK || i == ARMV8_PAUTH_DMASK)
reg_list[i].hidden = !armv8->enable_pauth;
reg_list[i].exist = armv8->enable_pauth;
}
arm->cpsr = reg_list + ARMV8_XPSR;

View File

@ -801,15 +801,11 @@ static int cortex_m_debug_entry(struct target *target)
return retval;
/* examine PE security state */
bool secure_state = false;
uint32_t dscsr = 0;
if (armv7m->arm.arch == ARM_ARCH_V8M) {
uint32_t dscsr;
retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DSCSR, &dscsr);
if (retval != ERROR_OK)
return retval;
secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS;
}
/* Load all registers to arm.core_cache */
@ -857,6 +853,7 @@ static int cortex_m_debug_entry(struct target *target)
if (armv7m->exception_number)
cortex_m_examine_exception_reason(target);
bool secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS;
LOG_TARGET_DEBUG(target, "entered debug state in core mode: %s at PC 0x%" PRIx32
", cpu in %s state, target->state: %s",
arm_mode_name(arm->core_mode),

View File

@ -1374,7 +1374,7 @@ static int dsp563xx_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info)
unsigned int timeout_ms, void *arch_info)
{
int i;
int retval = ERROR_OK;

View File

@ -15,5 +15,8 @@ noinst_LTLIBRARIES += %D%/libespressif.la
%D%/esp32.c \
%D%/esp32s2.c \
%D%/esp32s3.c \
%D%/esp32_sysview.c \
%D%/esp32_sysview.h \
%D%/segger_sysview.h \
%D%/esp_semihosting.c \
%D%/esp_semihosting.h

View File

@ -32,6 +32,8 @@
#include "esp_xtensa_smp.h"
#include "esp_xtensa_apptrace.h"
#include "esp32_apptrace.h"
#include "esp32_sysview.h"
#include "segger_sysview.h"
#define ESP32_APPTRACE_USER_BLOCK_CORE(_v_) ((_v_) >> 15)
#define ESP32_APPTRACE_USER_BLOCK_LEN(_v_) ((_v_) & ~BIT(15))
@ -82,6 +84,8 @@ static int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx,
static struct esp32_apptrace_block *esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx *ctx);
static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx *ctx,
struct esp32_apptrace_block *block);
static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx);
static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx);
static const bool s_time_stats_enable = true;
@ -1118,10 +1122,7 @@ static int esp32_apptrace_poll(void *priv)
return ERROR_FAIL;
}
}
res =
ctx->hw->data_read(ctx->cpus[fired_target_num],
target_state[fired_target_num].data_len,
block->data,
res = ctx->hw->data_read(ctx->cpus[fired_target_num], target_state[fired_target_num].data_len, block->data,
target_state[fired_target_num].block_id,
/* do not ack target data in sync mode,
esp32_apptrace_handle_trace_block() can write response data and will do ack thereafter */
@ -1215,6 +1216,11 @@ static int esp32_apptrace_poll(void *priv)
return ERROR_OK;
}
static inline bool is_sysview_mode(int mode)
{
return mode == ESP_APPTRACE_CMD_MODE_SYSVIEW || mode == ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE;
}
static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
{
if (duration_measure(&ctx->read_time) != 0)
@ -1222,7 +1228,12 @@ static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
int res = target_unregister_timer_callback(esp32_apptrace_poll, ctx);
if (res != ERROR_OK)
LOG_ERROR("Failed to unregister target timer handler (%d)!", res);
if (is_sysview_mode(ctx->mode)) {
/* stop tracing */
res = esp32_sysview_stop(ctx);
if (res != ERROR_OK)
LOG_ERROR("sysview: Failed to stop tracing!");
}
/* data processor is alive, so wait for all received blocks to be processed */
res = esp32_apptrace_wait_tracing_finished(ctx);
if (res != ERROR_OK)
@ -1236,7 +1247,191 @@ static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
LOG_ERROR("Failed to cleanup cmd ctx (%d)!", res);
}
int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const char **argv, int argc)
/* this function must be called after connecting to targets */
static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx)
{
uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_START };
uint32_t fired_target_num = 0;
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM] = {0};
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
/* get current block id */
int res = esp32_apptrace_get_data_info(ctx, target_state, &fired_target_num);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to read target data info!");
return res;
}
if (fired_target_num == UINT32_MAX) {
/* it can happen that there is no pending target data, but block was switched
* in this case block_ids on both CPUs are equal, so select the first one */
fired_target_num = 0;
}
/* start tracing */
res = esp_apptrace_usr_block_write(ctx->hw, ctx->cpus[fired_target_num], target_state[fired_target_num].block_id,
cmds, sizeof(cmds));
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to start tracing!");
return res;
}
cmd_data->sv_trace_running = 1;
return res;
}
static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx)
{
uint32_t old_block_id, fired_target_num = 0, empty_target_num = 0;
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM];
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_STOP };
struct duration wait_time;
struct esp32_apptrace_block *block = esp32_apptrace_free_block_get(ctx);
if (!block) {
LOG_ERROR("Failed to get free block for data on (%s)!", target_name(ctx->cpus[fired_target_num]));
return ERROR_FAIL;
}
/* halt all CPUs (not only one), otherwise it can happen that there is no target data and
* while we are queueing commands another CPU switches tracing block */
int res = esp32_apptrace_safe_halt_targets(ctx, target_state);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to halt targets (%d)!", res);
return res;
}
/* it can happen that there is no pending target data
* in this case block_ids on both CPUs are equal, so the first one will be selected */
for (unsigned int k = 0; k < ctx->cores_num; k++) {
if (target_state[k].data_len) {
fired_target_num = k;
break;
}
}
if (target_state[fired_target_num].data_len) {
/* read pending data without ack, they will be acked when stop command is queued */
res = ctx->hw->data_read(ctx->cpus[fired_target_num], target_state[fired_target_num].data_len, block->data,
target_state[fired_target_num].block_id,
false /*no ack target data*/);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to read data on (%s)!", target_name(ctx->cpus[fired_target_num]));
return res;
}
/* process data */
block->data_len = target_state[fired_target_num].data_len;
res = esp32_apptrace_handle_trace_block(ctx, block);
if (res != ERROR_OK) {
LOG_ERROR("Failed to process trace block %" PRId32 " bytes!", block->data_len);
return res;
}
}
/* stop tracing and ack target data */
res = esp_apptrace_usr_block_write(ctx->hw, ctx->cpus[fired_target_num], target_state[fired_target_num].block_id,
cmds,
sizeof(cmds));
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to stop tracing!");
return res;
}
if (ctx->cores_num > 1) {
empty_target_num = fired_target_num ? 0 : 1;
/* ack target data on another CPU */
res = ctx->hw->ctrl_reg_write(ctx->cpus[empty_target_num], target_state[fired_target_num].block_id,
0 /*target data ack*/,
true /*host connected*/,
false /*no host data*/);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to ack data on target '%s' (%d)!",
target_name(ctx->cpus[empty_target_num]), res);
return res;
}
}
/* resume targets to allow command processing */
LOG_INFO("Resume targets");
bool smp_resumed = false;
for (unsigned int k = 0; k < ctx->cores_num; k++) {
if (smp_resumed && ctx->cpus[k]->smp) {
/* in SMP mode we need to call target_resume for one core only */
continue;
}
res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to resume target '%s' (%d)!", target_name(ctx->cpus[k]), res);
return res;
}
if (ctx->cpus[k]->smp)
smp_resumed = true;
}
/* wait for block switch (command sent), so we can disconnect from targets */
old_block_id = target_state[fired_target_num].block_id;
if (duration_start(&wait_time) != 0) {
LOG_ERROR("Failed to start trace stop timeout measurement!");
return ERROR_FAIL;
}
/* we are waiting for the last data from tracing block and also there can be data in the pended
* data buffer */
/* so we are expecting two TRX block switches at most or stopping due to timeout */
while (cmd_data->sv_trace_running) {
res = esp32_apptrace_get_data_info(ctx, target_state, &fired_target_num);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to read targets data info!");
return res;
}
if (fired_target_num == UINT32_MAX) {
/* it can happen that there is no pending (last) target data, but block was
* switched */
/* in this case block_ids on both CPUs are equal, so select the first one */
fired_target_num = 0;
}
if (target_state[fired_target_num].block_id != old_block_id) {
if (target_state[fired_target_num].data_len) {
/* read last data and ack them */
res = ctx->hw->data_read(ctx->cpus[fired_target_num],
target_state[fired_target_num].data_len,
block->data,
target_state[fired_target_num].block_id,
true /*ack target data*/);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to read last data on (%s)!", target_name(ctx->cpus[fired_target_num]));
} else {
if (ctx->cores_num > 1) {
/* ack target data on another CPU */
empty_target_num = fired_target_num ? 0 : 1;
res = ctx->hw->ctrl_reg_write(ctx->cpus[empty_target_num],
target_state[fired_target_num].block_id,
0 /*all read*/,
true /*host connected*/,
false /*no host data*/);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to ack data on target '%s' (%d)!",
target_name(ctx->cpus[empty_target_num]), res);
return res;
}
}
/* process data */
block->data_len = target_state[fired_target_num].data_len;
res = esp32_apptrace_handle_trace_block(ctx, block);
if (res != ERROR_OK) {
LOG_ERROR("Failed to process trace block %" PRId32 " bytes!",
block->data_len);
return res;
}
}
old_block_id = target_state[fired_target_num].block_id;
}
}
if (duration_measure(&wait_time) != 0) {
LOG_ERROR("Failed to start trace stop timeout measurement!");
return ERROR_FAIL;
}
const float stop_tmo = LOG_LEVEL_IS(LOG_LVL_DEBUG) ? 30.0 : 0.5;
if (duration_elapsed(&wait_time) >= stop_tmo) {
LOG_INFO("Stop waiting for the last data due to timeout.");
break;
}
}
return res;
}
static int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const char **argv, int argc)
{
static struct esp32_apptrace_cmd_ctx s_at_cmd_ctx;
struct esp32_apptrace_cmd_data *cmd_data;
@ -1264,17 +1459,39 @@ int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const c
old_state = target->state;
if (strcmp(argv[0], "start") == 0) {
res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
cmd,
mode,
&argv[1],
argc - 1);
if (res != ERROR_OK) {
command_print(cmd, "Failed to init cmd ctx (%d)!", res);
return res;
if (is_sysview_mode(mode)) {
/* init cmd context */
res = esp32_sysview_cmd_init(&s_at_cmd_ctx,
cmd,
mode,
mode == ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE,
&argv[1],
argc - 1);
if (res != ERROR_OK) {
command_print(cmd, "Failed to init cmd ctx (%d)!", res);
return res;
}
cmd_data = s_at_cmd_ctx.cmd_priv;
if (cmd_data->skip_len != 0) {
s_at_cmd_ctx.running = 0;
esp32_sysview_cmd_cleanup(&s_at_cmd_ctx);
command_print(cmd, "Data skipping not supported!");
return ERROR_FAIL;
}
s_at_cmd_ctx.process_data = esp32_sysview_process_data;
} else {
res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
cmd,
mode,
&argv[1],
argc - 1);
if (res != ERROR_OK) {
command_print(cmd, "Failed to init cmd ctx (%d)!", res);
return res;
}
cmd_data = s_at_cmd_ctx.cmd_priv;
s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
}
cmd_data = s_at_cmd_ctx.cmd_priv;
s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
s_at_cmd_ctx.auto_clean = esp32_apptrace_cmd_stop;
if (cmd_data->wait4halt) {
res = esp32_apptrace_wait4halt(&s_at_cmd_ctx, target);
@ -1288,6 +1505,17 @@ int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const c
command_print(cmd, "Failed to connect to targets (%d)!", res);
goto _on_start_error;
}
if (is_sysview_mode(mode)) {
/* start tracing */
res = esp32_sysview_start(&s_at_cmd_ctx);
if (res != ERROR_OK) {
esp32_apptrace_connect_targets(&s_at_cmd_ctx, false, old_state == TARGET_RUNNING);
s_at_cmd_ctx.running = 0;
esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
command_print(cmd, "sysview: Failed to start tracing!");
return res;
}
}
res = target_register_timer_callback(esp32_apptrace_poll,
cmd_data->poll_period,
TARGET_TIMER_TYPE_PERIODIC,
@ -1309,6 +1537,10 @@ int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const c
esp32_apptrace_print_stats(&s_at_cmd_ctx);
return ERROR_OK;
} else if (strcmp(argv[0], "dump") == 0) {
if (is_sysview_mode(mode)) {
command_print(cmd, "Not supported!");
return ERROR_FAIL;
}
/* [dump outfile] - post-mortem dump without connection to targets */
res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
cmd,
@ -1349,7 +1581,10 @@ int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const c
_on_start_error:
s_at_cmd_ctx.running = 0;
esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
if (is_sysview_mode(mode))
esp32_sysview_cmd_cleanup(&s_at_cmd_ctx);
else
esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
return res;
}
@ -1358,6 +1593,16 @@ COMMAND_HANDLER(esp32_cmd_apptrace)
return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_GEN, CMD_ARGV, CMD_ARGC);
}
COMMAND_HANDLER(esp32_cmd_sysview)
{
return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_SYSVIEW, CMD_ARGV, CMD_ARGC);
}
COMMAND_HANDLER(esp32_cmd_sysview_mcore)
{
return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE, CMD_ARGV, CMD_ARGC);
}
const struct command_registration esp32_apptrace_command_handlers[] = {
{
.name = "apptrace",
@ -1366,7 +1611,25 @@ const struct command_registration esp32_apptrace_command_handlers[] = {
.help =
"App Tracing: application level trace control. Starts, stops or queries tracing process status.",
.usage =
"[start <destination> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] | [stop] | [status] | [dump <destination>]",
"(start <destination> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status) | (dump <destination>)",
},
{
.name = "sysview",
.handler = esp32_cmd_sysview,
.mode = COMMAND_EXEC,
.help =
"App Tracing: SEGGER SystemView compatible trace control. Starts, stops or queries tracing process status.",
.usage =
"(start file://<outfile1> [file://<outfile2>] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
},
{
.name = "sysview_mcore",
.handler = esp32_cmd_sysview_mcore,
.mode = COMMAND_EXEC,
.help =
"App Tracing: Espressif multi-core SystemView trace control. Starts, stops or queries tracing process status.",
.usage =
"(start file://<outfile> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]) | (stop) | (status)",
},
COMMAND_REGISTRATION_DONE
};

View File

@ -0,0 +1,554 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* ESP32 sysview tracing module *
* Copyright (C) 2020 Espressif Systems Ltd. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/log.h>
#include "esp32_apptrace.h"
#include "esp32_sysview.h"
#include "segger_sysview.h"
/* in SystemView mode core ID is passed in event ID field */
#define ESP32_SYSVIEW_USER_BLOCK_CORE(_v_) (0) /* not used */
#define ESP32_SYSVIEW_USER_BLOCK_LEN(_v_) (_v_)
#define ESP32_SYSVIEW_USER_BLOCK_HDR_SZ 2
struct esp_sysview_target2host_hdr {
uint8_t block_sz;
uint8_t wr_sz;
};
#define SYSVIEW_BLOCK_SIZE_OFFSET 0
#define SYSVIEW_WR_SIZE_OFFSET 1
static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx *ctx, bool mcore_format);
static int esp32_sysview_core_id_get(struct target *target, uint8_t *hdr_buf);
static uint32_t esp32_sysview_usr_block_len_get(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len);
int esp32_sysview_cmd_init(struct esp32_apptrace_cmd_ctx *cmd_ctx,
struct command_invocation *cmd,
int mode,
bool mcore_format,
const char **argv,
int argc)
{
struct esp32_sysview_cmd_data *cmd_data;
if (argc < 1) {
command_print(cmd, "Not enough args! Need trace data destination!");
return ERROR_FAIL;
}
int res = esp32_apptrace_cmd_ctx_init(cmd_ctx, cmd, mode);
if (res != ERROR_OK)
return res;
int core_num = cmd_ctx->cores_num;
if (!mcore_format && argc < core_num) {
command_print(cmd, "Not enough args! Need %d trace data destinations!", core_num);
res = ERROR_FAIL;
goto on_error;
}
cmd_data = calloc(1, sizeof(*cmd_data));
if (!cmd_data) {
command_print(cmd, "No memory for command data!");
res = ERROR_FAIL;
goto on_error;
}
cmd_ctx->cmd_priv = cmd_data;
cmd_data->mcore_format = mcore_format;
/*outfile1 [outfile2] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] */
int dests_num = esp32_apptrace_dest_init(cmd_data->data_dests, argv, !mcore_format ? core_num : 1);
if (!mcore_format && dests_num < core_num) {
command_print(cmd, "Not enough args! Need %d trace data destinations!", core_num);
free(cmd_data);
res = ERROR_FAIL;
goto on_error;
}
cmd_data->apptrace.max_len = UINT32_MAX;
cmd_data->apptrace.poll_period = 0 /*ms*/;
cmd_ctx->stop_tmo = -1.0; /* infinite */
if (argc > dests_num) {
/* parse remaining args */
esp32_apptrace_cmd_args_parse(cmd_ctx,
&cmd_data->apptrace,
&argv[dests_num],
argc - dests_num);
}
LOG_USER("App trace params: from %d cores, size %u bytes, stop_tmo %g s, "
"poll period %u ms, wait_rst %d, skip %u bytes",
cmd_ctx->cores_num,
cmd_data->apptrace.max_len,
cmd_ctx->stop_tmo,
cmd_data->apptrace.poll_period,
cmd_data->apptrace.wait4halt,
cmd_data->apptrace.skip_len);
cmd_ctx->trace_format.hdr_sz = ESP32_SYSVIEW_USER_BLOCK_HDR_SZ;
cmd_ctx->trace_format.core_id_get = esp32_sysview_core_id_get;
cmd_ctx->trace_format.usr_block_len_get = esp32_sysview_usr_block_len_get;
res = esp_sysview_trace_header_write(cmd_ctx, mcore_format);
if (res != ERROR_OK) {
command_print(cmd, "Failed to write trace header (%d)!", res);
esp32_apptrace_dest_cleanup(cmd_data->data_dests, core_num);
free(cmd_data);
return res;
}
return ERROR_OK;
on_error:
cmd_ctx->running = 0;
esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
return res;
}
int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
{
struct esp32_sysview_cmd_data *cmd_data = cmd_ctx->cmd_priv;
esp32_apptrace_dest_cleanup(cmd_data->data_dests, cmd_ctx->cores_num);
free(cmd_data);
cmd_ctx->cmd_priv = NULL;
esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
return ERROR_OK;
}
static int esp32_sysview_core_id_get(struct target *target, uint8_t *hdr_buf)
{
/* for sysview compressed apptrace header is used, so core id is encoded in sysview packet */
return 0;
}
static uint32_t esp32_sysview_usr_block_len_get(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len)
{
*wr_len = ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf[SYSVIEW_WR_SIZE_OFFSET]);
return ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf[SYSVIEW_BLOCK_SIZE_OFFSET]);
}
static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx *ctx, bool mcore_format)
{
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
char *hdr_str;
int dests_num;
if (!mcore_format) {
hdr_str = ";\n"
"; Version " SYSVIEW_MIN_VER_STRING "\n"
"; Author Espressif Inc\n"
";\n";
dests_num = ctx->cores_num;
} else {
hdr_str = ";\n"
"; Version " SYSVIEW_MIN_VER_STRING "\n"
"; Author Espressif Inc\n"
"; ESP_Extension\n"
";\n";
dests_num = 1;
}
int hdr_len = strlen(hdr_str);
for (int i = 0; i < dests_num; i++) {
int res = cmd_data->data_dests[i].write(cmd_data->data_dests[i].priv,
(uint8_t *)hdr_str,
hdr_len);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", hdr_len, i);
return ERROR_FAIL;
}
}
return ERROR_OK;
}
static void sysview_encode_u32(uint8_t **dest, uint32_t val)
{
uint8_t *sv_ptr = *dest;
while (val > 0x7F) {
*sv_ptr++ = (uint8_t)(val | 0x80);
val >>= 7;
}
*sv_ptr++ = (uint8_t)val;
*dest = sv_ptr;
}
static uint32_t esp_sysview_decode_u32(uint8_t **ptr)
{
uint32_t val = 0;
for (int k = 0;; k++, (*ptr)++) {
if (**ptr & 0x80) {
val |= (uint32_t)(**ptr & ~0x80) << 7 * k;
} else {
val |= (uint32_t)**ptr << 7 * k;
(*ptr)++;
break;
}
}
return val;
}
static uint16_t esp_sysview_decode_plen(uint8_t **ptr)
{
uint16_t payload_len = 0;
uint8_t *p = *ptr;
/* here pkt points to encoded payload length */
if (*p & 0x80) {
payload_len = *(p + 1); /* higher part */
payload_len = (payload_len << 7) | (*p & ~0x80);/* lower 7 bits */
p += 2; /* payload len (2 bytes) */
} else {
payload_len = *p;
p++; /* payload len (1 byte) */
}
*ptr = p;
return payload_len;
}
static uint16_t esp_sysview_get_predef_payload_len(uint16_t id, uint8_t *pkt)
{
uint16_t len;
uint8_t *ptr = pkt;
switch (id) {
case SYSVIEW_EVTID_OVERFLOW:
case SYSVIEW_EVTID_ISR_ENTER:
case SYSVIEW_EVTID_TASK_START_EXEC:
case SYSVIEW_EVTID_TASK_START_READY:
case SYSVIEW_EVTID_TASK_CREATE:
case SYSVIEW_EVTID_SYSTIME_CYCLES:
case SYSVIEW_EVTID_USER_START:
case SYSVIEW_EVTID_USER_STOP:
case SYSVIEW_EVTID_TIMER_ENTER:
/*ENCODE_U32 */
esp_sysview_decode_u32(&ptr);
len = ptr - pkt;
break;
case SYSVIEW_EVTID_TASK_STOP_READY:
case SYSVIEW_EVTID_SYSTIME_US:
/*2*ENCODE_U32 */
esp_sysview_decode_u32(&ptr);
esp_sysview_decode_u32(&ptr);
len = ptr - pkt;
break;
case SYSVIEW_EVTID_SYSDESC:
/*str(128 + 1) */
len = *ptr + 1;
break;
case SYSVIEW_EVTID_TASK_INFO:
case SYSVIEW_EVTID_MODULEDESC:
/*2*ENCODE_U32 + str */
esp_sysview_decode_u32(&ptr);
esp_sysview_decode_u32(&ptr);
/* TODO: add support for strings longer then 255 bytes */
len = ptr - pkt + *ptr + 1;
break;
case SYSVIEW_EVTID_STACK_INFO:
/*4*ENCODE_U32 */
esp_sysview_decode_u32(&ptr);
esp_sysview_decode_u32(&ptr);
esp_sysview_decode_u32(&ptr);
esp_sysview_decode_u32(&ptr);
len = ptr - pkt;
break;
case SYSVIEW_EVTID_ISR_EXIT:
case SYSVIEW_EVTID_TASK_STOP_EXEC:
case SYSVIEW_EVTID_TRACE_START:
case SYSVIEW_EVTID_TRACE_STOP:
case SYSVIEW_EVTID_IDLE:
case SYSVIEW_EVTID_ISR_TO_SCHEDULER:
case SYSVIEW_EVTID_TIMER_EXIT:
len = 0;
break;
/*case SYSVIEW_EVTID_NOP: */
default:
LOG_ERROR("sysview: Unsupported predef event %d!", id);
len = 0;
}
return len;
}
static uint16_t esp_sysview_parse_packet(uint8_t *pkt_buf,
uint32_t *pkt_len,
unsigned int *pkt_core_id,
uint32_t *delta,
uint32_t *delta_len,
bool clear_core_bit)
{
uint8_t *pkt = pkt_buf;
uint16_t event_id = 0, payload_len = 0;
*pkt_core_id = 0;
*pkt_len = 0;
/* 1-2 byte of message type, 0-2 byte of payload length, payload, 1-5 bytes of timestamp. */
if (*pkt & 0x80) {
if (*(pkt + 1) & (1 << 6)) {
if (clear_core_bit)
*(pkt + 1) &= ~(1 << 6); /* clear core_id bit */
*pkt_core_id = 1;
}
event_id = *(pkt + 1) & ~(1 << 6); /* higher part */
event_id = (event_id << 7) | (*pkt & ~0x80); /* lower 7 bits */
pkt += 2; /* event_id (2 bytes) */
/* here pkt points to encoded payload length */
payload_len = esp_sysview_decode_plen(&pkt);
} else {
if (*pkt & (1 << 6)) {
if (clear_core_bit)
*pkt &= ~(1 << 6); /* clear core_id bit */
*pkt_core_id = 1;
}
/* event_id (1 byte) */
event_id = *pkt & ~(1 << 6);
pkt++;
if (event_id < 24)
payload_len = esp_sysview_get_predef_payload_len(event_id, pkt);
else
payload_len = esp_sysview_decode_plen(&pkt);
}
pkt += payload_len;
uint8_t *delta_start = pkt;
*delta = esp_sysview_decode_u32(&pkt);
*delta_len = pkt - delta_start;
*pkt_len = pkt - pkt_buf;
LOG_DEBUG("sysview: evt %d len %d plen %d dlen %d",
event_id,
*pkt_len,
payload_len,
*delta_len);
return event_id;
}
static int esp32_sysview_write_packet(struct esp32_sysview_cmd_data *cmd_data,
int pkt_core_id, uint32_t pkt_len, uint8_t *pkt_buf, uint32_t delta_len, uint8_t *delta_buf)
{
if (!cmd_data->data_dests[pkt_core_id].write)
return ERROR_FAIL;
int res = cmd_data->data_dests[pkt_core_id].write(cmd_data->data_dests[pkt_core_id].priv, pkt_buf, pkt_len);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", pkt_len, pkt_core_id);
return res;
}
if (delta_len) {
/* write packet with modified delta */
res = cmd_data->data_dests[pkt_core_id].write(cmd_data->data_dests[pkt_core_id].priv, delta_buf, delta_len);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u bytes of delta to dest %d!", delta_len, pkt_core_id);
return res;
}
}
return ERROR_OK;
}
static int esp32_sysview_process_packet(struct esp32_apptrace_cmd_ctx *ctx,
unsigned int pkt_core_id, uint16_t event_id, uint32_t delta, uint32_t delta_len,
uint32_t pkt_len, uint8_t *pkt_buf)
{
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
int pkt_core_changed = 0;
uint32_t new_delta_len = 0;
uint8_t new_delta_buf[10];
uint32_t wr_len = pkt_len;
if (ctx->cores_num > 1) {
if (cmd_data->sv_last_core_id == pkt_core_id) {
/* if this packet is for the same core as the prev one acc delta and write packet unmodified */
cmd_data->sv_acc_time_delta += delta;
} else {
/* if this packet is for another core then prev one set acc delta to the packet's delta */
uint8_t *delta_ptr = new_delta_buf;
sysview_encode_u32(&delta_ptr, delta + cmd_data->sv_acc_time_delta);
cmd_data->sv_acc_time_delta = delta;
wr_len -= delta_len;
new_delta_len = delta_ptr - new_delta_buf;
pkt_core_changed = 1;
}
cmd_data->sv_last_core_id = pkt_core_id;
}
if (pkt_core_id >= ctx->cores_num) {
LOG_WARNING("sysview: invalid core ID in packet %d, must be less then %d! Event id %d",
pkt_core_id,
ctx->cores_num,
event_id);
return ERROR_FAIL;
}
int res = esp32_sysview_write_packet(cmd_data,
pkt_core_id,
wr_len,
pkt_buf,
new_delta_len,
new_delta_buf);
if (res != ERROR_OK)
return res;
for (unsigned int i = 0; i < ctx->cores_num; i++) {
if (pkt_core_id == i)
continue;
switch (event_id) {
/* messages below should be sent to trace destinations for all cores */
case SYSVIEW_EVTID_TRACE_START:
case SYSVIEW_EVTID_TRACE_STOP:
case SYSVIEW_EVTID_SYSTIME_CYCLES:
case SYSVIEW_EVTID_SYSTIME_US:
case SYSVIEW_EVTID_SYSDESC:
case SYSVIEW_EVTID_TASK_INFO:
case SYSVIEW_EVTID_STACK_INFO:
case SYSVIEW_EVTID_MODULEDESC:
case SYSVIEW_EVTID_INIT:
case SYSVIEW_EVTID_NUMMODULES:
case SYSVIEW_EVTID_OVERFLOW:
case SYSVIEW_EVTID_TASK_START_READY:
/* if packet's source core has changed */
wr_len = pkt_len;
if (pkt_core_changed) {
/* clone packet with unmodified delta */
new_delta_len = 0;
} else {
/* clone packet with modified delta */
uint8_t *delta_ptr = new_delta_buf;
sysview_encode_u32(&delta_ptr, cmd_data->sv_acc_time_delta /*delta has been accumulated above*/);
wr_len -= delta_len;
new_delta_len = delta_ptr - new_delta_buf;
}
LOG_DEBUG("sysview: Redirect %d bytes of event %d to dest %d", wr_len, event_id, i);
res = esp32_sysview_write_packet(cmd_data,
i,
wr_len,
pkt_buf,
new_delta_len,
new_delta_buf);
if (res != ERROR_OK)
return res;
/* messages above are cloned to trace files for both cores,
* so reset acc time delta, both files have actual delta
* info */
cmd_data->sv_acc_time_delta = 0;
break;
default:
break;
}
}
return ERROR_OK;
}
int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx *ctx,
unsigned int core_id,
uint8_t *data,
uint32_t data_len)
{
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
LOG_DEBUG("sysview: Read from target %d bytes [%x %x %x %x]",
data_len,
data[0],
data[1],
data[2],
data[3]);
int res;
uint32_t processed = 0;
if (core_id >= ctx->cores_num) {
LOG_ERROR("sysview: Invalid core id %d in user block!", core_id);
return ERROR_FAIL;
}
if (cmd_data->mcore_format)
core_id = 0;
if (ctx->tot_len == 0) {
/* handle sync seq */
if (data_len < SYSVIEW_SYNC_LEN) {
LOG_ERROR("sysview: Invalid init seq len %d!", data_len);
return ERROR_FAIL;
}
LOG_DEBUG("sysview: Process %d sync bytes", SYSVIEW_SYNC_LEN);
uint8_t sync_seq[SYSVIEW_SYNC_LEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
if (memcmp(data, sync_seq, SYSVIEW_SYNC_LEN) != 0) {
LOG_ERROR("sysview: Invalid init seq [%x %x %x %x %x %x %x %x %x %x]",
data[0], data[1], data[2], data[3], data[4], data[5], data[6],
data[7], data[8], data[9]);
return ERROR_FAIL;
}
res = cmd_data->data_dests[core_id].write(cmd_data->data_dests[core_id].priv,
data,
SYSVIEW_SYNC_LEN);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u sync bytes to dest %d!",
SYSVIEW_SYNC_LEN,
core_id);
return res;
}
if (!cmd_data->mcore_format) {
for (unsigned int i = 0; i < ctx->cores_num; i++) {
if (core_id == i)
continue;
res =
cmd_data->data_dests[i].write(cmd_data->data_dests[i].priv,
data,
SYSVIEW_SYNC_LEN);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u sync bytes to dest %d!", SYSVIEW_SYNC_LEN, core_id ? 0 : 1);
return res;
}
}
}
ctx->tot_len += SYSVIEW_SYNC_LEN;
processed += SYSVIEW_SYNC_LEN;
}
while (processed < data_len) {
unsigned int pkt_core_id;
uint32_t delta_len = 0;
uint32_t pkt_len = 0, delta = 0;
uint16_t event_id = esp_sysview_parse_packet(data + processed,
&pkt_len,
&pkt_core_id,
&delta,
&delta_len,
!cmd_data->mcore_format);
LOG_DEBUG("sysview: Process packet: core %d, %d id, %d bytes [%x %x %x %x]",
pkt_core_id,
event_id,
pkt_len,
data[processed + 0],
data[processed + 1],
data[processed + 2],
data[processed + 3]);
if (!cmd_data->mcore_format) {
res = esp32_sysview_process_packet(ctx,
pkt_core_id,
event_id,
delta,
delta_len,
pkt_len,
data + processed);
if (res != ERROR_OK)
return res;
} else {
res = cmd_data->data_dests[0].write(cmd_data->data_dests[0].priv, data + processed, pkt_len);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", pkt_len, 0);
return res;
}
}
if (event_id == SYSVIEW_EVTID_TRACE_STOP)
cmd_data->sv_trace_running = 0;
ctx->tot_len += pkt_len;
processed += pkt_len;
}
LOG_USER("%u ", ctx->tot_len);
/* check for stop condition */
if (ctx->tot_len > cmd_data->apptrace.skip_len &&
(ctx->tot_len - cmd_data->apptrace.skip_len >= cmd_data->apptrace.max_len)) {
ctx->running = 0;
if (duration_measure(&ctx->read_time) != 0) {
LOG_ERROR("Failed to stop trace read time measure!");
return ERROR_FAIL;
}
}
return ERROR_OK;
}

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* ESP32 sysview tracing module *
* Copyright (C) 2020 Espressif Systems Ltd. *
***************************************************************************/
#ifndef OPENOCD_TARGET_ESP32_SYSVIEW_H
#define OPENOCD_TARGET_ESP32_SYSVIEW_H
#include <stdint.h>
#include "esp32_apptrace.h"
struct esp32_sysview_cmd_data {
/* Should be the first field. Generic apptrace command handling code accesses it */
struct esp32_apptrace_cmd_data apptrace;
struct esp32_apptrace_dest data_dests[ESP32_APPTRACE_MAX_CORES_NUM];
bool mcore_format;
uint32_t sv_acc_time_delta;
unsigned int sv_last_core_id;
int sv_trace_running;
};
struct esp32_apptrace_cmd_ctx;
int esp32_sysview_cmd_init(struct esp32_apptrace_cmd_ctx *cmd_ctx,
struct command_invocation *cmd,
int mode,
bool mcore_format,
const char **argv,
int argc);
int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx);
int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx *ctx,
unsigned int core_id,
uint8_t *data,
uint32_t data_len);
#endif /* OPENOCD_TARGET_ESP32_SYSVIEW_H */

View File

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: BSD-1-Clause */
/* SPDX-FileCopyrightText: (c) 1995-2021 SEGGER Microcontroller GmbH. All rights reserved. */
/* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD */
/*
* The contend below is extracted from files SEGGER_SYSVIEW.h and SEGGER_SYSVIEW_Int.h in:
* https://www.segger.com/downloads/systemview/systemview_target_src
* SystemView version: 3.42
*/
#ifndef OPENOCD_TARGET_SEGGER_SYSVIEW_H
#define OPENOCD_TARGET_SEGGER_SYSVIEW_H
#define SYSVIEW_EVTID_NOP 0 /* Dummy packet. */
#define SYSVIEW_EVTID_OVERFLOW 1
#define SYSVIEW_EVTID_ISR_ENTER 2
#define SYSVIEW_EVTID_ISR_EXIT 3
#define SYSVIEW_EVTID_TASK_START_EXEC 4
#define SYSVIEW_EVTID_TASK_STOP_EXEC 5
#define SYSVIEW_EVTID_TASK_START_READY 6
#define SYSVIEW_EVTID_TASK_STOP_READY 7
#define SYSVIEW_EVTID_TASK_CREATE 8
#define SYSVIEW_EVTID_TASK_INFO 9
#define SYSVIEW_EVTID_TRACE_START 10
#define SYSVIEW_EVTID_TRACE_STOP 11
#define SYSVIEW_EVTID_SYSTIME_CYCLES 12
#define SYSVIEW_EVTID_SYSTIME_US 13
#define SYSVIEW_EVTID_SYSDESC 14
#define SYSVIEW_EVTID_USER_START 15
#define SYSVIEW_EVTID_USER_STOP 16
#define SYSVIEW_EVTID_IDLE 17
#define SYSVIEW_EVTID_ISR_TO_SCHEDULER 18
#define SYSVIEW_EVTID_TIMER_ENTER 19
#define SYSVIEW_EVTID_TIMER_EXIT 20
#define SYSVIEW_EVTID_STACK_INFO 21
#define SYSVIEW_EVTID_MODULEDESC 22
#define SYSVIEW_EVTID_INIT 24
#define SYSVIEW_EVTID_NAME_RESOURCE 25
#define SYSVIEW_EVTID_PRINT_FORMATTED 26
#define SYSVIEW_EVTID_NUMMODULES 27
#define SYSVIEW_EVTID_END_CALL 28
#define SYSVIEW_EVTID_TASK_TERMINATE 29
#define SYSVIEW_EVTID_EX 31
//
// SystemView extended events. Sent with ID 31.
//
#define SYSVIEW_EVTID_EX_MARK 0
#define SYSVIEW_EVTID_EX_NAME_MARKER 1
#define SYSVIEW_EVTID_EX_HEAP_DEFINE 2
#define SYSVIEW_EVTID_EX_HEAP_ALLOC 3
#define SYSVIEW_EVTID_EX_HEAP_ALLOC_EX 4
#define SYSVIEW_EVTID_EX_HEAP_FREE 5
#define SYSVIEW_SYNC_LEN 10
#define SYSVIEW_EVENT_ID_MAX (200)
//
// Commands that Host can send to target
//
enum {
SEGGER_SYSVIEW_COMMAND_ID_START = 1,
SEGGER_SYSVIEW_COMMAND_ID_STOP,
SEGGER_SYSVIEW_COMMAND_ID_GET_SYSTIME,
SEGGER_SYSVIEW_COMMAND_ID_GET_TASKLIST,
SEGGER_SYSVIEW_COMMAND_ID_GET_SYSDESC,
SEGGER_SYSVIEW_COMMAND_ID_GET_NUMMODULES,
SEGGER_SYSVIEW_COMMAND_ID_GET_MODULEDESC,
SEGGER_SYSVIEW_COMMAND_ID_HEARTBEAT = 127,
// Extended commands: Commands >= 128 have a second parameter
SEGGER_SYSVIEW_COMMAND_ID_GET_MODULE = 128
};
/* Minimum compatible SEGGER SystemView tool version */
#define SYSVIEW_MIN_VER_STRING "SEGGER SystemViewer V2.42"
#endif

View File

@ -407,10 +407,12 @@ static int image_elf32_read_headers(struct image *image)
return ERROR_FILEIO_OPERATION_FAILED;
}
/* count useful segments (loadable) */
/* count useful segments (loadable), ignore BSS section */
image->num_sections = 0;
for (i = 0; i < elf->segment_count; i++)
if (field32(elf, elf->segments32[i].p_type) == PT_LOAD)
if ((field32(elf,
elf->segments32[i].p_type) == PT_LOAD) &&
(field32(elf, elf->segments32[i].p_filesz) != 0))
image->num_sections++;
if (image->num_sections == 0) {
@ -447,8 +449,10 @@ static int image_elf32_read_headers(struct image *image)
}
for (i = 0, j = 0; i < elf->segment_count; i++) {
if (field32(elf, elf->segments32[i].p_type) == PT_LOAD) {
image->sections[j].size = field32(elf, elf->segments32[i].p_memsz);
if ((field32(elf,
elf->segments32[i].p_type) == PT_LOAD) &&
(field32(elf, elf->segments32[i].p_filesz) != 0)) {
image->sections[j].size = field32(elf, elf->segments32[i].p_filesz);
if (load_to_vaddr)
image->sections[j].base_address = field32(elf,
elf->segments32[i].p_vaddr);
@ -528,10 +532,12 @@ static int image_elf64_read_headers(struct image *image)
return ERROR_FILEIO_OPERATION_FAILED;
}
/* count useful segments (loadable) */
/* count useful segments (loadable), ignore BSS section */
image->num_sections = 0;
for (i = 0; i < elf->segment_count; i++)
if (field32(elf, elf->segments64[i].p_type) == PT_LOAD)
if ((field32(elf,
elf->segments64[i].p_type) == PT_LOAD) &&
(field64(elf, elf->segments64[i].p_filesz) != 0))
image->num_sections++;
if (image->num_sections == 0) {
@ -568,8 +574,10 @@ static int image_elf64_read_headers(struct image *image)
}
for (i = 0, j = 0; i < elf->segment_count; i++) {
if (field32(elf, elf->segments64[i].p_type) == PT_LOAD) {
image->sections[j].size = field64(elf, elf->segments64[i].p_memsz);
if ((field32(elf,
elf->segments64[i].p_type) == PT_LOAD) &&
(field64(elf, elf->segments64[i].p_filesz) != 0)) {
image->sections[j].size = field64(elf, elf->segments64[i].p_filesz);
if (load_to_vaddr)
image->sections[j].base_address = field64(elf,
elf->segments64[i].p_vaddr);
@ -643,8 +651,6 @@ static int image_elf32_read_section(struct image *image,
{
struct image_elf *elf = image->type_private;
Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
uint32_t filesz = field32(elf, segment->p_filesz);
uint32_t memsz = field32(elf, segment->p_memsz);
size_t read_size, really_read;
int retval;
@ -653,9 +659,9 @@ static int image_elf32_read_section(struct image *image,
LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
/* read initialized data in current segment if any */
if (offset < filesz) {
if (offset < field32(elf, segment->p_filesz)) {
/* maximal size present in file for the current segment */
read_size = MIN(size, filesz - offset);
read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
field32(elf, segment->p_offset) + offset);
/* read initialized area of the segment */
@ -669,8 +675,6 @@ static int image_elf32_read_section(struct image *image,
LOG_ERROR("cannot read ELF segment content, read failed");
return retval;
}
buffer += read_size;
offset += read_size;
size -= read_size;
*size_read += read_size;
/* need more data ? */
@ -678,13 +682,6 @@ static int image_elf32_read_section(struct image *image,
return ERROR_OK;
}
/* clear bss in current segment if any */
if (offset >= filesz) {
uint32_t memset_size = MIN(size, memsz - filesz);
memset(buffer, 0, memset_size);
*size_read += memset_size;
}
return ERROR_OK;
}
@ -697,8 +694,6 @@ static int image_elf64_read_section(struct image *image,
{
struct image_elf *elf = image->type_private;
Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private;
uint64_t filesz = field64(elf, segment->p_filesz);
uint64_t memsz = field64(elf, segment->p_memsz);
size_t read_size, really_read;
int retval;
@ -707,9 +702,9 @@ static int image_elf64_read_section(struct image *image,
LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
/* read initialized data in current segment if any */
if (offset < filesz) {
if (offset < field64(elf, segment->p_filesz)) {
/* maximal size present in file for the current segment */
read_size = MIN(size, filesz - offset);
read_size = MIN(size, field64(elf, segment->p_filesz) - offset);
LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
field64(elf, segment->p_offset) + offset);
/* read initialized area of the segment */
@ -723,8 +718,6 @@ static int image_elf64_read_section(struct image *image,
LOG_ERROR("cannot read ELF segment content, read failed");
return retval;
}
buffer += read_size;
offset += read_size;
size -= read_size;
*size_read += read_size;
/* need more data ? */
@ -732,13 +725,6 @@ static int image_elf64_read_section(struct image *image,
return ERROR_OK;
}
/* clear bss in current segment if any */
if (offset >= filesz) {
uint64_t memset_size = MIN(size, memsz - filesz);
memset(buffer, 0, memset_size);
*size_read += memset_size;
}
return ERROR_OK;
}

View File

@ -384,7 +384,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s
/* run to exit point. return error if exit point was not reached. */
static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32)
unsigned int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32)
{
uint32_t pc;
int retval;
@ -418,7 +418,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
int mips32_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point,
target_addr_t exit_point, int timeout_ms, void *arch_info)
target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
{
struct mips32_common *mips32 = target_to_mips32(target);
struct mips32_algorithm *mips32_algorithm_info = arch_info;
@ -803,7 +803,7 @@ int mips32_checksum_memory(struct target *target, target_addr_t address,
init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
int timeout = 20000 * (1 + (count / (1024 * 1024)));
unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);

View File

@ -400,7 +400,7 @@ int mips32_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
int mips32_configure_break_unit(struct target *target);

View File

@ -459,7 +459,7 @@ int mips64_init_arch_info(struct target *target, struct mips64_common *mips64,
int mips64_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point,
target_addr_t exit_point, int timeout_ms, void *arch_info)
target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
{
/* TODO */
return ERROR_OK;

View File

@ -213,7 +213,7 @@ int mips64_build_reg_cache(struct target *target);
int mips64_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_params,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
int mips64_configure_break_unit(struct target *target);
int mips64_enable_interrupts(struct target *target, bool enable);
int mips64_examine(struct target *target);

View File

@ -2573,7 +2573,7 @@ static int riscv_arch_state(struct target *target)
static int riscv_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point,
target_addr_t exit_point, int timeout_ms, void *arch_info)
target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
{
RISCV_INFO(info);

View File

@ -39,6 +39,7 @@
#include <helper/binarybuffer.h>
#include <helper/log.h>
#include <server/gdb_server.h>
#include <sys/stat.h>
/**
@ -92,9 +93,6 @@ static int semihosting_common_fileio_info(struct target *target,
static int semihosting_common_fileio_end(struct target *target, int result,
int fileio_errno, bool ctrl_c);
/* Attempts to include gdb_server.h failed. */
extern int gdb_actual_connections;
/**
* Initialize common semihosting support.
*
@ -493,7 +491,7 @@ int semihosting_common(struct target *target)
int code = semihosting_get_field(target, 1, fields);
if (type == ADP_STOPPED_APPLICATION_EXIT) {
if (!gdb_actual_connections)
if (!gdb_get_actual_connections())
exit(code);
else {
fprintf(stderr,
@ -508,7 +506,7 @@ int semihosting_common(struct target *target)
}
} else {
if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
if (!gdb_actual_connections)
if (!gdb_get_actual_connections())
exit(0);
else {
fprintf(stderr,
@ -517,14 +515,14 @@ int semihosting_common(struct target *target)
} else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
/* Chosen more or less arbitrarily to have a nicer message,
* otherwise all other return the same exit code 1. */
if (!gdb_actual_connections)
if (!gdb_get_actual_connections())
exit(1);
else {
fprintf(stderr,
"semihosting: *** application exited with error ***\n");
}
} else {
if (!gdb_actual_connections)
if (!gdb_get_actual_connections())
exit(1);
else {
fprintf(stderr,
@ -584,7 +582,7 @@ int semihosting_common(struct target *target)
int code = semihosting_get_field(target, 1, fields);
if (type == ADP_STOPPED_APPLICATION_EXIT) {
if (!gdb_actual_connections)
if (!gdb_get_actual_connections())
exit(code);
else {
fprintf(stderr,
@ -781,7 +779,8 @@ int semihosting_common(struct target *target)
if (retval != ERROR_OK)
return retval;
int fd = semihosting_get_field(target, 0, fields);
semihosting->result = isatty(fd);
// isatty() on Windows may return any non-zero value if fd is a terminal
semihosting->result = isatty(fd) ? 1 : 0;
semihosting->sys_errno = errno;
LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
}

View File

@ -1784,7 +1784,7 @@ static int stm8_checksum_memory(struct target *target, target_addr_t address,
/* run to exit point. return error if exit point was not reached. */
static int stm8_run_and_wait(struct target *target, uint32_t entry_point,
int timeout_ms, uint32_t exit_point, struct stm8_common *stm8)
unsigned int timeout_ms, uint32_t exit_point, struct stm8_common *stm8)
{
uint32_t pc;
int retval;
@ -1819,7 +1819,7 @@ static int stm8_run_and_wait(struct target *target, uint32_t entry_point,
static int stm8_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point,
target_addr_t exit_point, int timeout_ms, void *arch_info)
target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
{
struct stm8_common *stm8 = target_to_stm8(target);

View File

@ -210,7 +210,7 @@ static const struct jim_nvp nvp_target_event[] = {
{ .name = NULL, .value = -1 }
};
static const struct jim_nvp nvp_target_state[] = {
static const struct nvp nvp_target_state[] = {
{ .name = "unknown", .value = TARGET_UNKNOWN },
{ .name = "running", .value = TARGET_RUNNING },
{ .name = "halted", .value = TARGET_HALTED },
@ -265,7 +265,7 @@ const char *debug_reason_name(struct target *t)
const char *target_state_name(struct target *t)
{
const char *cp;
cp = jim_nvp_value2name_simple(nvp_target_state, t->state)->name;
cp = nvp_value2name(nvp_target_state, t->state)->name;
if (!cp) {
LOG_ERROR("Invalid target state: %d", (int)(t->state));
cp = "(*BUG*unknown*BUG*)";
@ -819,7 +819,7 @@ int target_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_param,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info)
unsigned int timeout_ms, void *arch_info)
{
int retval = ERROR_FAIL;
@ -903,7 +903,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,
target_addr_t exit_point, int timeout_ms,
target_addr_t exit_point, unsigned int timeout_ms,
void *arch_info)
{
int retval = ERROR_FAIL;
@ -3230,7 +3230,7 @@ COMMAND_HANDLER(handle_wait_halt_command)
*
* After 500ms, keep_alive() is invoked
*/
int target_wait_state(struct target *target, enum target_state state, int ms)
int target_wait_state(struct target *target, enum target_state state, unsigned int ms)
{
int retval;
int64_t then = 0, cur;
@ -3247,7 +3247,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms)
once = false;
then = timeval_ms();
LOG_DEBUG("waiting for target %s...",
jim_nvp_value2name_simple(nvp_target_state, state)->name);
nvp_value2name(nvp_target_state, state)->name);
}
if (cur-then > 500)
@ -3255,7 +3255,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms)
if ((cur-then) > ms) {
LOG_ERROR("timed out while waiting for target %s",
jim_nvp_value2name_simple(nvp_target_state, state)->name);
nvp_value2name(nvp_target_state, state)->name);
return ERROR_FAIL;
}
}
@ -5635,55 +5635,40 @@ static int jim_target_array2mem(Jim_Interp *interp,
return target_array2mem(interp, target, argc - 1, argv + 1);
}
static int jim_target_tap_disabled(Jim_Interp *interp)
{
Jim_SetResultFormatted(interp, "[TAP is disabled]");
return JIM_ERR;
}
static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
COMMAND_HANDLER(handle_target_examine)
{
bool allow_defer = false;
struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
if (goi.argc > 1) {
const char *cmd_name = Jim_GetString(argv[0], NULL);
Jim_SetResultFormatted(goi.interp,
"usage: %s ['allow-defer']", cmd_name);
return JIM_ERR;
}
if (goi.argc > 0 &&
strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) {
/* consume it */
Jim_Obj *obj;
int e = jim_getopt_obj(&goi, &obj);
if (e != JIM_OK)
return e;
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 1) {
if (strcmp(CMD_ARGV[0], "allow-defer"))
return ERROR_COMMAND_ARGUMENT_INVALID;
allow_defer = true;
}
struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled)
return jim_target_tap_disabled(interp);
struct target *target = get_current_target(CMD_CTX);
if (!target->tap->enabled) {
command_print(CMD, "[TAP is disabled]");
return ERROR_FAIL;
}
if (allow_defer && target->defer_examine) {
LOG_INFO("Deferring arp_examine of %s", target_name(target));
LOG_INFO("Use arp_examine command to examine it manually!");
return JIM_OK;
return ERROR_OK;
}
int e = target->type->examine(target);
if (e != ERROR_OK) {
int retval = target->type->examine(target);
if (retval != ERROR_OK) {
target_reset_examined(target);
return JIM_ERR;
return retval;
}
target_set_examined(target);
return JIM_OK;
return ERROR_OK;
}
COMMAND_HANDLER(handle_target_was_examined)
@ -5791,45 +5776,35 @@ COMMAND_HANDLER(handle_target_halt)
return target->type->halt(target);
}
static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
COMMAND_HANDLER(handle_target_wait_state)
{
struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
/* params: <name> statename timeoutmsecs */
if (goi.argc != 2) {
const char *cmd_name = Jim_GetString(argv[0], NULL);
Jim_SetResultFormatted(goi.interp,
"%s <state_name> <timeout_in_msec>", cmd_name);
return JIM_ERR;
const struct nvp *n = nvp_name2value(nvp_target_state, CMD_ARGV[0]);
if (!n->name) {
nvp_unknown_command_print(CMD, nvp_target_state, NULL, CMD_ARGV[0]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
struct jim_nvp *n;
int e = jim_getopt_nvp(&goi, nvp_target_state, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(&goi, nvp_target_state, 1);
return e;
}
jim_wide a;
e = jim_getopt_wide(&goi, &a);
if (e != JIM_OK)
return e;
struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled)
return jim_target_tap_disabled(interp);
unsigned int a;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], a);
e = target_wait_state(target, n->value, a);
if (e != ERROR_OK) {
Jim_Obj *obj = Jim_NewIntObj(interp, e);
Jim_SetResultFormatted(goi.interp,
"target: %s wait %s fails (%#s) %s",
struct target *target = get_current_target(CMD_CTX);
if (!target->tap->enabled) {
command_print(CMD, "[TAP is disabled]");
return ERROR_FAIL;
}
int retval = target_wait_state(target, n->value, a);
if (retval != ERROR_OK) {
command_print(CMD,
"target: %s wait %s fails (%d) %s",
target_name(target), n->name,
obj, target_strerror_safe(e));
return JIM_ERR;
retval, target_strerror_safe(retval));
return retval;
}
return JIM_OK;
return ERROR_OK;
}
/* List for human, Events defined for this target.
* scripts/programs should use 'name cget -event NAME'
@ -6021,7 +5996,7 @@ static const struct command_registration target_instance_command_handlers[] = {
{
.name = "arp_examine",
.mode = COMMAND_EXEC,
.jim_handler = jim_target_examine,
.handler = handle_target_examine,
.help = "used internally for reset processing",
.usage = "['allow-defer']",
},
@ -6070,8 +6045,9 @@ static const struct command_registration target_instance_command_handlers[] = {
{
.name = "arp_waitstate",
.mode = COMMAND_EXEC,
.jim_handler = jim_target_wait_state,
.handler = handle_target_wait_state,
.help = "used internally for reset processing",
.usage = "statename timeoutmsecs",
},
{
.name = "invoke-event",
@ -7173,3 +7149,29 @@ static int target_register_user_commands(struct command_context *cmd_ctx)
return register_commands(cmd_ctx, NULL, target_exec_command_handlers);
}
const char *target_debug_reason_str(enum target_debug_reason reason)
{
switch (reason) {
case DBG_REASON_DBGRQ:
return "DBGRQ";
case DBG_REASON_BREAKPOINT:
return "BREAKPOINT";
case DBG_REASON_WATCHPOINT:
return "WATCHPOINT";
case DBG_REASON_WPTANDBKPT:
return "WPTANDBKPT";
case DBG_REASON_SINGLESTEP:
return "SINGLESTEP";
case DBG_REASON_NOTHALTED:
return "NOTHALTED";
case DBG_REASON_EXIT:
return "EXIT";
case DBG_REASON_EXC_CATCH:
return "EXC_CATCH";
case DBG_REASON_UNDEFINED:
return "UNDEFINED";
default:
return "UNKNOWN!";
}
}

View File

@ -553,7 +553,7 @@ int target_run_algorithm(struct target *target,
int num_mem_params, struct mem_param *mem_params,
int num_reg_params, struct reg_param *reg_param,
target_addr_t entry_point, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
/**
* Starts an algorithm in the background on the @a target given.
@ -574,7 +574,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,
target_addr_t exit_point, int timeout_ms,
target_addr_t exit_point, unsigned int timeout_ms,
void *arch_info);
/**
@ -666,7 +666,7 @@ int target_checksum_memory(struct target *target,
int target_blank_check_memory(struct target *target,
struct target_memory_check_block *blocks, int num_blocks,
uint8_t erased_value);
int target_wait_state(struct target *target, enum target_state state, int ms);
int target_wait_state(struct target *target, enum target_state state, unsigned int ms);
/**
* Obtain file-I/O information from target for GDB to do syscall.
@ -809,4 +809,6 @@ extern bool get_target_reset_nag(void);
#define TARGET_DEFAULT_POLLING_INTERVAL 100
const char *target_debug_reason_str(enum target_debug_reason reason);
#endif /* OPENOCD_TARGET_TARGET_H */

View File

@ -181,7 +181,7 @@ struct target_type {
int (*run_algorithm)(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_param, target_addr_t entry_point,
target_addr_t exit_point, int timeout_ms, void *arch_info);
target_addr_t exit_point, unsigned int timeout_ms, void *arch_info);
int (*start_algorithm)(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_param, target_addr_t entry_point,
@ -189,7 +189,7 @@ struct target_type {
int (*wait_algorithm)(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_param, target_addr_t exit_point,
int timeout_ms, void *arch_info);
unsigned int timeout_ms, void *arch_info);
const struct command_registration *commands;

View File

@ -8,4 +8,6 @@ noinst_LTLIBRARIES += %D%/libxtensa.la
%D%/xtensa_chip.h \
%D%/xtensa_debug_module.c \
%D%/xtensa_debug_module.h \
%D%/xtensa_fileio.c \
%D%/xtensa_fileio.h \
%D%/xtensa_regs.h

View File

@ -1544,6 +1544,7 @@ int xtensa_prepare_resume(struct target *target,
LOG_TARGET_WARNING(target, "target not halted");
return ERROR_TARGET_NOT_HALTED;
}
xtensa->halt_request = false;
if (address && !current) {
xtensa_reg_set(target, XT_REG_IDX_PC, address);

View File

@ -15,6 +15,7 @@
#include <target/arm_adi_v5.h>
#include <rtos/rtos.h>
#include "xtensa_chip.h"
#include "xtensa_fileio.h"
int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
struct xtensa_debug_module_config *dm_cfg)
@ -30,7 +31,10 @@ int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target *target)
{
return xtensa_target_init(cmd_ctx, target);
int ret = xtensa_target_init(cmd_ctx, target);
if (ret != ERROR_OK)
return ret;
return xtensa_fileio_init(target);
}
int xtensa_chip_arch_state(struct target *target)
@ -45,10 +49,12 @@ static int xtensa_chip_poll(struct target *target)
if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
/*Call any event callbacks that are applicable */
if (old_state == TARGET_DEBUG_RUNNING)
if (old_state == TARGET_DEBUG_RUNNING) {
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
else
} else {
xtensa_fileio_detect_proc(target);
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
}
return ret;
@ -193,4 +199,7 @@ struct target_type xtensa_chip_target = {
.gdb_query_custom = xtensa_gdb_query_custom,
.commands = xtensa_command_handlers,
.get_gdb_fileio_info = xtensa_get_gdb_fileio_info,
.gdb_fileio_end = xtensa_gdb_fileio_end,
};

View File

@ -0,0 +1,195 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Xtensa Target File-I/O Support for OpenOCD *
* Copyright (C) 2020-2023 Cadence Design Systems, Inc. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xtensa_chip.h"
#include "xtensa_fileio.h"
#include "xtensa.h"
#define XTENSA_SYSCALL(x) XT_INS_BREAK(x, 1, 14)
#define XTENSA_SYSCALL_SZ 3
#define XTENSA_SYSCALL_LEN_MAX 255
int xtensa_fileio_init(struct target *target)
{
char *idmem = malloc(XTENSA_SYSCALL_LEN_MAX + 1);
target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
if (!idmem || !target->fileio_info) {
LOG_TARGET_ERROR(target, "Out of memory!");
free(idmem);
free(target->fileio_info);
return ERROR_FAIL;
}
target->fileio_info->identifier = idmem;
return ERROR_OK;
}
/**
* Checks for and processes an Xtensa File-IO request.
*
* Return ERROR_OK if request was found and handled; or
* return ERROR_FAIL if no request was detected.
*/
int xtensa_fileio_detect_proc(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
int retval;
xtensa_reg_val_t dbg_cause = xtensa_cause_get(target);
if ((dbg_cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) == 0 || xtensa->halt_request)
return ERROR_FAIL;
uint8_t brk_insn_buf[sizeof(uint32_t)] = {0};
xtensa_reg_val_t pc = xtensa_reg_get(target, XT_REG_IDX_PC);
retval = target_read_memory(target,
pc,
XTENSA_SYSCALL_SZ,
1,
(uint8_t *)brk_insn_buf);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read break instruction!");
return ERROR_FAIL;
}
if (buf_get_u32(brk_insn_buf, 0, 32) != XTENSA_SYSCALL(xtensa))
return ERROR_FAIL;
LOG_TARGET_DEBUG(target, "File-I/O: syscall breakpoint found at 0x%x", pc);
xtensa->proc_syscall = true;
return ERROR_OK;
}
int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
{
/* fill syscall parameters to file-I/O info */
if (!fileio_info) {
LOG_ERROR("File-I/O data structure uninitialized");
return ERROR_FAIL;
}
struct xtensa *xtensa = target_to_xtensa(target);
if (!xtensa->proc_syscall)
return ERROR_FAIL;
xtensa_reg_val_t syscall = xtensa_reg_get(target, XTENSA_SYSCALL_OP_REG);
xtensa_reg_val_t arg0 = xtensa_reg_get(target, XT_REG_IDX_A6);
xtensa_reg_val_t arg1 = xtensa_reg_get(target, XT_REG_IDX_A3);
xtensa_reg_val_t arg2 = xtensa_reg_get(target, XT_REG_IDX_A4);
xtensa_reg_val_t arg3 = xtensa_reg_get(target, XT_REG_IDX_A5);
int retval = ERROR_OK;
LOG_TARGET_DEBUG(target, "File-I/O: syscall 0x%x 0x%x 0x%x 0x%x 0x%x",
syscall, arg0, arg1, arg2, arg3);
switch (syscall) {
case XTENSA_SYSCALL_OPEN:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "open");
fileio_info->param_1 = arg0; // pathp
fileio_info->param_2 = arg3; // len
fileio_info->param_3 = arg1; // flags
fileio_info->param_4 = arg2; // mode
break;
case XTENSA_SYSCALL_CLOSE:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "close");
fileio_info->param_1 = arg0; // fd
break;
case XTENSA_SYSCALL_READ:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "read");
fileio_info->param_1 = arg0; // fd
fileio_info->param_2 = arg1; // bufp
fileio_info->param_3 = arg2; // count
break;
case XTENSA_SYSCALL_WRITE:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "write");
fileio_info->param_1 = arg0; // fd
fileio_info->param_2 = arg1; // bufp
fileio_info->param_3 = arg2; // count
break;
case XTENSA_SYSCALL_LSEEK:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "lseek");
fileio_info->param_1 = arg0; // fd
fileio_info->param_2 = arg1; // offset
fileio_info->param_3 = arg2; // flags
break;
case XTENSA_SYSCALL_RENAME:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "rename");
fileio_info->param_1 = arg0; // old pathp
fileio_info->param_2 = arg3; // old len
fileio_info->param_3 = arg1; // new pathp
fileio_info->param_4 = arg2; // new len
break;
case XTENSA_SYSCALL_UNLINK:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unlink");
fileio_info->param_1 = arg0; // pathnamep
fileio_info->param_2 = arg1; // len
break;
case XTENSA_SYSCALL_STAT:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "stat");
fileio_info->param_1 = arg0; // pathnamep
fileio_info->param_2 = arg2; // len
fileio_info->param_3 = arg1; // bufp
break;
case XTENSA_SYSCALL_FSTAT:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "fstat");
fileio_info->param_1 = arg0; // fd
fileio_info->param_2 = arg1; // bufp
break;
case XTENSA_SYSCALL_GETTIMEOFDAY:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "gettimeofday");
fileio_info->param_1 = arg0; // tvp
fileio_info->param_2 = arg1; // tzp
break;
case XTENSA_SYSCALL_ISATTY:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "isatty");
fileio_info->param_1 = arg0; // fd
break;
case XTENSA_SYSCALL_SYSTEM:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "system");
fileio_info->param_1 = arg0; // cmdp
fileio_info->param_2 = arg1; // len
break;
default:
snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unknown");
LOG_TARGET_DEBUG(target, "File-I/O: syscall unknown (%d), pc=0x%08X",
syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
LOG_INFO("File-I/O: syscall unknown (%d), pc=0x%08X",
syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
retval = ERROR_FAIL;
break;
}
return retval;
}
int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
{
struct xtensa *xtensa = target_to_xtensa(target);
if (!xtensa->proc_syscall)
return ERROR_FAIL;
LOG_TARGET_DEBUG(target, "File-I/O: syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
retcode, fileio_errno, ctrl_c ? "true" : "false");
/* If interrupt was requested before FIO completion (ERRNO==4), halt and repeat
* syscall. Otherwise, set File-I/O Ax and underlying ARx registers, increment PC.
* NOTE: sporadic cases of ((ERRNO==4) && !ctrl_c) were observed; most have ctrl_c.
*/
if (fileio_errno != 4) {
xtensa_reg_set_deep_relgen(target, XTENSA_SYSCALL_RETVAL_REG, retcode);
xtensa_reg_set_deep_relgen(target, XTENSA_SYSCALL_ERRNO_REG, fileio_errno);
xtensa_reg_val_t pc = xtensa_reg_get(target, XT_REG_IDX_PC);
xtensa_reg_set(target, XT_REG_IDX_PC, pc + XTENSA_SYSCALL_SZ);
}
xtensa->proc_syscall = false;
xtensa->halt_request = true;
return ctrl_c ? ERROR_FAIL : ERROR_OK;
}

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Xtensa Target File-I/O Support for OpenOCD *
* Copyright (C) 2020-2023 Cadence Design Systems, Inc. *
***************************************************************************/
#ifndef OPENOCD_TARGET_XTENSA_FILEIO_H
#define OPENOCD_TARGET_XTENSA_FILEIO_H
#include <target/target.h>
#include <helper/command.h>
#include "xtensa.h"
#define XTENSA_SYSCALL_OP_REG XT_REG_IDX_A2
#define XTENSA_SYSCALL_RETVAL_REG XT_REG_IDX_A2
#define XTENSA_SYSCALL_ERRNO_REG XT_REG_IDX_A3
#define XTENSA_SYSCALL_OPEN (-2)
#define XTENSA_SYSCALL_CLOSE (-3)
#define XTENSA_SYSCALL_READ (-4)
#define XTENSA_SYSCALL_WRITE (-5)
#define XTENSA_SYSCALL_LSEEK (-6)
#define XTENSA_SYSCALL_RENAME (-7)
#define XTENSA_SYSCALL_UNLINK (-8)
#define XTENSA_SYSCALL_STAT (-9)
#define XTENSA_SYSCALL_FSTAT (-10)
#define XTENSA_SYSCALL_GETTIMEOFDAY (-11)
#define XTENSA_SYSCALL_ISATTY (-12)
#define XTENSA_SYSCALL_SYSTEM (-13)
int xtensa_fileio_init(struct target *target);
int xtensa_fileio_detect_proc(struct target *target);
int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
#endif /* OPENOCD_TARGET_XTENSA_FILEIO_H */

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# CALAO Systems USB-A9G20-C01
# Authors: Gregory Hermant, Jean-Christophe PLAGNIOL-VILLARD, Wolfram Sang
adapter driver ftdi
ftdi device_desc "USB-A9G20"
@ -12,3 +13,160 @@ ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
transport select jtag
source [find target/at91sam9g20.cfg]
source [find mem_helper.tcl]
proc at91sam9g20_reset_start { } {
# Make sure that the jtag is running slow, since there are a number of different ways the board
# can be configured coming into this state that can cause communication problems with the jtag
# adapter. Also since this call can be made following a "reset init" where fast memory accesses
# are enabled, Need to temporarily shut this down so that the RSTC_MR register can be written at slower
# jtag speed without causing GDB keep alive problem.
arm7_9 fast_memory_access disable
adapter speed 2 ;# Slow-speed oscillator enabled at reset, so run jtag speed slow.
halt 0 ;# Make sure processor is halted, or error will result in following steps.
wait_halt 10000
# RSTC_MR : enable user reset, MMU may be enabled... use physical address
mww phys 0xfffffd08 0xa5000501
}
proc at91sam9g20_reset_init { } {
# At reset AT91SAM9G20 chip runs on slow clock (32.768 kHz). To shift over to a normal clock requires
# a number of steps that must be carefully performed. The process outline below follows the
# recommended procedure outlined in the AT91SAM9G20 technical manual.
#
# Several key and very important things to keep in mind:
# The SDRAM parts used currently on the Atmel evaluation board are -75 grade parts. This
# means the master clock (MCLK) must be at or below 133 MHz or timing errors will occur. The processor
# core can operate up to 400 MHz and therefore PCLK must be at or below this to function properly.
mww 0xfffffd44 0x00008000 ;# WDT_MR : disable watchdog.
# Set oscillator bypass bit (12.00 MHz external oscillator) in CKGR_MOR register.
mww 0xfffffc20 0x00000002
# Set PLLA Register for 798.000 MHz (divider: bypass, multiplier: 132).
# Wait for LOCKA signal in PMC_SR to assert indicating PLLA is stable.
mww 0xfffffc28 0x20843F02
while { [expr { [mrw 0xfffffc68] & 0x02 } ] != 2 } { sleep 1 }
# Set master system clock prescaler divide by 6 and processor clock divide by 2 in PMC_MCKR.
# Wait for MCKRDY signal from PMC_SR to assert.
mww 0xfffffc30 0x00001300
while { [expr { [mrw 0xfffffc68] & 0x08 } ] != 8 } { sleep 1 }
# Now change PMC_MCKR register to select PLLA.
# Wait for MCKRDY signal from PMC_SR to assert.
mww 0xfffffc30 0x00001302
while { [expr { [mrw 0xfffffc68] & 0x08 } ] != 8 } { sleep 1 }
# Processor and master clocks are now operating and stable at maximum frequency possible:
# -> MCLK = 133.000 MHz
# -> PCLK = 400.000 MHz
# Switch to fast JTAG speed
adapter speed 9500
# Enable faster DCC downloads.
arm7_9 dcc_downloads enable
arm7_9 fast_memory_access enable
# To be able to use external SDRAM, several peripheral configuration registers must
# be modified. The first change is made to PIO_ASR to select peripheral functions
# for D15 through D31. The second change is made to the PIO_PDR register to disable
# this for D15 through D31.
mww 0xfffff870 0xffff0000
mww 0xfffff804 0xffff0000
# The EBI chip select register EBI_CS must be specifically configured to enable the internal SDRAM controller
# using CS1. Additionally we want CS3 assigned to NandFlash. Also VDDIO is connected physically on
# the board to the 1.8V VDC power supply so set the appropriate register bit to notify the micrcontroller.
mww 0xffffef1c 0x000000a
# The USB-A9G20 Embedded computer has built-in NandFlash. The exact physical timing characteristics
# for the memory type used on the current board (MT29F2G08AACWP) can be established by setting
# four registers in order: SMC_SETUP3, SMC_PULSE3, SMC_CYCLE3, and SMC_MODE3.
mww 0xffffec30 0x00020002
mww 0xffffec34 0x04040404
mww 0xffffec38 0x00070007
mww 0xffffec3c 0x00030003
# Now setup SDRAM. This is tricky and configuration is very important for reliability! The current calculations
# are based on 2 x Micron LPSDRAM MT48H16M16LFBF-75 memory (4 M x 16 bit x 4 banks). If you use this file as a reference
# for a new board that uses different SDRAM devices or clock rates, you need to recalculate the value inserted
# into the SDRAM_CR register. Using the memory datasheet for the -75 grade part and assuming a master clock
# of 133.000 MHz then the SDCLK period is equal to 7.6 ns. This means the device requires:
#
# CAS latency = 3 cycles
# TXSR = 10 cycles
# TRAS = 6 cycles
# TRCD = 3 cycles
# TRP = 3 cycles
# TRC = 9 cycles
# TWR = 2 cycles
# 9 column, 13 row, 4 banks
# refresh equal to or less then 7.8 us for commercial/industrial rated devices
#
# Thus SDRAM_CR = 0xa6339279
mww 0xffffea08 0xa6339279
# Memory Device Type: SDRAM (low-power would be 0x1)
mww 0xffffea24 0x00000000
# Next issue a 'NOP' command through the SDRAMC_MR register followed by writing a zero value into
# the starting memory location for the SDRAM.
mww 0xffffea00 0x00000001
mww 0x20000000 0
# Issue an 'All Banks Precharge' command through the SDRAMC_MR register followed by writing a zero
# value into the starting memory location for the SDRAM.
mww 0xffffea00 0x00000002
mww 0x20000000 0
# Now issue an 'Auto-Refresh' command through the SDRAMC_MR register. Follow this operation by writing
# zero values eight times into the starting memory location for the SDRAM.
mww 0xffffea00 0x4
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
mww 0x20000000 0
# Almost done, so next issue a 'Load Mode Register' command followed by a zero value write to the
# the starting memory location for the SDRAM.
mww 0xffffea00 0x3
mww 0x20000000 0
# Signal normal mode using the SDRAMC_MR register and follow with a zero value write the starting
# memory location for the SDRAM.
mww 0xffffea00 0x0
mww 0x20000000 0
# Finally set the refresh rate to about every 7 us (7.5 ns x 924 cycles).
mww 0xffffea04 0x0000039c
}
$_TARGETNAME configure -event gdb-attach { reset init }
$_TARGETNAME configure -event reset-start {at91sam9g20_reset_start}
$_TARGETNAME configure -event reset-init {at91sam9g20_reset_init}

View File

@ -7,6 +7,6 @@ source [find interface/stlink-dap.cfg]
transport select swim
source [find target/stm8l152.cfg]
source [find target/stm8l15xx8.cfg]
reset_config srst_only

28
tcl/board/vd_xt8_jtag.cfg Normal file
View File

@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# Xtensa xt8 through JTAG
source [find interface/vdebug.cfg]
set CHIPNAME xt8
set CPUTAPID 0x120034e5
# vdebug select transport
transport select jtag
# JTAG reset config, frequency and reset delay
reset_config trst_and_srst
adapter speed 50000
adapter srst delay 5
# BFM hierarchical path and input clk period
vdebug bfm_path Testbench.u_vd_jtag_bfm 10ns
# DMA Memories to access backdoor, the values come from generated xtensa-core-xt8.cfg
#vdebug mem_path Testbench.Xtsubsystem.Core0.iram0.iram0.mem.dataArray 0x40000000 0x100000
#vdebug mem_path Testbench.Xtsubsystem.Core0.dram0.dram0.mem.dataArray 0x3ff00000 0x40000
# Create Xtensa target first
source [find target/xtensa.cfg]
# Generate [xtensa-core-XXX.cfg] via "xt-gdb --dump-oocd-config"
source [find target/xtensa-core-xt8.cfg]

View File

@ -23,11 +23,21 @@ if { [info exists FLASHNAME] } {
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
proc jtagspi_init {chain_id proxy_bit} {
# initialize jtagspi flash
# chain_id: identifier of pld (you can get a list with 'pld devices')
# proxy_bit: file with bitstream connecting JTAG and SPI interface in the PLD.
# release_from_pwr_down_cmd: optional, command sent to spi flash before probing.
# ex: 0xAB to release from power-dowm.
# Just omit it to not send a command.
proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} {
# load proxy bitstream $proxy_bit and probe spi flash
global _FLASHNAME
pld load $chain_id $proxy_bit
reset halt
if {$release_from_pwr_down_cmd != -1} {
jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd
}
flash probe $_FLASHNAME
}

38
tcl/target/qn908x.cfg Normal file
View File

@ -0,0 +1,38 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# NXP QN908x Cortex-M4F with 128 KiB SRAM
source [find target/swj-dp.tcl]
set CHIPNAME qn908x
set CHIPSERIES qn9080
if { ![info exists WORKAREASIZE] } {
set WORKAREASIZE 0x20000
}
# SWD IDCODE (Cortex M4).
set CPUTAPID 0x2ba01477
swj_newdap $CHIPNAME cpu -irlen 4 -expected-id $CPUTAPID
dap create $CHIPNAME.dap -chain-position $CHIPNAME.cpu
set TARGETNAME $CHIPNAME.cpu
target create $TARGETNAME cortex_m -dap $CHIPNAME.dap
# SRAM is mapped at 0x04000000.
$TARGETNAME configure -work-area-phys 0x04000000 -work-area-size $WORKAREASIZE
# flash bank <name> qn908x <base> <size> 0 0 <target#> [calc_checksum]
# The base must be set as 0x01000000, and the size parameter is unused.
set FLASHNAME $CHIPNAME.flash
flash bank $FLASHNAME qn908x 0x01000000 0 0 0 $TARGETNAME calc_checksum
# We write directly to flash memory over this adapter interface. For debugging
# this could in theory be faster (the Core clock on reset is normally at 32MHz),
# but for flashing 1MHz is more reliable.
adapter speed 1000
# Delay on reset line.
adapter srst delay 200
cortex_m reset_config sysresetreq

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

@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# script for stm32c0x family
#
# stm32c0 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 stm32c0x
}
set _ENDIAN little
# Work-area is a space in RAM used for flash programming
# By default use 6kB
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x1800
}
#jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
# SWD IDCODE (single drop, arm)
set _CPUTAPID 0x0bc11477
}
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 -endian $_ENDIAN -dap $_CHIPNAME.dap
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
flash bank $_CHIPNAME.flash stm32l4x 0x08000000 0 0 0 $_TARGETNAME
flash bank $_CHIPNAME.otp stm32l4x 0x1fff7000 0 0 0 $_TARGETNAME
# reasonable default
adapter speed 2000
adapter srst delay 100
if {[using_jtag]} {
jtag_ntrst_delay 100
}
reset_config srst_nogate
if {![using_hla]} {
# if srst is not fitted use SYSRESETREQ to
# perform a soft reset
cortex_m reset_config sysresetreq
}
$_TARGETNAME configure -event examine-end {
# Enable DBGMCU clock
# RCC_APB1ENR |= DBGMCUEN
mmw 0x4002103C 0x08000000 0
# Enable debug during low power modes (uses more power)
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
mmw 0x40015804 0x00000006 0
# Stop watchdog counters during halt
# DBGMCU_APB1_FZ |= DBG_WDGLS_STOP | DBG_WWDG_STOP
mmw 0x40015808 0x00001800 0
}

32
tcl/target/stm8l151x2.cfg Normal file
View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Config script for STM8L151x2
# Supported Devices:
# STM8L151C2
# STM8L151F2
# STM8L151G2
# STM8L151K2
# 1kB RAM
# Start 0x0000
# End 0x03ff
set WORKAREASIZE 1024
# 4kB Flash
set FLASHSTART 0x8000
set FLASHEND 0x8fff
# 256B EEPROM
set EEPROMSTART 0x1000
set EEPROMEND 0x10ff
set OPTIONSTART 0x4800
set OPTIONEND 0x487f
proc stm8_reset_rop {} {
mwb 0x4800 0xaa
mwb 0x4800 0xaa
reset halt
}
source [find target/stm8l.cfg]

32
tcl/target/stm8l151x3.cfg Normal file
View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Config script for STM8L151x3
# Supported Devices:
# STM8L151C3
# STM8L151F3
# STM8L151G3
# STM8L151K3
# 1kB RAM
# Start 0x0000
# End 0x03ff
set WORKAREASIZE 1024
# 8kB Flash
set FLASHSTART 0x8000
set FLASHEND 0x9fff
# 256B EEPROM
set EEPROMSTART 0x1000
set EEPROMEND 0x10ff
set OPTIONSTART 0x4800
set OPTIONEND 0x487f
proc stm8_reset_rop {} {
mwb 0x4800 0xaa
mwb 0x4800 0xaa
reset halt
}
source [find target/stm8l.cfg]

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#config script for STM8L152
echo 'DEPRECATED: choose between stm8l15xx4.cfg, stm8l15xx6.cfg and stm8l15xx8.cfg instead of stm8l152.cfg'
echo ' using stm8l152.cfg for backwards compatability'
set EEPROMSTART 0x1000
set EEPROMEND 0x13ff

33
tcl/target/stm8l15xx4.cfg Normal file
View File

@ -0,0 +1,33 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Config script for STM8L151x4/STM8L152x4
# Supported Devices:
# STM8L151C4
# STM8L151G4
# STM8L151K4
# STM8L152C4
# STM8L152K4
# 2kB RAM
# Start 0x0000
# End 0x07ff
set WORKAREASIZE 2048
# 16kB Flash
set FLASHSTART 0x8000
set FLASHEND 0xbfff
# 1kB EEPROM
set EEPROMSTART 0x1000
set EEPROMEND 0x13ff
set OPTIONSTART 0x4800
set OPTIONEND 0x48ff
proc stm8_reset_rop {} {
mwb 0x4800 0xaa
mwb 0x4800 0xaa
reset halt
}
source [find target/stm8l.cfg]

35
tcl/target/stm8l15xx6.cfg Normal file
View File

@ -0,0 +1,35 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Config script for STM8L151x6/STM8L152x6
# Supported Devices:
# STM8L151C6
# STM8L151G6
# STM8L151K6
# STM8L151R6
# STM8L152C6
# STM8L152K6
# STM8L152R6
# 2kB RAM
# Start 0x0000
# End 0x07ff
set WORKAREASIZE 2048
# 32kB Flash
set FLASHSTART 0x8000
set FLASHEND 0xffff
# 1kB EEPROM
set EEPROMSTART 0x1000
set EEPROMEND 0x13ff
set OPTIONSTART 0x4800
set OPTIONEND 0x48ff
proc stm8_reset_rop {} {
mwb 0x4800 0xaa
mwb 0x4800 0xaa
reset halt
}
source [find target/stm8l.cfg]

35
tcl/target/stm8l15xx8.cfg Normal file
View File

@ -0,0 +1,35 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Config script for STM8L151x8/STM8L152x8
# Supported Devices:
# STM8L151C8
# STM8L151M8
# STM8L151R8
# STM8L152C8
# STM8L152K8
# STM8L152M8
# STM8L152R8
# 4kB RAM
# Start 0x0000
# End 0x0fff
set WORKAREASIZE 4096
# 64kB Flash
set FLASHSTART 0x08000
set FLASHEND 0x17fff
# 2kB EEPROM
set EEPROMSTART 0x1000
set EEPROMEND 0x17ff
set OPTIONSTART 0x4800
set OPTIONEND 0x48ff
proc stm8_reset_rop {} {
mwb 0x4800 0xaa
mwb 0x4800 0xaa
reset halt
}
source [find target/stm8l.cfg]

View File

@ -22,7 +22,7 @@ source [find target/icepick.cfg]
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
}
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable -ignore-version
jtag configure $_CHIPNAME.cpu -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0"
# ICEpick-C (JTAG route controller)
@ -35,10 +35,7 @@ set _JRC_TAPID2 0x0B7B302F
set _JRC_TAPID3 0x0B95502F
set _JRC_TAPID4 0x0B97102F
set _JRC_TAPID5 0x0D8A002F
set _JRC_TAPID6 0x2B8A002F
set _JRC_TAPID7 0x2D8A002F
set _JRC_TAPID8 0x3B8A002F
set _JRC_TAPID9 0x3D8A002F
set _JRC_TAPID6 0x0B8A002F
jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \
@ -48,9 +45,6 @@ jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f \
-expected-id $_JRC_TAPID4 \
-expected-id $_JRC_TAPID5 \
-expected-id $_JRC_TAPID6 \
-expected-id $_JRC_TAPID7 \
-expected-id $_JRC_TAPID8 \
-expected-id $_JRC_TAPID9 \
-ignore-version
jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.cpu"
jtag configure $_CHIPNAME.jrc -event post-reset "runtest 100"
@ -60,7 +54,7 @@ dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# Cortex-R4 target
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_r4 -endian $_ENDIAN \
-dap $_CHIPNAME.dap -coreid 0 -dbgbase 0x00001003
-dap $_CHIPNAME.dap -coreid 0 -dbgbase 0x80001000
# TMS570 uses quirky BE-32 mode
$_CHIPNAME.dap ti_be_32_quirks 1

View File

@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
set DAP_TAPID 0x0B95A02F
set JRC_TAPID 0x0B95A02F
source [find target/ti_tms570.cfg]

View File

@ -1,27 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# for Palladium emulation systems
#
# TODO: Enable backdoor memory access
# set _MEMSTART 0x00000000
# set _MEMSIZE 0x100000
# BFM hierarchical path and input clk period
vdebug bfm_path dut_top.JTAG 10ns
# DMA Memories to access backdoor (up to 4)
# vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE
# Create Xtensa target first
source [find target/xtensa.cfg]
# Configure Xtensa core parameters next
# Generate [xtensa-core-XXX.cfg] via "xt-gdb --dump-oocd-config"
# register target
proc vdebug_examine_end {} {
# vdebug register_target
}
# Default hooks
$_TARGETNAME configure -event examine-end { vdebug_examine_end }

View File

@ -0,0 +1,166 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# OpenOCD configuration file for Xtensa xt8 target
# Core definition and ABI
xtensa xtdef LX
xtensa xtopt arnum 32
xtensa xtopt windowed 1
# Exception/Interrupt Options
xtensa xtopt exceptions 1
xtensa xtopt hipriints 1
xtensa xtopt intlevels 3
xtensa xtopt excmlevel 1
# Cache Options
xtensa xtmem icache 16 1024 1
xtensa xtmem dcache 16 1024 1 1
# Memory Options
xtensa xtmem iram 0x40000000 1048576
xtensa xtmem dram 0x3ff00000 262144
xtensa xtmem srom 0x50000000 131072
xtensa xtmem sram 0x60000000 4194304
# Memory Protection/Translation Options
# Debug Options
xtensa xtopt debuglevel 3
xtensa xtopt ibreaknum 2
xtensa xtopt dbreaknum 2
# Core Registers
xtensa xtregs 127
xtensa xtreg a0 0x0000
xtensa xtreg a1 0x0001
xtensa xtreg a2 0x0002
xtensa xtreg a3 0x0003
xtensa xtreg a4 0x0004
xtensa xtreg a5 0x0005
xtensa xtreg a6 0x0006
xtensa xtreg a7 0x0007
xtensa xtreg a8 0x0008
xtensa xtreg a9 0x0009
xtensa xtreg a10 0x000a
xtensa xtreg a11 0x000b
xtensa xtreg a12 0x000c
xtensa xtreg a13 0x000d
xtensa xtreg a14 0x000e
xtensa xtreg a15 0x000f
xtensa xtreg pc 0x0020
xtensa xtreg ar0 0x0100
xtensa xtreg ar1 0x0101
xtensa xtreg ar2 0x0102
xtensa xtreg ar3 0x0103
xtensa xtreg ar4 0x0104
xtensa xtreg ar5 0x0105
xtensa xtreg ar6 0x0106
xtensa xtreg ar7 0x0107
xtensa xtreg ar8 0x0108
xtensa xtreg ar9 0x0109
xtensa xtreg ar10 0x010a
xtensa xtreg ar11 0x010b
xtensa xtreg ar12 0x010c
xtensa xtreg ar13 0x010d
xtensa xtreg ar14 0x010e
xtensa xtreg ar15 0x010f
xtensa xtreg ar16 0x0110
xtensa xtreg ar17 0x0111
xtensa xtreg ar18 0x0112
xtensa xtreg ar19 0x0113
xtensa xtreg ar20 0x0114
xtensa xtreg ar21 0x0115
xtensa xtreg ar22 0x0116
xtensa xtreg ar23 0x0117
xtensa xtreg ar24 0x0118
xtensa xtreg ar25 0x0119
xtensa xtreg ar26 0x011a
xtensa xtreg ar27 0x011b
xtensa xtreg ar28 0x011c
xtensa xtreg ar29 0x011d
xtensa xtreg ar30 0x011e
xtensa xtreg ar31 0x011f
xtensa xtreg lbeg 0x0200
xtensa xtreg lend 0x0201
xtensa xtreg lcount 0x0202
xtensa xtreg sar 0x0203
xtensa xtreg windowbase 0x0248
xtensa xtreg windowstart 0x0249
xtensa xtreg configid0 0x02b0
xtensa xtreg configid1 0x02d0
xtensa xtreg ps 0x02e6
xtensa xtreg expstate 0x03e6
xtensa xtreg mmid 0x0259
xtensa xtreg ibreakenable 0x0260
xtensa xtreg ddr 0x0268
xtensa xtreg ibreaka0 0x0280
xtensa xtreg ibreaka1 0x0281
xtensa xtreg dbreaka0 0x0290
xtensa xtreg dbreaka1 0x0291
xtensa xtreg dbreakc0 0x02a0
xtensa xtreg dbreakc1 0x02a1
xtensa xtreg epc1 0x02b1
xtensa xtreg epc2 0x02b2
xtensa xtreg epc3 0x02b3
xtensa xtreg depc 0x02c0
xtensa xtreg eps2 0x02c2
xtensa xtreg eps3 0x02c3
xtensa xtreg excsave1 0x02d1
xtensa xtreg excsave2 0x02d2
xtensa xtreg excsave3 0x02d3
xtensa xtreg interrupt 0x02e2
xtensa xtreg intset 0x02e2
xtensa xtreg intclear 0x02e3
xtensa xtreg intenable 0x02e4
xtensa xtreg exccause 0x02e8
xtensa xtreg debugcause 0x02e9
xtensa xtreg ccount 0x02ea
xtensa xtreg icount 0x02ec
xtensa xtreg icountlevel 0x02ed
xtensa xtreg excvaddr 0x02ee
xtensa xtreg ccompare0 0x02f0
xtensa xtreg ccompare1 0x02f1
xtensa xtreg pwrctl 0x200f
xtensa xtreg pwrstat 0x2010
xtensa xtreg eristat 0x2011
xtensa xtreg cs_itctrl 0x2012
xtensa xtreg cs_claimset 0x2013
xtensa xtreg cs_claimclr 0x2014
xtensa xtreg cs_lockaccess 0x2015
xtensa xtreg cs_lockstatus 0x2016
xtensa xtreg cs_authstatus 0x2017
xtensa xtreg fault_info 0x2026
xtensa xtreg trax_id 0x2027
xtensa xtreg trax_control 0x2028
xtensa xtreg trax_status 0x2029
xtensa xtreg trax_data 0x202a
xtensa xtreg trax_address 0x202b
xtensa xtreg trax_pctrigger 0x202c
xtensa xtreg trax_pcmatch 0x202d
xtensa xtreg trax_delay 0x202e
xtensa xtreg trax_memstart 0x202f
xtensa xtreg trax_memend 0x2030
xtensa xtreg pmg 0x203e
xtensa xtreg pmpc 0x203f
xtensa xtreg pm0 0x2040
xtensa xtreg pm1 0x2041
xtensa xtreg pmctrl0 0x2042
xtensa xtreg pmctrl1 0x2043
xtensa xtreg pmstat0 0x2044
xtensa xtreg pmstat1 0x2045
xtensa xtreg ocdid 0x2046
xtensa xtreg ocd_dcrclr 0x2047
xtensa xtreg ocd_dcrset 0x2048
xtensa xtreg ocd_dsr 0x2049
xtensa xtreg psintlevel 0x2003
xtensa xtreg psum 0x2004
xtensa xtreg pswoe 0x2005
xtensa xtreg psexcm 0x2006
xtensa xtreg pscallinc 0x2007
xtensa xtreg psowb 0x2008