Merge commit '9f23a1d7c1e27c556ef9787b9d3f263f5c1ecf24' into from_upstream
Conflicts: HACKING src/target/riscv/riscv-013.c Change-Id: I43ccb143cae8daa39212d66a8824ae3ad2af6fef
This commit is contained in:
commit
f02fe0960c
15
HACKING
15
HACKING
|
@ -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
|
||||
|
|
165
doc/openocd.texi
165
doc/openocd.texi
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
#include <helper/log.h>
|
||||
#include "hello.h"
|
||||
|
||||
COMMAND_HANDLER(handle_foo_command)
|
||||
{
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
373
src/jtag/tcl.c
373
src/jtag/tcl.c
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *)¤t_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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(®_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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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!";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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]
|
|
@ -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]
|
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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]
|
|
@ -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]
|
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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 }
|
|
@ -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
|
Loading…
Reference in New Issue