Merge commit 'e17fe4db0f256ee4fb97dcfd6b9f7f55c966b190' into from_upstream

Conflicts:
	src/flash/nor/drivers.c
	src/target/riscv/riscv.c

Change-Id: Ide3eded7e0d5b0b446bfd0873a32c00cc9f128bd
This commit is contained in:
Tim Newsome 2023-10-23 12:29:21 -07:00
commit af08d582b5
123 changed files with 6584 additions and 698 deletions

View File

@ -21,7 +21,7 @@
.global _start
_start:
launch_program_in_rom:
// variables are already set, addres to jump is in r3
// variables are already set, address to jump is in r3
blx r3
exit:
// Wait for OpenOCD

View File

@ -8519,13 +8519,90 @@ openocd -f board/digilent_zedboard.cfg -c "init" \
@end example
@deffn {Command} {virtex2 read_stat} num
Reads and displays the Virtex-II status register (STAT)
for FPGA @var{num}.
@end deffn
@end deffn
@deffn {FPGA Driver} {lattice} [family]
The FGPA families ECP2, ECP3, ECP5, Certus and CertusPro by Lattice are supported.
This driver can be used to load the bitstream into the FPGA or read the status register and read/write the usercode register.
The option @option{family} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
@deffn {Command} {lattice read_status} num
Reads and displays the status register
for FPGA @var{num}.
@end deffn
@deffn {Command} {lattice read_user} num
Reads and displays the user register
for FPGA @var{num}.
@end deffn
@deffn {Command} {lattice write_user} num val
Writes the user register.
for FPGA @var{num} with value @var{val}.
@end deffn
@deffn {Command} {lattice set_preload} num length
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
The load command for the FPGA @var{num} will use a length for the preload of @var{length}.
@end deffn
@end deffn
@deffn {FPGA Driver} {efinix}
Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
This driver can be used to load the bitstream into the FPGA.
@end deffn
@deffn {FPGA Driver} {intel} [@option{family}]
This driver can be used to load the bitstream into Intel (former Altera) FPGAs.
The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported.
@c Arria V and Arria 10, MAX II, MAX V, MAX10)
The option @option{family} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
This is needed when the JTAG ID of the device is ambiguous (same ID is used for chips in different families).
As input file format the driver supports a '.rbf' (raw bitstream file) file. The '.rbf' file can be generated
from a '.sof' file with @verb{|quartus_cpf -c blinker.sof blinker.rbf|}
Defines a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
@example
pld device intel cycloneiii.tap cycloneiii
@end example
@deffn {Command} {intel set_bscan} num len
Set boundary scan register length of FPGA @var{num} to @var{len}. This is needed because the
length can vary between chips with the same JTAG ID.
@end deffn
@deffn {Command} {intel set_check_pos} num pos
Selects the position @var{pos} in the boundary-scan register. The bit at this
position is checked after loading the bitstream and must be '1', which is the case when no error occurred.
With a value of -1 for @var{pos} the check will be omitted.
@end deffn
@end deffn
@deffn {FPGA Driver} {gowin}
This driver can be used to load the bitstream into FPGAs from Gowin.
It is possible to program the SRAM. Programming the flash is not supported.
The files @verb{|.fs|} and @verb{|.bin|} generated by Gowin FPGA Designer are supported.
@end deffn
@deffn {FPGA Driver} {gatemate}
This driver can be used to load the bitstream into GateMate FPGAs form CologneChip.
The files @verb{|.bit|} and @verb{|.cfg|} both generated by p_r tool from CologneChip are supported.
@end deffn
@node General Commands
@chapter General Commands
@cindex commands
@ -11370,6 +11447,46 @@ Stop current trace as started by the tracestart command.
Dump trace memory to a file.
@end deffn
@section Espressif Specific Commands
@deffn {Command} {esp apptrace} (start <destination> [<poll_period> [<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
Starts
@uref{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#application-level-tracing-library, application level tracing}.
Data will be stored to specified destination. Available destinations are:
@itemize @bullet
@item @code{file://<outfile>} - Save trace logs into file.
@item @code{tcp://<host>:<port>} - Send trace logs to tcp port on specified host. OpenOCD will act as a tcp client.
@item @code{con:} - Print trace logs to the stdout.
@end itemize
Other parameters will be same for each destination.
@itemize @bullet
@item @code{poll_period} - trace data polling period in ms.
@item @code{trace_size} - maximum trace data size.
Tracing will be stopped automatically when that amount is reached.
Use "-1" to disable the limitation.
@item @code{stop_tmo} - Data reception timeout in ms.
Tracing will be stopped automatically when no data is received within that period.
@item @code{wait4halt} - if non-zero then wait for target to be halted before tracing start.
@item @code{skip_size} - amount of tracing data to be skipped before writing it to destination.
@end itemize
@end deffn
@deffn {Command} {esp apptrace} (stop)
Stops tracing started with above command.
@end deffn
@deffn {Command} {esp apptrace} (status)
Requests ongoing tracing status.
@end deffn
@deffn {Command} {esp apptrace} (dump file://<outfile>)
Dumps tracing data from target buffer. It can be useful to dump the latest data
buffered on target for post-mortem analysis. For example when target starts tracing automatically
w/o OpenOCD command and keeps only the latest data window which fit into the buffer.
@uref{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#application-level-tracing-library, application level tracing}.
Data will be stored to specified destination.
@end deffn
@anchor{softwaredebugmessagesandtracing}
@section Software Debug Messages and Tracing
@cindex Linux-ARM DCC support

View File

@ -13,25 +13,6 @@
#include "core.h"
#include "driver.h"
/* NAND flash controller
*/
extern struct nand_flash_controller nonce_nand_controller;
extern struct nand_flash_controller davinci_nand_controller;
extern struct nand_flash_controller lpc3180_nand_controller;
extern struct nand_flash_controller lpc32xx_nand_controller;
extern struct nand_flash_controller orion_nand_controller;
extern struct nand_flash_controller s3c2410_nand_controller;
extern struct nand_flash_controller s3c2412_nand_controller;
extern struct nand_flash_controller s3c2440_nand_controller;
extern struct nand_flash_controller s3c2443_nand_controller;
extern struct nand_flash_controller s3c6400_nand_controller;
extern struct nand_flash_controller mxc_nand_flash_controller;
extern struct nand_flash_controller imx31_nand_flash_controller;
extern struct nand_flash_controller at91sam9_nand_controller;
extern struct nand_flash_controller nuc910_nand_controller;
/* extern struct nand_flash_controller boundary_scan_nand_controller; */
static struct nand_flash_controller *nand_flash_controllers[] = {
&nonce_nand_controller,
&davinci_nand_controller,
@ -47,7 +28,6 @@ static struct nand_flash_controller *nand_flash_controllers[] = {
&imx31_nand_flash_controller,
&at91sam9_nand_controller,
&nuc910_nand_controller,
/* &boundary_scan_nand_controller, */
NULL
};

View File

@ -89,4 +89,19 @@ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *);
*/
int nand_driver_walk(nand_driver_walker_t f, void *x);
extern struct nand_flash_controller at91sam9_nand_controller;
extern struct nand_flash_controller davinci_nand_controller;
extern struct nand_flash_controller imx31_nand_flash_controller;
extern struct nand_flash_controller lpc3180_nand_controller;
extern struct nand_flash_controller lpc32xx_nand_controller;
extern struct nand_flash_controller mxc_nand_flash_controller;
extern struct nand_flash_controller nonce_nand_controller;
extern struct nand_flash_controller nuc910_nand_controller;
extern struct nand_flash_controller orion_nand_controller;
extern struct nand_flash_controller s3c2410_nand_controller;
extern struct nand_flash_controller s3c2412_nand_controller;
extern struct nand_flash_controller s3c2440_nand_controller;
extern struct nand_flash_controller s3c2443_nand_controller;
extern struct nand_flash_controller s3c6400_nand_controller;
#endif /* OPENOCD_FLASH_NAND_DRIVER_H */

View File

@ -1029,7 +1029,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
LOG_DEBUG("SLC write page %" PRIx32 " data=%d, oob=%d, "
"data_size=%" PRIu32 ", oob_size=%" PRIu32,
page, data != 0, oob != 0, data_size, oob_size);
page, !!data, !!oob, data_size, oob_size);
target_mem_base = pworking_area->address;
/*

View File

@ -67,8 +67,6 @@
#define OFFSET_EFC_FSR 8
#define OFFSET_EFC_FRR 12
extern const struct flash_driver at91sam3_flash;
static float _tomhz(uint32_t freq_hz)
{
float f;

View File

@ -62,8 +62,6 @@
#define OFFSET_EFC_FSR 8
#define OFFSET_EFC_FRR 12
extern const struct flash_driver at91sam4_flash;
static float _tomhz(uint32_t freq_hz)
{
float f;

View File

@ -78,7 +78,7 @@
#define SAMD_GET_DEVSEL(id) (id & 0xFF)
/* Bits to mask out lockbits in user row */
#define NVMUSERROW_LOCKBIT_MASK ((uint64_t)0x0000FFFFFFFFFFFF)
#define NVMUSERROW_LOCKBIT_MASK 0x0000FFFFFFFFFFFFULL
struct samd_part {
uint8_t id;
@ -316,31 +316,31 @@ struct samd_family {
static const struct samd_family samd_families[] = {
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20,
samd20_parts, ARRAY_SIZE(samd20_parts),
(uint64_t)0xFFFF01FFFE01FF77 },
0xFFFF01FFFE01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
samd21_parts, ARRAY_SIZE(samd21_parts),
(uint64_t)0xFFFF01FFFE01FF77 },
0xFFFF01FFFE01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_09,
samd09_parts, ARRAY_SIZE(samd09_parts),
(uint64_t)0xFFFF01FFFE01FF77 },
0xFFFF01FFFE01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10,
samd10_parts, ARRAY_SIZE(samd10_parts),
(uint64_t)0xFFFF01FFFE01FF77 },
0xFFFF01FFFE01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11,
samd11_parts, ARRAY_SIZE(samd11_parts),
(uint64_t)0xFFFF01FFFE01FF77 },
0xFFFF01FFFE01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_21,
saml21_parts, ARRAY_SIZE(saml21_parts),
(uint64_t)0xFFFF03FFFC01FF77 },
0xFFFF03FFFC01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_22,
saml22_parts, ARRAY_SIZE(saml22_parts),
(uint64_t)0xFFFF03FFFC01FF77 },
0xFFFF03FFFC01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_20,
samc20_parts, ARRAY_SIZE(samc20_parts),
(uint64_t)0xFFFF03FFFC01FF77 },
0xFFFF03FFFC01FF77ULL },
{ SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_21,
samc21_parts, ARRAY_SIZE(samc21_parts),
(uint64_t)0xFFFF03FFFC01FF77 },
0xFFFF03FFFC01FF77ULL },
};
struct samd_info {

View File

@ -93,7 +93,7 @@
#define SAMD_GET_DEVSEL(id) (id & 0xFF)
/* Bits to mask user row */
#define NVMUSERROW_SAM_E5_D5_MASK ((uint64_t)0x7FFF00FF3C007FFF)
#define NVMUSERROW_SAM_E5_D5_MASK 0x7FFF00FF3C007FFFULL
struct samd_part {
uint8_t id;

View File

@ -53,8 +53,6 @@
#define SAMV_PAGE_SIZE 512
#define SAMV_FLASH_BASE 0x00400000
extern const struct flash_driver atsamv_flash;
struct samv_flash_bank {
bool probed;
unsigned size_bytes;

View File

@ -237,4 +237,75 @@ struct flash_driver {
*/
const struct flash_driver *flash_driver_find_by_name(const char *name);
extern const struct flash_driver aduc702x_flash;
extern const struct flash_driver aducm360_flash;
extern const struct flash_driver ambiqmicro_flash;
extern const struct flash_driver at91sam3_flash;
extern const struct flash_driver at91sam4_flash;
extern const struct flash_driver at91sam4l_flash;
extern const struct flash_driver at91sam7_flash;
extern const struct flash_driver at91samd_flash;
extern const struct flash_driver ath79_flash;
extern const struct flash_driver atsame5_flash;
extern const struct flash_driver atsamv_flash;
extern const struct flash_driver avr_flash;
extern const struct flash_driver bluenrgx_flash;
extern const struct flash_driver cc26xx_flash;
extern const struct flash_driver cc3220sf_flash;
extern const struct flash_driver cfi_flash;
extern const struct flash_driver dsp5680xx_flash;
extern const struct flash_driver efm32_flash;
extern const struct flash_driver em357_flash;
extern const struct flash_driver esirisc_flash;
extern const struct flash_driver faux_flash;
extern const struct flash_driver fespi_flash;
extern const struct flash_driver fm3_flash;
extern const struct flash_driver fm4_flash;
extern const struct flash_driver jtagspi_flash;
extern const struct flash_driver kinetis_flash;
extern const struct flash_driver kinetis_ke_flash;
extern const struct flash_driver lpc2000_flash;
extern const struct flash_driver lpc288x_flash;
extern const struct flash_driver lpc2900_flash;
extern const struct flash_driver lpcspifi_flash;
extern const struct flash_driver max32xxx_flash;
extern const struct flash_driver mdr_flash;
extern const struct flash_driver mrvlqspi_flash;
extern const struct flash_driver msp432_flash;
extern const struct flash_driver niietcm4_flash;
extern const struct flash_driver npcx_flash;
extern const struct flash_driver nrf51_flash;
extern const struct flash_driver nrf5_flash;
extern const struct flash_driver numicro_flash;
extern const struct flash_driver ocl_flash;
extern const struct flash_driver pic32mx_flash;
extern const struct flash_driver psoc4_flash;
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 renesas_rpchf_flash;
extern const struct flash_driver rp2040_flash;
extern const struct flash_driver rsl10_flash;
extern const struct flash_driver sh_qspi_flash;
extern const struct flash_driver sim3x_flash;
extern const struct flash_driver stellaris_flash;
extern const struct flash_driver stm32f1x_flash;
extern const struct flash_driver stm32f2x_flash;
extern const struct flash_driver stm32h7x_flash;
extern const struct flash_driver stm32l4x_flash;
extern const struct flash_driver stm32lx_flash;
extern const struct flash_driver stmqspi_flash;
extern const struct flash_driver stmsmi_flash;
extern const struct flash_driver str7x_flash;
extern const struct flash_driver str9x_flash;
extern const struct flash_driver str9xpec_flash;
extern const struct flash_driver swm050_flash;
extern const struct flash_driver tms470_flash;
extern const struct flash_driver virtual_flash;
extern const struct flash_driver w600_flash;
extern const struct flash_driver xcf_flash;
extern const struct flash_driver xmc1xxx_flash;
extern const struct flash_driver xmc4xxx_flash;
#endif /* OPENOCD_FLASH_NOR_DRIVER_H */

View File

@ -9,78 +9,6 @@
#endif
#include "imp.h"
extern const struct flash_driver aduc702x_flash;
extern const struct flash_driver aducm360_flash;
extern const struct flash_driver ambiqmicro_flash;
extern const struct flash_driver at91sam3_flash;
extern const struct flash_driver at91sam4_flash;
extern const struct flash_driver at91sam4l_flash;
extern const struct flash_driver at91sam7_flash;
extern const struct flash_driver at91samd_flash;
extern const struct flash_driver ath79_flash;
extern const struct flash_driver atsame5_flash;
extern const struct flash_driver atsamv_flash;
extern const struct flash_driver avr_flash;
extern const struct flash_driver bluenrgx_flash;
extern const struct flash_driver cc3220sf_flash;
extern const struct flash_driver cc26xx_flash;
extern const struct flash_driver cfi_flash;
extern const struct flash_driver dsp5680xx_flash;
extern const struct flash_driver efm32_flash;
extern const struct flash_driver em357_flash;
extern const struct flash_driver esirisc_flash;
extern const struct flash_driver faux_flash;
extern const struct flash_driver fm3_flash;
extern const struct flash_driver fm4_flash;
extern const struct flash_driver fespi_flash;
extern const struct flash_driver gd32vf103_flash;
extern const struct flash_driver jtagspi_flash;
extern const struct flash_driver kinetis_flash;
extern const struct flash_driver kinetis_ke_flash;
extern const struct flash_driver lpc2000_flash;
extern const struct flash_driver lpc288x_flash;
extern const struct flash_driver lpc2900_flash;
extern const struct flash_driver lpcspifi_flash;
extern const struct flash_driver max32xxx_flash;
extern const struct flash_driver mdr_flash;
extern const struct flash_driver mrvlqspi_flash;
extern const struct flash_driver msp432_flash;
extern const struct flash_driver niietcm4_flash;
extern const struct flash_driver npcx_flash;
extern const struct flash_driver nrf5_flash;
extern const struct flash_driver nrf51_flash;
extern const struct flash_driver numicro_flash;
extern const struct flash_driver ocl_flash;
extern const struct flash_driver pic32mx_flash;
extern const struct flash_driver psoc4_flash;
extern const struct flash_driver psoc5lp_flash;
extern const struct flash_driver psoc5lp_eeprom_flash;
extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash;
extern const struct flash_driver renesas_rpchf_flash;
extern const struct flash_driver rp2040_flash;
extern const struct flash_driver sh_qspi_flash;
extern const struct flash_driver sim3x_flash;
extern const struct flash_driver stellaris_flash;
extern const struct flash_driver stm32f1x_flash;
extern const struct flash_driver stm32f2x_flash;
extern const struct flash_driver stm32lx_flash;
extern const struct flash_driver stm32l4x_flash;
extern const struct flash_driver stm32h7x_flash;
extern const struct flash_driver stmqspi_flash;
extern const struct flash_driver stmsmi_flash;
extern const struct flash_driver str7x_flash;
extern const struct flash_driver str9x_flash;
extern const struct flash_driver str9xpec_flash;
extern const struct flash_driver swm050_flash;
extern const struct flash_driver tms470_flash;
extern const struct flash_driver virtual_flash;
extern const struct flash_driver w600_flash;
extern const struct flash_driver xcf_flash;
extern const struct flash_driver xmc1xxx_flash;
extern const struct flash_driver xmc4xxx_flash;
extern const struct flash_driver rsl10_flash;
/**
* The list of built-in flash drivers.
* @todo Make this dynamically extendable with loadable modules.

View File

@ -375,7 +375,7 @@ static int msp432_init(struct flash_bank *bank)
buf_set_u32(reg_params[0].value, 0, 32, ALGO_STACK_POINTER_ADDR);
/* Begin executing the flash helper algorithm */
retval = target_start_algorithm(target, 0, 0, 1, reg_params,
retval = target_start_algorithm(target, 0, NULL, 1, reg_params,
algo_entry_addr, 0, &msp432_bank->armv7m_info);
destroy_reg_param(&reg_params[0]);
if (retval != ERROR_OK) {

View File

@ -536,8 +536,8 @@ struct numicro_flash_bank {
};
/* Private variables */
uint32_t m_page_size = NUMICRO_PAGESIZE;
uint32_t m_address_bias_offset;
static uint32_t m_page_size = NUMICRO_PAGESIZE;
static uint32_t m_address_bias_offset;
/* Private methods */
static int numicro_get_arm_arch(struct target *target)

View File

@ -520,7 +520,7 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command)
return ERROR_OK;
}
struct flash_driver rp2040_flash = {
const struct flash_driver rp2040_flash = {
.name = "rp2040_flash",
.flash_bank_command = rp2040_flash_bank_command,
.erase = rp2040_flash_erase,

View File

@ -107,7 +107,7 @@ static const char *const rsl10_error_list[] = {
[RSL10_FLASH_ERR_PROG_FAILED] = "prog failed",
};
const char *rsl10_error(enum rsl10_flash_status x)
static const char *rsl10_error(enum rsl10_flash_status x)
{
if (x >= RSL10_FLASH_MAX_ERR_CODES || !rsl10_error_list[x])
return "unknown";

View File

@ -1342,7 +1342,7 @@ COMMAND_HANDLER(stellaris_handle_recover_command)
* cycle to recover.
*/
Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", NULL, 0);
if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
retval = ERROR_OK;
goto user_action;

View File

@ -2447,7 +2447,7 @@ static const struct command_registration stmqspi_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct flash_driver stmqspi_flash = {
const struct flash_driver stmqspi_flash = {
.name = "stmqspi",
.commands = stmqspi_command_handlers,
.flash_bank_command = stmqspi_flash_bank_command,

View File

@ -183,7 +183,7 @@ static const struct command_registration swm050_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct flash_driver swm050_flash = {
const struct flash_driver swm050_flash = {
.name = "swm050",
.commands = swm050_command_handlers,
.flash_bank_command = swm050_flash_bank_command,

View File

@ -582,7 +582,7 @@ int command_run_line(struct command_context *context, char *line)
Jim_DeleteAssocData(interp, "retval");
retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
if (retcode == JIM_OK) {
retcode = Jim_Eval_Named(interp, line, 0, 0);
retcode = Jim_Eval_Named(interp, line, NULL, 0);
Jim_DeleteAssocData(interp, "retval");
}

View File

@ -26,7 +26,7 @@ const char *jep106_table_manufacturer(unsigned int bank, unsigned int id)
/* index is zero based */
id--;
if (bank >= ARRAY_SIZE(jep106) || jep106[bank][id] == 0)
if (bank >= ARRAY_SIZE(jep106) || !jep106[bank][id])
return "<unknown>";
return jep106[bank][id];

View File

@ -39,12 +39,12 @@ static int help_flag, version_flag;
static const struct option long_options[] = {
{"help", no_argument, &help_flag, 1},
{"version", no_argument, &version_flag, 1},
{"debug", optional_argument, 0, 'd'},
{"file", required_argument, 0, 'f'},
{"search", required_argument, 0, 's'},
{"log_output", required_argument, 0, 'l'},
{"command", required_argument, 0, 'c'},
{0, 0, 0, 0}
{"debug", optional_argument, NULL, 'd'},
{"file", required_argument, NULL, 'f'},
{"search", required_argument, NULL, 's'},
{"log_output", required_argument, NULL, 'l'},
{"command", required_argument, NULL, 'c'},
{NULL, 0, NULL, 0}
};
int configuration_output_handler(struct command_context *context, const char *line)

View File

@ -12,6 +12,7 @@
#include "log.h"
#include "time_support.h"
#include "util.h"
COMMAND_HANDLER(handler_util_ms)
{

View File

@ -213,7 +213,7 @@ static int armjtagew_init(void)
armjtagew_handle = armjtagew_usb_open();
if (armjtagew_handle == 0) {
if (!armjtagew_handle) {
LOG_ERROR(
"Cannot find ARM-JTAG-EW Interface! Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;

View File

@ -107,7 +107,7 @@ static int at91rm9200_quit(void);
static struct bitbang_interface at91rm9200_bitbang = {
.read = at91rm9200_read,
.write = at91rm9200_write,
.blink = 0
.blink = NULL,
};
static bb_value_t at91rm9200_read(void)
@ -157,8 +157,12 @@ COMMAND_HANDLER(at91rm9200_handle_device_command)
return ERROR_COMMAND_SYNTAX_ERROR;
/* only if the device name wasn't overwritten by cmdline */
if (at91rm9200_device == 0) {
if (!at91rm9200_device) {
at91rm9200_device = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
if (!at91rm9200_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
strcpy(at91rm9200_device, CMD_ARGV[0]);
}

View File

@ -19,7 +19,7 @@
#include <sys/mman.h>
uint32_t bcm2835_peri_base = 0x20000000;
static uint32_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)

View File

@ -37,7 +37,7 @@ static int ep93xx_reset(int trst, int srst);
static int ep93xx_init(void);
static int ep93xx_quit(void);
struct timespec ep93xx_zzzz;
static struct timespec ep93xx_zzzz;
static struct jtag_interface ep93xx_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
@ -58,7 +58,7 @@ struct adapter_driver ep93xx_adapter_driver = {
static struct bitbang_interface ep93xx_bitbang = {
.read = ep93xx_read,
.write = ep93xx_write,
.blink = 0,
.blink = NULL,
};
static bb_value_t ep93xx_read(void)

View File

@ -235,7 +235,7 @@ static int ft232r_speed(int divisor)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BAUD_RATE, divisor, 0, 0, 0, 1000) != 0) {
SIO_SET_BAUD_RATE, divisor, 0, NULL, 0, 1000) != 0) {
LOG_ERROR("cannot set baud rate");
return ERROR_JTAG_DEVICE_ERROR;
}
@ -266,7 +266,7 @@ static int ft232r_init(void)
/* Reset the device. */
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_RESET, 0, 0, 0, 0, 1000) != 0) {
SIO_RESET, 0, 0, NULL, 0, 1000) != 0) {
LOG_ERROR("unable to reset device");
return ERROR_JTAG_INIT_FAILED;
}
@ -275,7 +275,7 @@ static int ft232r_init(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
0, 0, 0, 1000) != 0) {
0, NULL, 0, 1000) != 0) {
LOG_ERROR("cannot set sync bitbang mode");
return ERROR_JTAG_INIT_FAILED;
}
@ -288,13 +288,13 @@ static int ft232r_init(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BAUD_RATE, divisor,
0, 0, 0, 1000) != 0) {
0, NULL, 0, 1000) != 0) {
LOG_ERROR("cannot set baud rate");
return ERROR_JTAG_INIT_FAILED;
}
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_LATENCY_TIMER, latency_timer, 0, 0, 0, 1000) != 0) {
SIO_SET_LATENCY_TIMER, latency_timer, 0, NULL, 0, 1000) != 0) {
LOG_ERROR("unable to set latency timer");
return ERROR_JTAG_INIT_FAILED;
}
@ -315,7 +315,7 @@ static int ft232r_quit(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, ft232r_restore_bitmode,
0, 0, 0, 1000) != 0) {
0, NULL, 0, 1000) != 0) {
LOG_ERROR("cannot set bitmode to restore serial port");
}
}

View File

@ -64,6 +64,7 @@
#include <transport/transport.h>
#include <helper/time_support.h>
#include <helper/log.h>
#include <helper/nvp.h>
#if IS_CYGWIN == 1
#include <windows.h>
@ -224,7 +225,7 @@ static int ftdi_set_signal(const struct signal *s, char value)
oe = s->invert_oe;
break;
default:
assert(0 && "invalid signal level specifier");
LOG_ERROR("invalid signal level specifier \'%c\'(0x%02x)", value, value);
return ERROR_FAIL;
}
@ -1272,22 +1273,22 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command)
COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command)
{
struct jim_nvp *n;
static const struct jim_nvp nvp_ftdi_jtag_modes[] = {
const struct nvp *n;
static const struct nvp nvp_ftdi_jtag_modes[] = {
{ .name = "rising", .value = JTAG_MODE },
{ .name = "falling", .value = JTAG_MODE_ALT },
{ .name = NULL, .value = -1 },
};
if (CMD_ARGC > 0) {
n = jim_nvp_name2value_simple(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
n = nvp_name2value(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
if (!n->name)
return ERROR_COMMAND_SYNTAX_ERROR;
ftdi_jtag_mode = n->value;
}
n = jim_nvp_value2name_simple(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
n = nvp_value2name(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
command_print(CMD, "ftdi samples TDO on %s edge of TCK", n->name);
return ERROR_OK;

View File

@ -313,7 +313,7 @@ struct mpsse_ctx *mpsse_open(const uint16_t vids[], const uint16_t pids[], const
int err;
if (!ctx)
return 0;
return NULL;
bit_copy_queue_init(&ctx->read_queue);
ctx->read_chunk_size = 16384;
@ -348,7 +348,7 @@ struct mpsse_ctx *mpsse_open(const uint16_t vids[], const uint16_t pids[], const
description ? description : "*",
serial ? serial : "*",
location ? location : "*");
ctx->usb_dev = 0;
ctx->usb_dev = NULL;
goto error;
}
@ -378,7 +378,7 @@ struct mpsse_ctx *mpsse_open(const uint16_t vids[], const uint16_t pids[], const
return ctx;
error:
mpsse_close(ctx);
return 0;
return NULL;
}
void mpsse_close(struct mpsse_ctx *ctx)
@ -465,13 +465,13 @@ static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_
void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
unsigned length, uint8_t mode)
{
mpsse_clock_data(ctx, out, out_offset, 0, 0, length, mode);
mpsse_clock_data(ctx, out, out_offset, NULL, 0, length, mode);
}
void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length,
uint8_t mode)
{
mpsse_clock_data(ctx, 0, 0, in, in_offset, length, mode);
mpsse_clock_data(ctx, NULL, 0, in, in_offset, length, mode);
}
void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
@ -548,7 +548,7 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of
void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
unsigned length, bool tdi, uint8_t mode)
{
mpsse_clock_tms_cs(ctx, out, out_offset, 0, 0, length, tdi, mode);
mpsse_clock_tms_cs(ctx, out, out_offset, NULL, 0, length, tdi, mode);
}
void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
@ -842,7 +842,7 @@ int mpsse_flush(struct mpsse_ctx *ctx)
if (ctx->write_count == 0)
return retval;
struct libusb_transfer *read_transfer = 0;
struct libusb_transfer *read_transfer = NULL;
struct transfer_result read_result = { .ctx = ctx, .done = true };
if (ctx->read_count) {
buffer_write_byte(ctx, 0x87); /* SEND_IMMEDIATE */

View File

@ -347,7 +347,7 @@ static int opendous_init(void)
opendous_jtag_handle = opendous_usb_open();
if (opendous_jtag_handle == 0) {
if (!opendous_jtag_handle) {
LOG_ERROR("Cannot find opendous Interface! Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}

View File

@ -411,9 +411,13 @@ COMMAND_HANDLER(parport_handle_parport_cable_command)
return ERROR_OK;
/* only if the cable name wasn't overwritten by cmdline */
if (parport_cable == 0) {
if (!parport_cable) {
/* REVISIT first verify that it's listed in cables[] ... */
parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
if (!parport_cable) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
strcpy(parport_cable, CMD_ARGV[0]);
}

View File

@ -632,7 +632,7 @@ static int dtc_queue_run(void)
uint8_t dtc_mask, tdo_mask;
uint8_t reply_buffer[USB_EP2IN_SIZE];
assert((dtc_queue.rq_head != 0) == (dtc_queue.reply_index > 0));
assert((!!dtc_queue.rq_head) == (dtc_queue.reply_index > 0));
assert(dtc_queue.cmd_index < USB_EP2BANK_SIZE);
assert(dtc_queue.reply_index <= USB_EP2IN_SIZE);

View File

@ -3694,7 +3694,7 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode
h = calloc(1, sizeof(struct stlink_usb_handle_s));
if (h == 0) {
if (!h) {
LOG_DEBUG("malloc failed");
return ERROR_FAIL;
}

View File

@ -571,7 +571,7 @@ static struct bitbang_interface sysfsgpio_bitbang = {
.swdio_read = sysfsgpio_swdio_read,
.swdio_drive = sysfsgpio_swdio_drive,
.swd_write = sysfsgpio_swd_write,
.blink = 0
.blink = NULL,
};
/* helper func to close and cleanup files only if they were valid/ used */

View File

@ -369,7 +369,7 @@ static int icdi_usb_query(void *handle)
if (h->max_packet != ICDI_PACKET_SIZE) {
h->read_buffer = realloc(h->read_buffer, h->max_packet);
h->write_buffer = realloc(h->write_buffer, h->max_packet);
if (h->read_buffer == 0 || h->write_buffer == 0) {
if (!h->read_buffer || !h->write_buffer) {
LOG_ERROR("unable to reallocate memory");
return ERROR_FAIL;
}
@ -664,7 +664,7 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
h = calloc(1, sizeof(struct icdi_usb_handle_s));
if (h == 0) {
if (!h) {
LOG_ERROR("unable to allocate memory");
return ERROR_FAIL;
}
@ -712,7 +712,7 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
h->write_buffer = malloc(ICDI_PACKET_SIZE);
h->max_packet = ICDI_PACKET_SIZE;
if (h->read_buffer == 0 || h->write_buffer == 0) {
if (!h->read_buffer || !h->write_buffer) {
LOG_DEBUG("malloc failed");
goto error_open;
}

View File

@ -148,7 +148,7 @@ static int usbprog_init(void)
usbprog_jtag_handle = usbprog_jtag_open();
tms_chain_index = 0;
if (usbprog_jtag_handle == 0) {
if (!usbprog_jtag_handle) {
LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}

View File

@ -344,7 +344,7 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem)
return rc;
}
int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
static int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
{
uint8_t num_pre, num_post, tdi, tms;
unsigned int num, anum, bytes, hwords, words;
@ -420,7 +420,7 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count)
return rc;
}
int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count)
static int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count)
{
unsigned int num, awidth, wwidth;
unsigned int req, waddr, rwords;

View File

@ -1300,7 +1300,7 @@ static int xds110_swd_run_queue(void)
/* Transfer results into caller's buffers */
for (result = 0; result < xds110.txn_result_count; result++)
if (xds110.txn_dap_results[result] != 0)
if (xds110.txn_dap_results[result])
*xds110.txn_dap_results[result] = dap_results[result];
xds110.txn_request_size = 0;
@ -1611,7 +1611,7 @@ static void xds110_flush(void)
}
bits = 0;
}
if (xds110.txn_scan_results[result].buffer != 0)
if (xds110.txn_scan_results[result].buffer)
bit_copy(xds110.txn_scan_results[result].buffer, 0, data_pntr,
bits, xds110.txn_scan_results[result].num_bits);
bits += xds110.txn_scan_results[result].num_bits;
@ -1687,8 +1687,8 @@ static void xds110_execute_pathmove(struct jtag_command *cmd)
if (num_states == 0)
return;
path = (uint8_t *)malloc(num_states * sizeof(uint8_t));
if (path == 0) {
path = malloc(num_states * sizeof(uint8_t));
if (!path) {
LOG_ERROR("XDS110: unable to allocate memory");
return;
}
@ -1766,7 +1766,7 @@ static void xds110_queue_scan(struct jtag_command *cmd)
/* Clear data out buffer to default value of all zeros */
memset((void *)buffer, 0x00, total_bytes);
for (i = 0; i < cmd->cmd.scan->num_fields; i++) {
if (cmd->cmd.scan->fields[i].out_value != 0) {
if (cmd->cmd.scan->fields[i].out_value) {
/* Copy over data to scan out into request buffer */
bit_copy(buffer, offset, cmd->cmd.scan->fields[i].out_value, 0,
cmd->cmd.scan->fields[i].num_bits);

View File

@ -72,181 +72,134 @@ static bool scan_is_safe(tap_state_t state)
}
}
static int jim_command_drscan(Jim_Interp *interp, int argc, Jim_Obj * const *args)
static COMMAND_HELPER(handle_jtag_command_drscan_fields, struct scan_field *fields)
{
int retval;
struct scan_field *fields;
int num_fields;
int field_count = 0;
int i, e;
struct jtag_tap *tap;
tap_state_t endstate;
/* args[1] = device
* args[2] = num_bits
* args[3] = hex string
* ... repeat num bits and hex string ...
*
* .. optionally:
* args[N-2] = "-endstate"
* args[N-1] = statename
*/
if ((argc < 4) || ((argc % 2) != 0)) {
Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
return JIM_ERR;
}
endstate = TAP_IDLE;
/* validate arguments as numbers */
e = JIM_OK;
for (i = 2; i < argc; i += 2) {
long bits;
const char *cp;
e = Jim_GetLong(interp, args[i], &bits);
/* If valid - try next arg */
if (e == JIM_OK)
continue;
/* Not valid.. are we at the end? */
if (((i + 2) != argc)) {
/* nope, then error */
return e;
}
/* it could be: "-endstate FOO"
* e.g. DRPAUSE so we can issue more instructions
* before entering RUN/IDLE and executing them.
*/
/* get arg as a string. */
cp = Jim_GetString(args[i], NULL);
/* is it the magic? */
if (strcmp("-endstate", cp) == 0) {
/* is the statename valid? */
cp = Jim_GetString(args[i + 1], NULL);
/* see if it is a valid state name */
endstate = tap_state_by_name(cp);
if (endstate < 0) {
/* update the error message */
Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
} else {
if (!scan_is_safe(endstate))
LOG_WARNING("drscan with unsafe "
"endstate \"%s\"", cp);
/* valid - so clear the error */
e = JIM_OK;
/* and remove the last 2 args */
argc -= 2;
}
}
/* Still an error? */
if (e != JIM_OK)
return e; /* too bad */
} /* validate args */
assert(e == JIM_OK);
tap = jtag_tap_by_jim_obj(interp, args[1]);
if (!tap)
return JIM_ERR;
num_fields = (argc-2)/2;
if (num_fields <= 0) {
Jim_SetResultString(interp, "drscan: no scan fields supplied", -1);
return JIM_ERR;
}
fields = malloc(sizeof(struct scan_field) * num_fields);
for (i = 2; i < argc; i += 2) {
long bits;
int len;
const char *str;
Jim_GetLong(interp, args[i], &bits);
str = Jim_GetString(args[i + 1], &len);
unsigned int field_count = 0;
for (unsigned int i = 1; i < CMD_ARGC; i += 2) {
unsigned int bits;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i], bits);
fields[field_count].num_bits = bits;
void *t = malloc(DIV_ROUND_UP(bits, 8));
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
fields[field_count].out_value = t;
str_to_buf(str, len, t, bits, 0);
str_to_buf(CMD_ARGV[i + 1], strlen(CMD_ARGV[i + 1]), t, bits, 0);
fields[field_count].in_value = t;
field_count++;
}
return ERROR_OK;
}
COMMAND_HANDLER(handle_jtag_command_drscan)
{
/*
* CMD_ARGV[0] = device
* CMD_ARGV[1] = num_bits
* CMD_ARGV[2] = hex string
* ... repeat num bits and hex string ...
*
* ... optionally:
* CMD_ARGV[CMD_ARGC-2] = "-endstate"
* CMD_ARGV[CMD_ARGC-1] = statename
*/
if (CMD_ARGC < 3 || (CMD_ARGC % 2) != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[0]);
if (!tap) {
command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[0]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (tap->bypass) {
command_print(CMD, "Can't execute as the selected tap is in BYPASS");
return ERROR_FAIL;
}
tap_state_t endstate = TAP_IDLE;
if (CMD_ARGC > 3 && !strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2])) {
const char *state_name = CMD_ARGV[CMD_ARGC - 1];
endstate = tap_state_by_name(state_name);
if (endstate < 0) {
command_print(CMD, "endstate: %s invalid", state_name);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (!scan_is_safe(endstate))
LOG_WARNING("drscan with unsafe endstate \"%s\"", state_name);
CMD_ARGC -= 2;
}
unsigned int num_fields = (CMD_ARGC - 1) / 2;
struct scan_field *fields = calloc(num_fields, sizeof(struct scan_field));
if (!fields) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
int retval = CALL_COMMAND_HANDLER(handle_jtag_command_drscan_fields, fields);
if (retval != ERROR_OK)
goto fail;
jtag_add_dr_scan(tap, num_fields, fields, endstate);
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
Jim_SetResultString(interp, "drscan: jtag execute failed", -1);
for (i = 0; i < field_count; i++)
free(fields[i].in_value);
free(fields);
return JIM_ERR;
command_print(CMD, "drscan: jtag execute failed");
goto fail;
}
field_count = 0;
Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
for (i = 2; i < argc; i += 2) {
long bits;
char *str;
Jim_GetLong(interp, args[i], &bits);
str = buf_to_hex_str(fields[field_count].in_value, bits);
free(fields[field_count].in_value);
Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
for (unsigned int i = 0; i < num_fields; i++) {
char *str = buf_to_hex_str(fields[i].in_value, fields[i].num_bits);
command_print(CMD, "%s", str);
free(str);
field_count++;
}
Jim_SetResult(interp, list);
fail:
for (unsigned int i = 0; i < num_fields; i++)
free(fields[i].in_value);
free(fields);
return JIM_OK;
return retval;
}
static int jim_command_pathmove(Jim_Interp *interp, int argc, Jim_Obj * const *args)
COMMAND_HANDLER(handle_jtag_command_pathmove)
{
tap_state_t states[8];
if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1))) {
Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
return JIM_ERR;
}
if (CMD_ARGC < 1 || CMD_ARGC > ARRAY_SIZE(states))
return ERROR_COMMAND_SYNTAX_ERROR;
int i;
for (i = 0; i < argc-1; i++) {
const char *cp;
cp = Jim_GetString(args[i + 1], NULL);
states[i] = tap_state_by_name(cp);
for (unsigned int i = 0; i < CMD_ARGC; i++) {
states[i] = tap_state_by_name(CMD_ARGV[i]);
if (states[i] < 0) {
/* update the error message */
Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
return JIM_ERR;
command_print(CMD, "endstate: %s invalid", CMD_ARGV[i]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
if ((jtag_add_statemove(states[0]) != ERROR_OK) || (jtag_execute_queue() != ERROR_OK)) {
Jim_SetResultString(interp, "pathmove: jtag execute failed", -1);
return JIM_ERR;
int retval = jtag_add_statemove(states[0]);
if (retval == ERROR_OK)
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
command_print(CMD, "pathmove: jtag execute failed");
return retval;
}
jtag_add_pathmove(argc - 2, states + 1);
if (jtag_execute_queue() != ERROR_OK) {
Jim_SetResultString(interp, "pathmove: failed", -1);
return JIM_ERR;
jtag_add_pathmove(CMD_ARGC - 1, states + 1);
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
command_print(CMD, "pathmove: failed");
return retval;
}
return JIM_OK;
return ERROR_OK;
}
COMMAND_HANDLER(handle_jtag_flush_count)
@ -274,10 +227,10 @@ static const struct command_registration jtag_command_handlers_to_move[] = {
{
.name = "drscan",
.mode = COMMAND_EXEC,
.jim_handler = jim_command_drscan,
.handler = handle_jtag_command_drscan,
.help = "Execute Data Register (DR) scan for one TAP. "
"Other TAPs must be in BYPASS mode.",
.usage = "tap_name [num_bits value]* ['-endstate' state_name]",
.usage = "tap_name (num_bits value)+ ['-endstate' state_name]",
},
{
.name = "flush_count",
@ -290,7 +243,7 @@ static const struct command_registration jtag_command_handlers_to_move[] = {
{
.name = "pathmove",
.mode = COMMAND_EXEC,
.jim_handler = jim_command_pathmove,
.handler = handle_jtag_command_pathmove,
.usage = "start_state state1 [state2 [state3 ...]]",
.help = "Move JTAG state machine from current state "
"(start_state) to state1, then state2, state3, etc.",

View File

@ -2,9 +2,26 @@
noinst_LTLIBRARIES += %D%/libpld.la
%C%_libpld_la_SOURCES = \
%D%/certus.c \
%D%/ecp2_3.c \
%D%/ecp5.c \
%D%/efinix.c \
%D%/gatemate.c \
%D%/gowin.c \
%D%/intel.c \
%D%/lattice.c \
%D%/lattice_bit.c \
%D%/pld.c \
%D%/raw_bit.c \
%D%/xilinx_bit.c \
%D%/virtex2.c \
%D%/certus.h \
%D%/ecp2_3.h \
%D%/ecp5.h \
%D%/lattice.h \
%D%/lattice_bit.h \
%D%/lattice_cmd.h \
%D%/pld.h \
%D%/raw_bit.h \
%D%/xilinx_bit.h \
%D%/virtex2.h

233
src/pld/certus.c Normal file
View File

@ -0,0 +1,233 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "certus.h"
#include "lattice.h"
#include "lattice_cmd.h"
#define LSC_ENABLE_X 0x74
#define LSC_REFRESH 0x79
#define LSC_DEVICE_CTRL 0x7D
int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t out)
{
return lattice_read_u64_register(tap, LSC_READ_STATUS, status, out);
}
int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out)
{
return lattice_read_u32_register(tap, READ_USERCODE, usercode, out, false);
}
int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode)
{
LOG_ERROR("Not supported to write usercode on certus devices");
return ERROR_FAIL;
}
static int lattice_certus_enable_transparent_mode(struct jtag_tap *tap)
{
struct scan_field field;
int retval = lattice_set_instr(tap, LSC_ENABLE_X, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
uint8_t buffer = 0x0;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
return jtag_execute_queue();
}
static int lattice_certus_erase_device(struct lattice_pld_device *lattice_device)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IRPAUSE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer = 8;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
retval = lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
buffer = 0;
field.num_bits = 8;
field.out_value = &buffer;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
retval = lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
buffer = 0;
field.num_bits = 8;
field.out_value = &buffer;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(100, TAP_IDLE);
jtag_add_sleep(5000);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
/* check done is cleared and fail is cleared */
const uint64_t status_done_flag = 0x100;
const uint64_t status_fail_flag = 0x2000;
return lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_done_flag | status_fail_flag);
}
static int lattice_certus_enable_programming(struct jtag_tap *tap)
{
struct scan_field field;
int retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
uint8_t buffer = 0;
field.num_bits = 8;
field.out_value = &buffer;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
return jtag_execute_queue();
}
static int lattice_certus_init_address(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
return jtag_execute_queue();
}
static int lattice_certus_exit_programming_mode(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(100, TAP_IDLE);
return jtag_execute_queue();
}
static int lattice_certus_program_config_map(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
{
struct scan_field field;
int retval = lattice_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
field.out_value = bit_file->raw_bit.data + bit_file->offset;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
return jtag_execute_queue();
}
int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_preload(lattice_device);
if (retval != ERROR_OK)
return retval;
/* check password protection is disabled */
const uint64_t status_pwd_protection = 0x20000;
retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_pwd_protection);
if (retval != ERROR_OK) {
LOG_ERROR("Password protection is set");
return retval;
}
retval = lattice_certus_enable_transparent_mode(tap);
if (retval != ERROR_OK)
return retval;
/* Check the SRAM Erase Lock */
const uint64_t status_otp = 0x40;
retval = lattice_verify_status_register_u64(lattice_device, 0x0, status_otp, status_otp);
if (retval != ERROR_OK) {
LOG_ERROR("NV User Feature Sector OTP is Set");
return retval;
}
/* Check the SRAM Lock */
const uint64_t status_write_protected = 0x400;
retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_write_protected);
if (retval != ERROR_OK) {
LOG_ERROR("NV User Feature Sector OTP is Set");
return retval;
}
retval = lattice_certus_enable_programming(tap);
if (retval != ERROR_OK) {
LOG_ERROR("failed to enable programming mode");
return retval;
}
retval = lattice_certus_erase_device(lattice_device);
if (retval != ERROR_OK) {
LOG_ERROR("erasing device failed");
return retval;
}
retval = lattice_certus_init_address(tap);
if (retval != ERROR_OK)
return retval;
retval = lattice_certus_program_config_map(tap, bit_file);
if (retval != ERROR_OK)
return retval;
const uint32_t expected = 0x100; // done
const uint32_t mask = expected |
0x3000 | // Busy Flag and Fail Flag
0xf000000; // BSE Error
retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x100, mask);
if (retval != ERROR_OK)
return retval;
return lattice_certus_exit_programming_mode(tap);
}

18
src/pld/certus.h Normal file
View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_CERTUS_H
#define OPENOCD_PLD_CERTUS_H
#include "lattice.h"
int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t out);
int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
#endif /* OPENOCD_PLD_CERTUS_H */

251
src/pld/ecp2_3.c Normal file
View File

@ -0,0 +1,251 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "ecp2_3.h"
#include "lattice.h"
#define LSCC_REFRESH 0x23
#define ISC_ENABLE 0x15
#define LSCC_RESET_ADDRESS 0x21
#define ISC_PROGRAM_USERCODE 0x1A
#define ISC_ERASE 0x03
#define READ_USERCODE 0x17
#define ISC_DISABLE 0x1E
#define LSCC_READ_STATUS 0x53
#define LSCC_BITSTREAM_BURST 0x02
#define STATUS_DONE_BIT 0x00020000
#define STATUS_ERROR_BITS_ECP2 0x00040003
#define STATUS_ERROR_BITS_ECP3 0x00040007
#define REGISTER_ALL_BITS_1 0xffffffff
#define REGISTER_ALL_BITS_0 0x00000000
int lattice_ecp2_3_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t out, bool do_idle)
{
return lattice_read_u32_register(tap, LSCC_READ_STATUS, status, out, do_idle);
}
int lattice_ecp2_3_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out)
{
return lattice_read_u32_register(tap, READ_USERCODE, usercode, out, false);
}
int lattice_ecp2_3_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(20000);
retval = lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer[4];
h_u32_to_le(buffer, usercode);
field.num_bits = 32;
field.out_value = buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(2000);
retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(200000);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
return lattice_verify_usercode(lattice_device, 0x0, usercode, REGISTER_ALL_BITS_1);
}
static int lattice_ecp2_3_erase_device(struct lattice_pld_device *lattice_device)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
/* program user code with all bits set */
int retval = lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IRPAUSE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer[4] = {0xff, 0xff, 0xff, 0xff};
field.num_bits = 32;
field.out_value = buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(2000);
/* verify every bit is set */
const uint32_t out = REGISTER_ALL_BITS_1;
const uint32_t mask = REGISTER_ALL_BITS_1;
const uint32_t expected_pre = REGISTER_ALL_BITS_1;
retval = lattice_verify_usercode(lattice_device, out, expected_pre, mask);
if (retval != ERROR_OK)
return retval;
retval = lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
if (lattice_device->family == LATTICE_ECP2)
jtag_add_sleep(100000);
else
jtag_add_sleep(2000000);
retval = lattice_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(2000);
/* after erasing check all bits in user register are cleared */
const uint32_t expected_post = REGISTER_ALL_BITS_0;
return lattice_verify_usercode(lattice_device, out, expected_post, mask);
}
static int lattice_ecp2_3_program_config_map(struct lattice_pld_device *lattice_device,
struct lattice_bit_file *bit_file)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(2000);
struct scan_field field;
retval = lattice_set_instr(tap, LSCC_BITSTREAM_BURST, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
field.out_value = bit_file->raw_bit.data + bit_file->offset;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(256, TAP_IDLE);
jtag_add_sleep(2000);
return jtag_execute_queue();
}
static int lattice_ecp2_3_exit_programming_mode(struct lattice_pld_device *lattice_device)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(200000);
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(100, TAP_IDLE);
jtag_add_sleep(1000);
return jtag_execute_queue();
}
int lattice_ecp2_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_preload(lattice_device);
if (retval != ERROR_OK)
return retval;
/* Enable the programming mode */
retval = lattice_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(20000);
/* Erase the device */
retval = lattice_ecp2_3_erase_device(lattice_device);
if (retval != ERROR_OK)
return retval;
/* Program Fuse Map */
retval = lattice_ecp2_3_program_config_map(lattice_device, bit_file);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp2_3_exit_programming_mode(lattice_device);
if (retval != ERROR_OK)
return retval;
const uint32_t out = REGISTER_ALL_BITS_1;
const uint32_t mask = STATUS_DONE_BIT | STATUS_ERROR_BITS_ECP2;
const uint32_t expected = STATUS_DONE_BIT;
return lattice_verify_status_register_u32(lattice_device, out, expected, mask, false);
}
int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
/* Program Bscan register */
int retval = lattice_preload(lattice_device);
if (retval != ERROR_OK)
return retval;
/* Enable the programming mode */
retval = lattice_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(500000);
retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(20000);
retval = lattice_ecp2_3_erase_device(lattice_device);
if (retval != ERROR_OK)
return retval;
/* Program Fuse Map */
retval = lattice_ecp2_3_program_config_map(lattice_device, bit_file);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp2_3_exit_programming_mode(lattice_device);
if (retval != ERROR_OK)
return retval;
const uint32_t out = REGISTER_ALL_BITS_1;
const uint32_t mask = STATUS_DONE_BIT | STATUS_ERROR_BITS_ECP3;
const uint32_t expected = STATUS_DONE_BIT;
return lattice_verify_status_register_u32(lattice_device, out, expected, mask, false);
}

19
src/pld/ecp2_3.h Normal file
View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_ECP2_3_H
#define OPENOCD_PLD_ECP2_3_H
#include "lattice.h"
int lattice_ecp2_3_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t out, bool do_idle);
int lattice_ecp2_3_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
int lattice_ecp2_3_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
int lattice_ecp2_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
#endif /* OPENOCD_PLD_ECP2_3_H */

207
src/pld/ecp5.c Normal file
View File

@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "ecp5.h"
#include "lattice.h"
#include "lattice_cmd.h"
#define ISC_PROGRAM_USERCODE 0xC2
#define STATUS_DONE_BIT 0x00000100
#define STATUS_ERROR_BITS 0x00020040
#define STATUS_FEA_OTP 0x00004000
#define STATUS_FAIL_FLAG 0x00002000
#define STATUS_BUSY_FLAG 0x00001000
#define REGISTER_ALL_BITS_1 0xffffffff
int lattice_ecp5_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t out, bool do_idle)
{
return lattice_read_u32_register(tap, LSC_READ_STATUS, status, out, do_idle);
}
int lattice_ecp5_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out)
{
return lattice_read_u32_register(tap, READ_USERCODE, usercode, out, true);
}
int lattice_ecp5_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(20000);
retval = lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
uint8_t buffer[4];
struct scan_field field;
h_u32_to_le(buffer, usercode);
field.num_bits = 32;
field.out_value = buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(2000);
retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(5, TAP_IDLE);
jtag_add_sleep(200000);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
return lattice_verify_usercode(lattice_device, 0x0, usercode, REGISTER_ALL_BITS_1);
}
static int lattice_ecp5_enable_sram_programming(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer = 0x0;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(10000);
return jtag_execute_queue();
}
static int lattice_ecp5_erase_sram(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer = 1;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(200000);
return jtag_execute_queue();
}
static int lattice_ecp5_init_address(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
struct scan_field field;
uint8_t buffer = 1;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(10000);
return jtag_execute_queue();
}
static int lattice_ecp5_program_config_map(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
{
int retval = lattice_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(10000);
struct scan_field field;
field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
field.out_value = bit_file->raw_bit.data + bit_file->offset;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(100, TAP_IDLE);
jtag_add_sleep(10000);
return jtag_execute_queue();
}
static int lattice_ecp5_exit_programming_mode(struct jtag_tap *tap)
{
int retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(200000);
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(1000);
return jtag_execute_queue();
}
int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
int retval = lattice_preload(lattice_device);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp5_enable_sram_programming(tap);
if (retval != ERROR_OK)
return retval;
const uint32_t out = 0x0;
const uint32_t expected1 = 0x0;
const uint32_t mask1 = STATUS_ERROR_BITS | STATUS_FEA_OTP;
retval = lattice_verify_status_register_u32(lattice_device, out, expected1, mask1, true);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp5_erase_sram(tap);
if (retval != ERROR_OK)
return retval;
const uint32_t mask2 = STATUS_FAIL_FLAG | STATUS_BUSY_FLAG;
retval = lattice_verify_status_register_u32(lattice_device, out, expected1, mask2, false);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp5_init_address(tap);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp5_program_config_map(tap, bit_file);
if (retval != ERROR_OK)
return retval;
retval = lattice_ecp5_exit_programming_mode(tap);
if (retval != ERROR_OK)
return retval;
const uint32_t expected2 = STATUS_DONE_BIT;
const uint32_t mask3 = STATUS_DONE_BIT | STATUS_FAIL_FLAG;
return lattice_verify_status_register_u32(lattice_device, out, expected2, mask3, false);
}

18
src/pld/ecp5.h Normal file
View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_ECP5_H
#define OPENOCD_PLD_ECP5_H
#include "lattice.h"
int lattice_ecp5_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t out, bool do_idle);
int lattice_ecp5_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
int lattice_ecp5_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
#endif /* OPENOCD_PLD_ECP5_H */

218
src/pld/efinix.c Normal file
View File

@ -0,0 +1,218 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/jtag.h>
#include "pld.h"
#include "raw_bit.h"
#define PROGRAM 0x4
#define ENTERUSER 0x7
#define TRAILING_ZEROS 4000
#define RUNTEST_START_CYCLES 100
#define RUNTEST_FINISH_CYCLES 100
struct efinix_pld_device {
struct jtag_tap *tap;
};
static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
{
FILE *input_file = fopen(filename, "r");
if (!input_file) {
LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
fseek(input_file, 0, SEEK_END);
long length = ftell(input_file);
fseek(input_file, 0, SEEK_SET);
if (length < 0 || ((length % 3))) {
fclose(input_file);
LOG_ERROR("Failed to get length from file %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
bit_file->length = DIV_ROUND_UP(length, 3);
bit_file->data = malloc(bit_file->length);
if (!bit_file->data) {
fclose(input_file);
LOG_ERROR("Out of memory");
return ERROR_PLD_FILE_LOAD_FAILED;
}
bool end_detected = false;
char buffer[3];
for (size_t idx = 0; !end_detected && idx < bit_file->length; ++idx) {
size_t read_count = fread(buffer, sizeof(char), 3, input_file);
end_detected = feof(input_file);
if ((read_count == 3 && buffer[2] != '\n') ||
(read_count != 3 && !end_detected) ||
(read_count != 2 && end_detected)) {
fclose(input_file);
free(bit_file->data);
bit_file->data = NULL;
LOG_ERROR("unexpected line length");
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (!isxdigit(buffer[0]) || !isxdigit(buffer[1])) {
fclose(input_file);
free(bit_file->data);
bit_file->data = NULL;
LOG_ERROR("unexpected char in hex string");
return ERROR_PLD_FILE_LOAD_FAILED;
}
unhexify(&bit_file->data[idx], buffer, 2);
}
fclose(input_file);
return ERROR_OK;
}
static int efinix_read_file(struct raw_bit_file *bit_file, const char *filename)
{
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
/* check if binary .bin or ascii .bit/.hex */
const char *file_ending_pos = strrchr(filename, '.');
if (!file_ending_pos) {
LOG_ERROR("Unable to detect filename suffix");
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (strcasecmp(file_ending_pos, ".bin") == 0) {
return cpld_read_raw_bit_file(bit_file, filename);
} else if ((strcasecmp(file_ending_pos, ".bit") == 0) ||
(strcasecmp(file_ending_pos, ".hex") == 0)) {
return efinix_read_bit_file(bit_file, filename);
}
LOG_ERROR("Unable to detect filetype");
return ERROR_PLD_FILE_LOAD_FAILED;
}
static int efinix_set_instr(struct jtag_tap *tap, uint8_t new_instr)
{
struct scan_field field;
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, TAP_IDLE);
free(t);
return ERROR_OK;
}
static int efinix_load(struct pld_device *pld_device, const char *filename)
{
struct raw_bit_file bit_file;
struct scan_field field[2];
if (!pld_device || !pld_device->driver_priv)
return ERROR_FAIL;
struct efinix_pld_device *efinix_info = pld_device->driver_priv;
if (!efinix_info || !efinix_info->tap)
return ERROR_FAIL;
struct jtag_tap *tap = efinix_info->tap;
jtag_add_tlr();
int retval = efinix_set_instr(tap, PROGRAM);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(RUNTEST_START_CYCLES, TAP_IDLE);
retval = efinix_set_instr(tap, PROGRAM); /* fix for T20 */
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
retval = efinix_read_file(&bit_file, filename);
if (retval != ERROR_OK)
return retval;
for (size_t i = 0; i < bit_file.length; i++)
bit_file.data[i] = flip_u32(bit_file.data[i], 8);
/* shift in the bitstream */
field[0].num_bits = bit_file.length * 8;
field[0].out_value = bit_file.data;
field[0].in_value = NULL;
/* followed by zeros */
field[1].num_bits = TRAILING_ZEROS;
uint8_t *buf = calloc(TRAILING_ZEROS / 8, 1);
if (!buf) {
free(bit_file.data);
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field[1].out_value = buf;
field[1].in_value = NULL;
jtag_add_dr_scan(tap, 2, field, TAP_DRPAUSE);
retval = jtag_execute_queue();
free(bit_file.data);
free(buf);
if (retval != ERROR_OK)
return retval;
retval = efinix_set_instr(tap, ENTERUSER);
if (retval != ERROR_OK)
return retval;
/* entering RUN/TEST for 100 cycles */
jtag_add_runtest(RUNTEST_FINISH_CYCLES, TAP_IDLE);
retval = jtag_execute_queue();
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
{
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
return ERROR_FAIL;
}
struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
if (!efinix_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
efinix_info->tap = tap;
pld->driver_priv = efinix_info;
return ERROR_OK;
}
struct pld_driver efinix_pld = {
.name = "efinix",
.pld_device_command = &efinix_pld_device_command,
.load = &efinix_load,
};

243
src/pld/gatemate.c Normal file
View File

@ -0,0 +1,243 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/jtag.h>
#include <jtag/adapter.h>
#include "pld.h"
#include "raw_bit.h"
#define JTAG_CONFIGURE 0x06
struct gatemate_pld_device {
struct jtag_tap *tap;
};
struct gatemate_bit_file {
struct raw_bit_file raw_file;
size_t capacity;
};
static int gatemate_add_byte_to_bitfile(struct gatemate_bit_file *bit_file, uint8_t byte)
{
const size_t chunk_size = 8192;
if (bit_file->raw_file.length + 1 > bit_file->capacity) {
uint8_t *buffer;
if (bit_file->raw_file.data)
buffer = realloc(bit_file->raw_file.data, bit_file->capacity + chunk_size);
else
buffer = malloc(chunk_size);
if (!buffer) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
bit_file->raw_file.data = buffer;
bit_file->capacity += chunk_size;
}
bit_file->raw_file.data[bit_file->raw_file.length++] = byte;
return ERROR_OK;
}
static int gatemate_read_cfg_line(struct gatemate_bit_file *bit_file, const char *line_buffer, size_t nread)
{
for (size_t idx = 0; idx < nread; ++idx) {
if (line_buffer[idx] == ' ') {
continue;
} else if (line_buffer[idx] == 0) {
break;
} else if (idx + 1 < nread) {
if (isxdigit(line_buffer[idx]) && isxdigit(line_buffer[idx + 1])) {
uint8_t byte;
unhexify(&byte, line_buffer + idx, 2);
int retval = gatemate_add_byte_to_bitfile(bit_file, byte);
if (retval != ERROR_OK)
return retval;
} else if (line_buffer[idx] == '/' && line_buffer[idx + 1] == '/') {
break;
}
++idx;
} else {
LOG_ERROR("parsing failed");
return ERROR_FAIL;
}
}
return ERROR_OK;
}
static int gatemate_getline(char **buffer, size_t *buf_size, FILE *input_file)
{
const size_t chunk_size = 32;
if (!*buffer)
*buf_size = 0;
size_t read = 0;
do {
if (read + 1 > *buf_size) {
char *new_buffer;
if (*buffer)
new_buffer = realloc(*buffer, *buf_size + chunk_size);
else
new_buffer = malloc(chunk_size);
if (!new_buffer) {
LOG_ERROR("Out of memory");
return -1;
}
*buffer = new_buffer;
*buf_size += chunk_size;
}
int c = fgetc(input_file);
if ((c == EOF && read) || (char)c == '\n') {
(*buffer)[read++] = 0;
return read;
} else if (c == EOF) {
return -1;
}
(*buffer)[read++] = (char)c;
} while (1);
return -1;
}
static int gatemate_read_cfg_file(struct gatemate_bit_file *bit_file, const char *filename)
{
FILE *input_file = fopen(filename, "r");
if (!input_file) {
LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
int retval = ERROR_OK;
char *line_buffer = NULL;
size_t buffer_length = 0;
int nread;
while (((nread = gatemate_getline(&line_buffer, &buffer_length, input_file)) != -1) && (retval == ERROR_OK))
retval = gatemate_read_cfg_line(bit_file, line_buffer, (size_t)nread);
if (line_buffer)
free(line_buffer);
fclose(input_file);
if (retval != ERROR_OK)
free(bit_file->raw_file.data);
return retval;
}
static int gatemate_read_file(struct gatemate_bit_file *bit_file, const char *filename)
{
memset(bit_file, 0, sizeof(struct gatemate_bit_file));
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
/* check if binary .bit or ascii .cfg */
const char *file_suffix_pos = strrchr(filename, '.');
if (!file_suffix_pos) {
LOG_ERROR("Unable to detect filename suffix");
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (strcasecmp(file_suffix_pos, ".bit") == 0)
return cpld_read_raw_bit_file(&bit_file->raw_file, filename);
else if (strcasecmp(file_suffix_pos, ".cfg") == 0)
return gatemate_read_cfg_file(bit_file, filename);
LOG_ERROR("Filetype not supported, expecting .bit or .cfg file");
return ERROR_PLD_FILE_LOAD_FAILED;
}
static int gatemate_set_instr(struct jtag_tap *tap, uint8_t new_instr)
{
struct scan_field field;
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, TAP_IDLE);
jtag_add_runtest(3, TAP_IDLE);
free(t);
return ERROR_OK;
}
static int gatemate_load(struct pld_device *pld_device, const char *filename)
{
if (!pld_device)
return ERROR_FAIL;
struct gatemate_pld_device *gatemate_info = pld_device->driver_priv;
if (!gatemate_info || !gatemate_info->tap)
return ERROR_FAIL;
struct jtag_tap *tap = gatemate_info->tap;
struct gatemate_bit_file bit_file;
int retval = gatemate_read_file(&bit_file, filename);
if (retval != ERROR_OK)
return retval;
retval = gatemate_set_instr(tap, JTAG_CONFIGURE);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
struct scan_field field;
field.num_bits = bit_file.raw_file.length * 8;
field.out_value = bit_file.raw_file.data;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
retval = jtag_execute_queue();
free(bit_file.raw_file.data);
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
{
struct jtag_tap *tap;
struct gatemate_pld_device *gatemate_info;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
return ERROR_FAIL;
}
gatemate_info = malloc(sizeof(struct gatemate_pld_device));
if (!gatemate_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
gatemate_info->tap = tap;
pld->driver_priv = gatemate_info;
return ERROR_OK;
}
struct pld_driver gatemate_pld = {
.name = "gatemate",
.pld_device_command = &gatemate_pld_device_command,
.load = &gatemate_load,
};

581
src/pld/gowin.c Normal file
View File

@ -0,0 +1,581 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/jtag.h>
#include <jtag/adapter.h>
#include <helper/bits.h>
#include "pld.h"
#include "raw_bit.h"
#define NO_OP 0x02
#define ERASE_SRAM 0x05
#define SRAM_ERASE_DONE 0x09
#define IDCODE 0x11
#define ADDRESS_INITIALIZATION 0x12
#define READ_USERCODE 0x13
#define CONFIG_ENABLE 0x15
#define TRANSFER_CONFIGURATION_DATA 0x17
#define CONFIG_DISABLE 0x3A
#define RELOAD 0x3C
#define STATUS_REGISTER 0x41
#define ERASE_FLASH 0x75
#define ENABLE_2ND_FLASH 0x78
#define STAUS_MASK_MEMORY_ERASE BIT(5)
#define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
struct gowin_pld_device {
struct jtag_tap *tap;
};
struct gowin_bit_file {
struct raw_bit_file raw_file;
size_t capacity;
uint32_t id;
uint16_t stored_checksum;
int compressed;
int crc_en;
uint16_t checksum;
uint8_t replace8x;
uint8_t replace4x;
uint8_t replace2x;
};
static uint64_t gowin_read_fs_file_bitsequence(const char *bits, int length)
{
uint64_t res = 0;
for (int i = 0; i < length; i++)
res = (res << 1) | (*bits++ == '1' ? 1 : 0);
return res;
}
static int gowin_add_byte_to_bit_file(struct gowin_bit_file *bit_file, uint8_t byte)
{
if (bit_file->raw_file.length + 1 > bit_file->capacity) {
uint8_t *buffer;
if (bit_file->raw_file.data)
buffer = realloc(bit_file->raw_file.data, bit_file->capacity + 8192);
else
buffer = malloc(8192);
if (!buffer) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
bit_file->raw_file.data = buffer;
bit_file->capacity += 8192;
}
bit_file->raw_file.data[bit_file->raw_file.length++] = byte;
return ERROR_OK;
}
static int gowin_read_fs_file_header(struct gowin_bit_file *bit_file, FILE *stream)
{
if (!bit_file)
return ERROR_FAIL;
int end_of_header = 0;
while (!end_of_header) {
char buffer[256];
char *line = fgets(buffer, 256, stream);
if (!line || feof(stream) || ferror(stream))
return ERROR_FAIL;
if (line[0] == '/')
continue;
size_t line_length = strlen(line);
if (line[line_length - 1] != '\n')
return ERROR_FAIL;
line_length--;
for (unsigned int i = 0; i < line_length; i += 8) {
uint8_t byte = gowin_read_fs_file_bitsequence(line + i, 8);
int retval = gowin_add_byte_to_bit_file(bit_file, byte);
if (retval != ERROR_OK)
return retval;
}
uint8_t key = gowin_read_fs_file_bitsequence(line, 8);
line += 8;
uint64_t value = gowin_read_fs_file_bitsequence(line, line_length - 8);
if (key == 0x06) {
bit_file->id = value & 0xffffffff;
} else if (key == 0x3B) {
end_of_header = 1;
bit_file->crc_en = (value & BIT(23)) ? 1 : 0;
}
}
return ERROR_OK;
}
static int gowin_read_fs_file(struct gowin_bit_file *bit_file, const char *filename)
{
FILE *input_file = fopen(filename, "r");
if (!input_file) {
LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
int retval = gowin_read_fs_file_header(bit_file, input_file);
if (retval != ERROR_OK) {
free(bit_file->raw_file.data);
fclose(input_file);
return retval;
}
char digits_buffer[9]; /* 8 + 1 trailing zero */
do {
char *digits = fgets(digits_buffer, 9, input_file);
if (feof(input_file))
break;
if (!digits || ferror(input_file)) {
free(bit_file->raw_file.data);
fclose(input_file);
return ERROR_FAIL;
}
if (digits[0] == '\n')
continue;
if (strlen(digits) != 8) {
free(bit_file->raw_file.data);
fclose(input_file);
return ERROR_FAIL;
}
uint8_t byte = gowin_read_fs_file_bitsequence(digits, 8);
retval = gowin_add_byte_to_bit_file(bit_file, byte);
if (retval != ERROR_OK) {
free(bit_file->raw_file.data);
fclose(input_file);
return ERROR_FAIL;
}
} while (1);
fclose(input_file);
return ERROR_OK;
}
static int gowin_read_file(struct gowin_bit_file *bit_file, const char *filename, bool *is_fs)
{
memset(bit_file, 0, sizeof(struct gowin_bit_file));
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
const char *file_suffix_pos = strrchr(filename, '.');
if (!file_suffix_pos) {
LOG_ERROR("Unable to detect filename suffix");
return ERROR_PLD_FILE_LOAD_FAILED;
}
/* check if binary .bin or ascii .fs */
if (strcasecmp(file_suffix_pos, ".bin") == 0) {
*is_fs = false;
return cpld_read_raw_bit_file(&bit_file->raw_file, filename);
} else if (strcasecmp(file_suffix_pos, ".fs") == 0) {
*is_fs = true;
return gowin_read_fs_file(bit_file, filename);
}
LOG_ERROR("Filetype not supported, expecting .fs or .bin file");
return ERROR_PLD_FILE_LOAD_FAILED;
}
static int gowin_set_instr(struct jtag_tap *tap, uint8_t new_instr)
{
struct scan_field field;
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, TAP_IDLE);
jtag_add_runtest(3, TAP_IDLE);
free(t);
return ERROR_OK;
}
static int gowin_read_register(struct jtag_tap *tap, uint32_t reg, uint32_t *result)
{
struct scan_field field;
int retval = gowin_set_instr(tap, reg);
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
uint8_t buf[4] = {0};
field.check_mask = NULL;
field.check_value = NULL;
field.num_bits = 32;
field.out_value = buf;
field.in_value = buf;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
retval = jtag_execute_queue();
*result = le_to_h_u32(buf);
return retval;
}
static int gowin_check_status_flag(struct jtag_tap *tap, uint32_t mask, uint32_t flag)
{
uint32_t status = 0;
int retries = 0;
do {
int retval = gowin_read_register(tap, STATUS_REGISTER, &status);
if (retval != ERROR_OK)
return retval;
if (retries++ == 100000)
return ERROR_FAIL;
} while ((status & mask) != flag);
return ERROR_OK;
}
static int gowin_enable_config(struct jtag_tap *tap)
{
int retval = gowin_set_instr(tap, CONFIG_ENABLE);
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE, STAUS_MASK_SYSTEM_EDIT_MODE);
}
static int gowin_disable_config(struct jtag_tap *tap)
{
int retval = gowin_set_instr(tap, CONFIG_DISABLE);
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE, 0);
}
static int gowin_reload(struct jtag_tap *tap)
{
int retval = gowin_set_instr(tap, RELOAD);
if (retval != ERROR_OK)
return retval;
retval = gowin_set_instr(tap, NO_OP);
if (retval != ERROR_OK)
return retval;
return jtag_execute_queue();
}
static int gowin_runtest_idle(struct jtag_tap *tap, unsigned int frac_sec)
{
int speed = adapter_get_speed_khz() * 1000;
int cycles = DIV_ROUND_UP(speed, frac_sec);
jtag_add_runtest(cycles, TAP_IDLE);
return jtag_execute_queue();
}
static int gowin_erase_sram(struct jtag_tap *tap, bool tx_erase_done)
{
/* config is already enabled */
int retval = gowin_set_instr(tap, ERASE_SRAM);
if (retval != ERROR_OK)
return retval;
retval = gowin_set_instr(tap, NO_OP);
if (retval != ERROR_OK)
return retval;
/* Delay or Run Test 2~10ms */
/* 10 ms is worst case for GW2A-55 */
jtag_add_sleep(10000);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
retval = gowin_check_status_flag(tap, STAUS_MASK_MEMORY_ERASE,
STAUS_MASK_MEMORY_ERASE);
if (retval != ERROR_OK)
return retval;
if (tx_erase_done) {
retval = gowin_set_instr(tap, SRAM_ERASE_DONE);
if (retval != ERROR_OK)
return retval;
retval = gowin_set_instr(tap, NO_OP);
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
/* gen clock cycles in RUN/IDLE for 500us -> 1/500us = 2000/s */
retval = gowin_runtest_idle(tap, 2000);
if (retval != ERROR_OK)
return retval;
}
retval = gowin_set_instr(tap, NO_OP);
if (retval != ERROR_OK)
return retval;
return jtag_execute_queue();
}
static int gowin_load_to_sram(struct pld_device *pld_device, const char *filename)
{
if (!pld_device)
return ERROR_FAIL;
struct gowin_pld_device *gowin_info = pld_device->driver_priv;
if (!gowin_info || !gowin_info->tap)
return ERROR_FAIL;
struct jtag_tap *tap = gowin_info->tap;
bool is_fs = false;
struct gowin_bit_file bit_file;
int retval = gowin_read_file(&bit_file, filename, &is_fs);
if (retval != ERROR_OK)
return retval;
for (unsigned int i = 0; i < bit_file.raw_file.length; i++)
bit_file.raw_file.data[i] = flip_u32(bit_file.raw_file.data[i], 8);
uint32_t id;
retval = gowin_read_register(tap, IDCODE, &id);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
if (is_fs && id != bit_file.id) {
free(bit_file.raw_file.data);
LOG_ERROR("Id on device (0x%8.8" PRIx32 ") and id in bit-stream (0x%8.8" PRIx32 ") don't match.",
id, bit_file.id);
return ERROR_FAIL;
}
retval = gowin_enable_config(tap);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
retval = gowin_erase_sram(tap, false);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
retval = gowin_set_instr(tap, ADDRESS_INITIALIZATION);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
retval = gowin_set_instr(tap, TRANSFER_CONFIGURATION_DATA);
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
/* scan out the bitstream */
struct scan_field field;
field.num_bits = bit_file.raw_file.length * 8;
field.out_value = bit_file.raw_file.data;
field.in_value = bit_file.raw_file.data;
jtag_add_dr_scan(gowin_info->tap, 1, &field, TAP_IDLE);
jtag_add_runtest(3, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
free(bit_file.raw_file.data);
return retval;
}
retval = gowin_disable_config(tap);
free(bit_file.raw_file.data);
if (retval != ERROR_OK)
return retval;
retval = gowin_set_instr(gowin_info->tap, NO_OP);
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
return retval;
}
static int gowin_read_register_command(struct pld_device *pld_device, uint32_t cmd, uint32_t *value)
{
if (!pld_device)
return ERROR_FAIL;
struct gowin_pld_device *gowin_info = pld_device->driver_priv;
if (!gowin_info || !gowin_info->tap)
return ERROR_FAIL;
return gowin_read_register(gowin_info->tap, cmd, value);
}
static int gowin_reload_command(struct pld_device *pld_device)
{
if (!pld_device)
return ERROR_FAIL;
struct gowin_pld_device *gowin_info = pld_device->driver_priv;
if (!gowin_info || !gowin_info->tap)
return ERROR_FAIL;
return gowin_reload(gowin_info->tap);
}
COMMAND_HANDLER(gowin_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
uint32_t status = 0;
int retval = gowin_read_register_command(device, STATUS_REGISTER, &status);
if (retval == ERROR_OK)
command_print(CMD, "0x%8.8" PRIx32, status);
return retval;
}
COMMAND_HANDLER(gowin_read_user_register_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
uint32_t user_reg = 0;
int retval = gowin_read_register_command(device, READ_USERCODE, &user_reg);
if (retval == ERROR_OK)
command_print(CMD, "0x%8.8" PRIx32, user_reg);
return retval;
}
COMMAND_HANDLER(gowin_reload_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
return gowin_reload_command(device);
}
static const struct command_registration gowin_exec_command_handlers[] = {
{
.name = "read_status",
.mode = COMMAND_EXEC,
.handler = gowin_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = gowin_read_user_register_command_handler,
.help = "reading user register from FPGA",
.usage = "num_pld",
}, {
.name = "reload",
.mode = COMMAND_EXEC,
.handler = gowin_reload_command_handler,
.help = "reloading bitstream from flash to SRAM",
.usage = "num_pld",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration gowin_command_handler[] = {
{
.name = "gowin",
.mode = COMMAND_ANY,
.help = "gowin specific commands",
.usage = "",
.chain = gowin_exec_command_handlers
},
COMMAND_REGISTRATION_DONE
};
PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
{
struct jtag_tap *tap;
struct gowin_pld_device *gowin_info;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
return ERROR_FAIL;
}
gowin_info = malloc(sizeof(struct gowin_pld_device));
if (!gowin_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
gowin_info->tap = tap;
pld->driver_priv = gowin_info;
return ERROR_OK;
}
struct pld_driver gowin_pld = {
.name = "gowin",
.commands = gowin_command_handler,
.pld_device_command = &gowin_pld_device_command,
.load = &gowin_load_to_sram,
};

474
src/pld/intel.c Normal file
View File

@ -0,0 +1,474 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/jtag.h>
#include <jtag/adapter.h>
#include <helper/system.h>
#include <helper/log.h>
#include "pld.h"
#include "raw_bit.h"
#define BYPASS 0x3FF
enum intel_family_e {
INTEL_CYCLONEIII,
INTEL_CYCLONEIV,
INTEL_CYCLONEV,
INTEL_CYCLONE10,
INTEL_ARRIAII,
INTEL_UNKNOWN
};
struct intel_pld_device {
struct jtag_tap *tap;
unsigned int boundary_scan_length;
int checkpos;
enum intel_family_e family;
};
struct intel_device_parameters_elem {
uint32_t id;
unsigned int boundary_scan_length;
int checkpos;
enum intel_family_e family;
};
static const struct intel_device_parameters_elem intel_device_parameters[] = {
{0x020f10dd, 603, 226, INTEL_CYCLONEIII}, /* EP3C5 EP3C10 */
{0x020f20dd, 1080, 409, INTEL_CYCLONEIII}, /* EP3C16 */
{0x020f30dd, 732, 286, INTEL_CYCLONEIII}, /* EP3C25 */
{0x020f40dd, 1632, 604, INTEL_CYCLONEIII}, /* EP3C40 */
{0x020f50dd, 1164, 442, INTEL_CYCLONEIII}, /* EP3C55 */
{0x020f60dd, 1314, 502, INTEL_CYCLONEIII}, /* EP3C80 */
{0x020f70dd, 1620, 613, INTEL_CYCLONEIII}, /* EP3C120*/
{0x027010dd, 1314, 226, INTEL_CYCLONEIII}, /* EP3CLS70 */
{0x027000dd, 1314, 226, INTEL_CYCLONEIII}, /* EP3CLS100 */
{0x027030dd, 1314, 409, INTEL_CYCLONEIII}, /* EP3CLS150 */
{0x027020dd, 1314, 409, INTEL_CYCLONEIII}, /* EP3CLS200 */
{0x020f10dd, 603, 226, INTEL_CYCLONEIV}, /* EP4CE6 EP4CE10 */
{0x020f20dd, 1080, 409, INTEL_CYCLONEIV}, /* EP4CE15 */
{0x020f30dd, 732, 286, INTEL_CYCLONEIV}, /* EP4CE22 */
{0x020f40dd, 1632, 604, INTEL_CYCLONEIV}, /* EP4CE30 EP4CE40 */
{0x020f50dd, 1164, 442, INTEL_CYCLONEIV}, /* EP4CE55 */
{0x020f60dd, 1314, 502, INTEL_CYCLONEIV}, /* EP4CE75 */
{0x020f70dd, 1620, 613, INTEL_CYCLONEIV}, /* EP4CE115 */
{0x028010dd, 260, 229, INTEL_CYCLONEIV}, /* EP4CGX15 */
{0x028120dd, 494, 463, INTEL_CYCLONEIV}, /* EP4CGX22 */
{0x028020dd, 494, 463, INTEL_CYCLONEIV}, /* EP4CGX30 */
{0x028230dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX30 */
{0x028130dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX50 */
{0x028030dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX75 */
{0x028140dd, 1495, 1438, INTEL_CYCLONEIV}, /* EP4CGX110 */
{0x028040dd, 1495, 1438, INTEL_CYCLONEIV}, /* EP4CGX150 */
{0x02b150dd, 864, 163, INTEL_CYCLONEV}, /* 5CEBA2F23 5CEBA2F17 5CEFA2M13 5CEFA2F23 5CEBA2U15 5CEFA2U19 5CEBA2U19 */
{0x02d020dd, 1485, 19, INTEL_CYCLONEV}, /* 5CSXFC6D6F31 5CSTFD6D5F31 5CSEBA6U23 5CSEMA6U23 5CSEBA6U19 5CSEBA6U23
5CSEBA6U19 5CSEMA6F31 5CSXFC6C6U23 */
{0x02b040dd, 1728, -1, INTEL_CYCLONEV}, /* 5CGXFC9EF35 5CGXBC9AU19 5CGXBC9CF23 5CGTFD9CF23 5CGXFC9AU19 5CGXFC9CF23
5CGXFC9EF31 5CGXFC9DF27 5CGXBC9DF27 5CGXBC9EF31 5CGTFD9EF31 5CGTFD9EF35
5CGTFD9AU19 5CGXBC9EF35 5CGTFD9DF27 */
{0x02b050dd, 864, 163, INTEL_CYCLONEV}, /* 5CEFA4U19 5CEFA4F23 5CEFA4M13 5CEBA4F17 5CEBA4U15 5CEBA4U19 5CEBA4F23 */
{0x02b030dd, 1488, 19, INTEL_CYCLONEV}, /* 5CGXBC7CU19 5CGTFD7CU19 5CGTFD7DF27 5CGXFC7BM15 5CGXFC7DF27 5CGXFC7DF31
5CGTFD7CF23 5CGXBC7CF23 5CGXBC7DF31 5CGTFD7BM15 5CGXFC7CU19 5CGTFD7DF31
5CGXBC7BM15 5CGXFC7CF23 5CGXBC7DF27 */
{0x02d120dd, 1485, -1, INTEL_CYCLONEV}, /* 5CSEBA5U23 5CSEBA5U23 5CSTFD5D5F31 5CSEBA5U19 5CSXFC5D6F31 5CSEMA5U23
5CSEMA5F31 5CSXFC5C6U23 5CSEBA5U19 */
{0x02b220dd, 1104, 19, INTEL_CYCLONEV}, /* 5CEBA5U19 5CEFA5U19 5CEFA5M13 5CEBA5F23 5CEFA5F23 */
{0x02b020dd, 1104, 19, INTEL_CYCLONEV}, /* 5CGXBC5CU19 5CGXFC5F6M11 5CGXFC5CM13 5CGTFD5CF23 5CGXBC5CF23 5CGTFD5CF27
5CGTFD5F5M11 5CGXFC5CF27 5CGXFC5CU19 5CGTFD5CM13 5CGXFC5CF23 5CGXBC5CF27
5CGTFD5CU19 */
{0x02d010dd, 1197, -1, INTEL_CYCLONEV}, /* 5CSEBA4U23 5CSXFC4C6U23 5CSEMA4U23 5CSEBA4U23 5CSEBA4U19 5CSEBA4U19
5CSXFC2C6U23 */
{0x02b120dd, 1104, 19, INTEL_CYCLONEV}, /* 5CGXFC4CM13 5CGXFC4CU19 5CGXFC4F6M11 5CGXBC4CU19 5CGXFC4CF27 5CGXBC4CF23
5CGXBC4CF27 5CGXFC4CF23 */
{0x02b140dd, 1728, -1, INTEL_CYCLONEV}, /* 5CEFA9F31 5CEBA9F31 5CEFA9F27 5CEBA9U19 5CEBA9F27 5CEFA9U19 5CEBA9F23
5CEFA9F23 */
{0x02b010dd, 720, 19, INTEL_CYCLONEV}, /* 5CGXFC3U15 5CGXBC3U15 5CGXFC3F23 5CGXFC3U19 5CGXBC3U19 5CGXBC3F23 */
{0x02b130dd, 1488, 19, INTEL_CYCLONEV}, /* 5CEFA7F31 5CEBA7F27 5CEBA7M15 5CEFA7U19 5CEBA7F23 5CEFA7F23 5CEFA7F27
5CEFA7M15 5CEBA7U19 5CEBA7F31 */
{0x02d110dd, 1197, -1, INTEL_CYCLONEV}, /* 5CSEBA2U23 5CSEMA2U23 5CSEBA2U23 5CSEBA2U19 5CSEBA2U19 */
{0x020f10dd, 603, 226, INTEL_CYCLONE10}, /* 10CL006E144 10CL006U256 10CL010M164 10CL010U256 10CL010E144 */
{0x020f20dd, 1080, 409, INTEL_CYCLONE10}, /* 10CL016U256 10CL016E144 10CL016U484 10CL016F484 10CL016M164 */
{0x020f30dd, 732, 286, INTEL_CYCLONE10}, /* 10CL025U256 10CL025E144 */
{0x020f40dd, 1632, 604, INTEL_CYCLONE10}, /* 10CL040F484 10CL040U484 */
{0x020f50dd, 1164, 442, INTEL_CYCLONE10}, /* 10CL055F484 10CL055U484 */
{0x020f60dd, 1314, 502, INTEL_CYCLONE10}, /* 10CL080F484 10CL080F780 10CL080U484 */
{0x020f70dd, 1620, 613, INTEL_CYCLONE10}, /* 10CL120F484 10CL120F780 */
{0x02e120dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX085U484 10CX085F672 */
{0x02e320dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX105F780 10CX105U484 10CX105F672 */
{0x02e720dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX150F672 10CX150F780 10CX150U484 */
{0x02ef20dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX220F672 10CX220F780 10CX220U484 */
{0x025120dd, 1227, 1174, INTEL_ARRIAII}, /* EP2AGX45 */
{0x025020dd, 1227, -1, INTEL_ARRIAII}, /* EP2AGX65 */
{0x025130dd, 1467, -1, INTEL_ARRIAII}, /* EP2AGX95 */
{0x025030dd, 1467, -1, INTEL_ARRIAII}, /* EP2AGX125 */
{0x025140dd, 1971, -1, INTEL_ARRIAII}, /* EP2AGX190 */
{0x025040dd, 1971, -1, INTEL_ARRIAII}, /* EP2AGX260 */
{0x024810dd, 2274, -1, INTEL_ARRIAII}, /* EP2AGZ225 */
{0x0240a0dd, 2682, -1, INTEL_ARRIAII}, /* EP2AGZ300 */
{0x024820dd, 2682, -1, INTEL_ARRIAII}, /* EP2AGZ350 */
};
static int intel_fill_device_parameters(struct intel_pld_device *intel_info)
{
for (size_t i = 0; i < ARRAY_SIZE(intel_device_parameters); ++i) {
if (intel_device_parameters[i].id == intel_info->tap->idcode &&
intel_info->family == intel_device_parameters[i].family) {
if (intel_info->boundary_scan_length == 0)
intel_info->boundary_scan_length = intel_device_parameters[i].boundary_scan_length;
if (intel_info->checkpos == -1)
intel_info->checkpos = intel_device_parameters[i].checkpos;
return ERROR_OK;
}
}
return ERROR_FAIL;
}
static int intel_check_for_unique_id(struct intel_pld_device *intel_info)
{
int found = 0;
for (size_t i = 0; i < ARRAY_SIZE(intel_device_parameters); ++i) {
if (intel_device_parameters[i].id == intel_info->tap->idcode) {
++found;
intel_info->family = intel_device_parameters[i].family;
}
}
return (found == 1) ? ERROR_OK : ERROR_FAIL;
}
static int intel_check_config(struct intel_pld_device *intel_info)
{
if (!intel_info->tap->hasidcode) {
LOG_ERROR("no IDCODE");
return ERROR_FAIL;
}
if (intel_info->family == INTEL_UNKNOWN) {
if (intel_check_for_unique_id(intel_info) != ERROR_OK) {
LOG_ERROR("id is ambiguous, please specify family");
return ERROR_FAIL;
}
}
if (intel_info->boundary_scan_length == 0 || intel_info->checkpos == -1) {
int ret = intel_fill_device_parameters(intel_info);
if (ret != ERROR_OK)
return ret;
}
if (intel_info->checkpos >= 0 && (unsigned int)intel_info->checkpos >= intel_info->boundary_scan_length) {
LOG_ERROR("checkpos has to be smaller than scan length %d < %u",
intel_info->checkpos, intel_info->boundary_scan_length);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int intel_read_file(struct raw_bit_file *bit_file, const char *filename)
{
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
/* check if binary .bin or ascii .bit/.hex */
const char *file_ending_pos = strrchr(filename, '.');
if (!file_ending_pos) {
LOG_ERROR("Unable to detect filename suffix");
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (strcasecmp(file_ending_pos, ".rbf") == 0)
return cpld_read_raw_bit_file(bit_file, filename);
LOG_ERROR("Unable to detect filetype");
return ERROR_PLD_FILE_LOAD_FAILED;
}
static int intel_set_instr(struct jtag_tap *tap, uint16_t new_instr)
{
struct scan_field field;
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, TAP_IDLE);
free(t);
return ERROR_OK;
}
static int intel_load(struct pld_device *pld_device, const char *filename)
{
unsigned int speed = adapter_get_speed_khz();
if (speed < 1)
speed = 1;
unsigned int cycles = DIV_ROUND_UP(speed, 200);
if (cycles < 1)
cycles = 1;
if (!pld_device || !pld_device->driver_priv)
return ERROR_FAIL;
struct intel_pld_device *intel_info = pld_device->driver_priv;
if (!intel_info || !intel_info->tap)
return ERROR_FAIL;
struct jtag_tap *tap = intel_info->tap;
int retval = intel_check_config(intel_info);
if (retval != ERROR_OK)
return retval;
struct raw_bit_file bit_file;
retval = intel_read_file(&bit_file, filename);
if (retval != ERROR_OK)
return retval;
if (retval != ERROR_OK)
return retval;
retval = intel_set_instr(tap, 0x002);
if (retval != ERROR_OK) {
free(bit_file.data);
return retval;
}
jtag_add_runtest(speed, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
free(bit_file.data);
return retval;
}
/* shift in the bitstream */
struct scan_field field;
field.num_bits = bit_file.length * 8;
field.out_value = bit_file.data;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE);
retval = jtag_execute_queue();
free(bit_file.data);
if (retval != ERROR_OK)
return retval;
retval = intel_set_instr(tap, 0x004);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(cycles, TAP_IDLE);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
if (intel_info->boundary_scan_length != 0) {
uint8_t *buf = calloc(DIV_ROUND_UP(intel_info->boundary_scan_length, 8), 1);
if (!buf) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.num_bits = intel_info->boundary_scan_length;
field.out_value = buf;
field.in_value = buf;
jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE);
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
free(buf);
return retval;
}
if (intel_info->checkpos != -1)
retval = ((buf[intel_info->checkpos / 8] & (1 << (intel_info->checkpos % 8)))) ?
ERROR_OK : ERROR_FAIL;
free(buf);
if (retval != ERROR_OK) {
LOG_ERROR("Check failed");
return ERROR_FAIL;
}
}
retval = intel_set_instr(tap, 0x003);
if (retval != ERROR_OK)
return retval;
switch (intel_info->family) {
case INTEL_CYCLONEIII:
case INTEL_CYCLONEIV:
jtag_add_runtest(5 * speed + 512, TAP_IDLE);
break;
case INTEL_CYCLONEV:
jtag_add_runtest(5 * speed + 512, TAP_IDLE);
break;
case INTEL_CYCLONE10:
jtag_add_runtest(DIV_ROUND_UP(512ul * speed, 125ul) + 512, TAP_IDLE);
break;
case INTEL_ARRIAII:
jtag_add_runtest(DIV_ROUND_UP(64ul * speed, 125ul) + 512, TAP_IDLE);
break;
case INTEL_UNKNOWN:
LOG_ERROR("unknown family");
return ERROR_FAIL;
}
retval = intel_set_instr(tap, BYPASS);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(speed, TAP_IDLE);
return jtag_execute_queue();
}
COMMAND_HANDLER(intel_set_bscan_command_handler)
{
int dev_id;
unsigned int boundary_scan_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], boundary_scan_length);
struct intel_pld_device *intel_info = pld_device->driver_priv;
if (!intel_info)
return ERROR_FAIL;
intel_info->boundary_scan_length = boundary_scan_length;
return ERROR_OK;
}
COMMAND_HANDLER(intel_set_check_pos_command_handler)
{
int dev_id;
int checkpos;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], checkpos);
struct intel_pld_device *intel_info = pld_device->driver_priv;
if (!intel_info)
return ERROR_FAIL;
intel_info->checkpos = checkpos;
return ERROR_OK;
}
PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
return ERROR_FAIL;
}
struct intel_pld_device *intel_info = malloc(sizeof(struct intel_pld_device));
if (!intel_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
enum intel_family_e family = INTEL_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcmp(CMD_ARGV[2], "cycloneiii") == 0) {
family = INTEL_CYCLONEIII;
} else if (strcmp(CMD_ARGV[2], "cycloneiv") == 0) {
family = INTEL_CYCLONEIV;
} else if (strcmp(CMD_ARGV[2], "cyclonev") == 0) {
family = INTEL_CYCLONEV;
} else if (strcmp(CMD_ARGV[2], "cyclone10") == 0) {
family = INTEL_CYCLONE10;
} else if (strcmp(CMD_ARGV[2], "arriaii") == 0) {
family = INTEL_ARRIAII;
} else {
command_print(CMD, "unknown family");
free(intel_info);
return ERROR_FAIL;
}
}
intel_info->tap = tap;
intel_info->boundary_scan_length = 0;
intel_info->checkpos = -1;
intel_info->family = family;
pld->driver_priv = intel_info;
return ERROR_OK;
}
static const struct command_registration intel_exec_command_handlers[] = {
{
.name = "set_bscan",
.mode = COMMAND_EXEC,
.handler = intel_set_bscan_command_handler,
.help = "set boundary scan register length of FPGA",
.usage = "num_pld len",
}, {
.name = "set_check_pos",
.mode = COMMAND_EXEC,
.handler = intel_set_check_pos_command_handler,
.help = "set check_pos of FPGA",
.usage = "num_pld pos",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration intel_command_handler[] = {
{
.name = "intel",
.mode = COMMAND_ANY,
.help = "intel specific commands",
.usage = "",
.chain = intel_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
struct pld_driver intel_pld = {
.name = "intel",
.commands = intel_command_handler,
.pld_device_command = &intel_pld_device_command,
.load = &intel_load,
};

529
src/pld/lattice.c Normal file
View File

@ -0,0 +1,529 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "lattice.h"
#include <jtag/jtag.h>
#include "pld.h"
#include "lattice_bit.h"
#include "ecp2_3.h"
#include "ecp5.h"
#include "certus.h"
#define PRELOAD 0x1C
struct lattice_devices_elem {
uint32_t id;
size_t preload_length;
enum lattice_family_e family;
};
static const struct lattice_devices_elem lattice_devices[] = {
{0x01270043, 654, LATTICE_ECP2 /* ecp2-6e */},
{0x01271043, 643, LATTICE_ECP2 /* ecp2-12e */},
{0x01272043, 827, LATTICE_ECP2 /* ecp2-20e */},
{0x01274043, 1011, LATTICE_ECP2 /* ecp2-35e */},
{0x01273043, 1219, LATTICE_ECP2 /* ecp2-50e */},
{0x01275043, 654, LATTICE_ECP2 /* ecp2-70e */},
{0x01279043, 680, LATTICE_ECP2 /* ecp2m20e */},
{0x0127A043, 936, LATTICE_ECP2 /* ecp2m35e */},
{0x0127B043, 1056, LATTICE_ECP2 /* ecp2m50e */},
{0x0127C043, 1039, LATTICE_ECP2 /* ecp2m70e */},
{0x0127D043, 1311, LATTICE_ECP2 /* ecp2m100e */},
{0x01010043, 467, LATTICE_ECP3 /* ecp3 lae3-17ea & lfe3-17ea*/},
{0x01012043, 675, LATTICE_ECP3 /* ecp3 lae3-35ea & lfe3-35ea*/},
{0x01014043, 1077, LATTICE_ECP3 /* ecp3 lfe3-70ea & lfe3-70e & lfe3-95ea && lfe3-95e*/},
{0x01015043, 1326, LATTICE_ECP3 /* ecp3 lfe3-150e*/},
{0x21111043, 409, LATTICE_ECP5 /* "LAE5U-12F & LFE5U-12F" */},
{0x41111043, 409, LATTICE_ECP5 /* "LFE5U-25F" */},
{0x41112043, 510, LATTICE_ECP5 /* "LFE5U-45F" */},
{0x41113043, 750, LATTICE_ECP5 /* "LFE5U-85F" */},
{0x81111043, 409, LATTICE_ECP5 /* "LFE5UM5G-25F" */},
{0x81112043, 510, LATTICE_ECP5 /* "LFE5UM5G-45F" */},
{0x81113043, 750, LATTICE_ECP5 /* "LFE5UM5G-85F" */},
{0x01111043, 409, LATTICE_ECP5 /* "LAE5UM-25F" */},
{0x01112043, 510, LATTICE_ECP5 /* "LAE5UM-45F" */},
{0x01113043, 750, LATTICE_ECP5 /* "LAE5UM-85F" */},
{0x310f0043, 362, LATTICE_CERTUS /* LFD2NX-17 */},
{0x310f1043, 362, LATTICE_CERTUS /* LFD2NX-40 */},
{0x010f4043, 362, LATTICE_CERTUS /* LFCPNX-100 */},
};
int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate)
{
struct scan_field field;
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, endstate);
free(t);
return ERROR_OK;
}
static int lattice_check_device_family(struct lattice_pld_device *lattice_device)
{
if (lattice_device->family != LATTICE_UNKNOWN && lattice_device->preload_length != 0)
return ERROR_OK;
if (!lattice_device->tap || !lattice_device->tap->hasidcode)
return ERROR_FAIL;
for (size_t i = 0; i < ARRAY_SIZE(lattice_devices); ++i) {
if (lattice_devices[i].id == lattice_device->tap->idcode) {
if (lattice_device->family == LATTICE_UNKNOWN)
lattice_device->family = lattice_devices[i].family;
if (lattice_device->preload_length == 0)
lattice_device->preload_length = lattice_devices[i].preload_length;
return ERROR_OK;
}
}
LOG_ERROR("Unknown id! Specify family and preload-length manually.");
return ERROR_FAIL;
}
int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val,
uint32_t out_val, bool do_idle)
{
struct scan_field field;
uint8_t buffer[4];
int retval = lattice_set_instr(tap, cmd, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
if (do_idle) {
jtag_add_runtest(2, TAP_IDLE);
jtag_add_sleep(1000);
}
h_u32_to_le(buffer, out_val);
field.num_bits = 32;
field.out_value = buffer;
field.in_value = buffer;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
retval = jtag_execute_queue();
if (retval == ERROR_OK)
*in_val = le_to_h_u32(buffer);
return retval;
}
int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_val,
uint64_t out_val)
{
struct scan_field field;
uint8_t buffer[8];
int retval = lattice_set_instr(tap, cmd, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
h_u64_to_le(buffer, out_val);
field.num_bits = 64;
field.out_value = buffer;
field.in_value = buffer;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
retval = jtag_execute_queue();
if (retval == ERROR_OK)
*in_val = le_to_h_u64(buffer);
return retval;
}
int lattice_preload(struct lattice_pld_device *lattice_device)
{
struct scan_field field;
size_t sz_bytes = DIV_ROUND_UP(lattice_device->preload_length, 8);
int retval = lattice_set_instr(lattice_device->tap, PRELOAD, TAP_IDLE);
if (retval != ERROR_OK)
return retval;
uint8_t *buffer = malloc(sz_bytes);
if (!buffer) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
memset(buffer, 0xff, sz_bytes);
field.num_bits = lattice_device->preload_length;
field.out_value = buffer;
field.in_value = NULL;
jtag_add_dr_scan(lattice_device->tap, 1, &field, TAP_IDLE);
retval = jtag_execute_queue();
free(buffer);
return retval;
}
static int lattice_read_usercode(struct lattice_pld_device *lattice_device, uint32_t *usercode, uint32_t out)
{
struct jtag_tap *tap = lattice_device->tap;
if (!tap)
return ERROR_FAIL;
if (lattice_device->family == LATTICE_ECP2 || lattice_device->family == LATTICE_ECP3)
return lattice_ecp2_3_read_usercode(tap, usercode, out);
else if (lattice_device->family == LATTICE_ECP5)
return lattice_ecp5_read_usercode(tap, usercode, out);
else if (lattice_device->family == LATTICE_CERTUS)
return lattice_certus_read_usercode(tap, usercode, out);
return ERROR_FAIL;
}
int lattice_verify_usercode(struct lattice_pld_device *lattice_device, uint32_t out,
uint32_t expected, uint32_t mask)
{
uint32_t usercode;
int retval = lattice_read_usercode(lattice_device, &usercode, out);
if (retval != ERROR_OK)
return retval;
if ((usercode & mask) != expected) {
LOG_ERROR("verifying user code register failed got: 0x%08" PRIx32 " expected: 0x%08" PRIx32,
usercode & mask, expected);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int lattice_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode)
{
if (lattice_device->family == LATTICE_ECP2 || lattice_device->family == LATTICE_ECP3)
return lattice_ecp2_3_write_usercode(lattice_device, usercode);
else if (lattice_device->family == LATTICE_ECP5)
return lattice_ecp5_write_usercode(lattice_device, usercode);
else if (lattice_device->family == LATTICE_CERTUS)
return lattice_certus_write_usercode(lattice_device, usercode);
return ERROR_FAIL;
}
static int lattice_read_status_u32(struct lattice_pld_device *lattice_device, uint32_t *status,
uint32_t out, bool do_idle)
{
if (!lattice_device->tap)
return ERROR_FAIL;
if (lattice_device->family == LATTICE_ECP2 || lattice_device->family == LATTICE_ECP3)
return lattice_ecp2_3_read_status(lattice_device->tap, status, out, do_idle);
else if (lattice_device->family == LATTICE_ECP5)
return lattice_ecp5_read_status(lattice_device->tap, status, out, do_idle);
return ERROR_FAIL;
}
static int lattice_read_status_u64(struct lattice_pld_device *lattice_device, uint64_t *status,
uint64_t out)
{
if (!lattice_device->tap)
return ERROR_FAIL;
if (lattice_device->family == LATTICE_CERTUS)
return lattice_certus_read_status(lattice_device->tap, status, out);
return ERROR_FAIL;
}
int lattice_verify_status_register_u32(struct lattice_pld_device *lattice_device, uint32_t out,
uint32_t expected, uint32_t mask, bool do_idle)
{
uint32_t status;
int retval = lattice_read_status_u32(lattice_device, &status, out, do_idle);
if (retval != ERROR_OK)
return retval;
if ((status & mask) != expected) {
LOG_ERROR("verifying status register failed got: 0x%08" PRIx32 " expected: 0x%08" PRIx32,
status & mask, expected);
return ERROR_FAIL;
}
return ERROR_OK;
}
int lattice_verify_status_register_u64(struct lattice_pld_device *lattice_device, uint64_t out,
uint64_t expected, uint64_t mask)
{
uint64_t status;
int retval = lattice_read_status_u64(lattice_device, &status, out);
if (retval != ERROR_OK)
return retval;
if ((status & mask) != expected) {
LOG_ERROR("verifying status register failed got: 0x%08" PRIx64 " expected: 0x%08" PRIx64,
status & mask, expected);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int lattice_load_command(struct pld_device *pld_device, const char *filename)
{
if (!pld_device)
return ERROR_FAIL;
struct lattice_pld_device *lattice_device = pld_device->driver_priv;
if (!lattice_device || !lattice_device->tap)
return ERROR_FAIL;
struct jtag_tap *tap = lattice_device->tap;
if (!tap || !tap->hasidcode)
return ERROR_FAIL;
int retval = lattice_check_device_family(lattice_device);
if (retval != ERROR_OK)
return retval;
struct lattice_bit_file bit_file;
retval = lattice_read_file(&bit_file, filename, lattice_device->family);
if (retval != ERROR_OK)
return retval;
uint32_t id = tap->idcode;
retval = ERROR_FAIL;
switch (lattice_device->family) {
case LATTICE_ECP2:
retval = lattice_ecp2_load(lattice_device, &bit_file);
break;
case LATTICE_ECP3:
retval = lattice_ecp3_load(lattice_device, &bit_file);
break;
case LATTICE_ECP5:
case LATTICE_CERTUS:
if (bit_file.has_id && id != bit_file.idcode)
LOG_WARNING("Id on device (0x%8.8" PRIx32 ") and id in bit-stream (0x%8.8" PRIx32 ") don't match.",
id, bit_file.idcode);
if (lattice_device->family == LATTICE_ECP5)
retval = lattice_ecp5_load(lattice_device, &bit_file);
else
retval = lattice_certus_load(lattice_device, &bit_file);
break;
default:
LOG_ERROR("loading unknown device family");
break;
}
free(bit_file.raw_bit.data);
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
return ERROR_FAIL;
}
struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
if (!lattice_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
/* id is not known yet -> postpone lattice_check_device_family() */
enum lattice_family_e family = LATTICE_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcasecmp(CMD_ARGV[2], "ecp2") == 0) {
family = LATTICE_ECP2;
} else if (strcasecmp(CMD_ARGV[2], "ecp3") == 0) {
family = LATTICE_ECP3;
} else if (strcasecmp(CMD_ARGV[2], "ecp5") == 0) {
family = LATTICE_ECP5;
} else if (strcasecmp(CMD_ARGV[2], "certus") == 0) {
family = LATTICE_CERTUS;
} else {
command_print(CMD, "unknown family");
free(lattice_device);
return ERROR_FAIL;
}
}
lattice_device->tap = tap;
lattice_device->family = family;
lattice_device->preload_length = 0;
pld->driver_priv = lattice_device;
return ERROR_OK;
}
COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct lattice_pld_device *lattice_device = device->driver_priv;
if (!lattice_device)
return ERROR_FAIL;
int retval = lattice_check_device_family(lattice_device);
if (retval != ERROR_OK)
return retval;
retval = lattice_read_usercode(lattice_device, &usercode, 0x0);
if (retval == ERROR_OK)
command_print(CMD, "0x%8.8" PRIx32, usercode);
return retval;
}
COMMAND_HANDLER(lattice_set_preload_command_handler)
{
int dev_id;
unsigned int preload_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], preload_length);
struct lattice_pld_device *lattice_device = device->driver_priv;
if (!lattice_device)
return ERROR_FAIL;
lattice_device->preload_length = preload_length;
return ERROR_OK;
}
COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], usercode);
struct lattice_pld_device *lattice_device = device->driver_priv;
if (!lattice_device)
return ERROR_FAIL;
int retval = lattice_check_device_family(lattice_device);
if (retval != ERROR_OK)
return retval;
return lattice_write_usercode(lattice_device, usercode);
}
COMMAND_HANDLER(lattice_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct lattice_pld_device *lattice_device = device->driver_priv;
if (!lattice_device)
return ERROR_FAIL;
int retval = lattice_check_device_family(lattice_device);
if (retval != ERROR_OK)
return retval;
if (lattice_device->family == LATTICE_CERTUS) {
uint64_t status;
retval = lattice_read_status_u64(lattice_device, &status, 0x0);
if (retval == ERROR_OK)
command_print(CMD, "0x%016" PRIx64, status);
} else {
uint32_t status;
const bool do_idle = lattice_device->family == LATTICE_ECP5;
retval = lattice_read_status_u32(lattice_device, &status, 0x0, do_idle);
if (retval == ERROR_OK)
command_print(CMD, "0x%8.8" PRIx32, status);
}
return retval;
}
static const struct command_registration lattice_exec_command_handlers[] = {
{
.name = "read_status",
.mode = COMMAND_EXEC,
.handler = lattice_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = lattice_read_usercode_register_command_handler,
.help = "reading usercode register from FPGA",
.usage = "num_pld",
}, {
.name = "write_user",
.mode = COMMAND_EXEC,
.handler = lattice_write_usercode_register_command_handler,
.help = "writing usercode register to FPGA",
.usage = "num_pld value",
}, {
.name = "set_preload",
.mode = COMMAND_EXEC,
.handler = lattice_set_preload_command_handler,
.help = "set length for preload (device specific)",
.usage = "num_pld value",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration lattice_command_handler[] = {
{
.name = "lattice",
.mode = COMMAND_ANY,
.help = "lattice specific commands",
.usage = "",
.chain = lattice_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
struct pld_driver lattice_pld = {
.name = "lattice",
.commands = lattice_command_handler,
.pld_device_command = &lattice_pld_device_command,
.load = &lattice_load_command,
};

36
src/pld/lattice.h Normal file
View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_LATTICE_H
#define OPENOCD_PLD_LATTICE_H
#include <jtag/jtag.h>
#include "pld.h"
#include "lattice_bit.h"
#define BYPASS 0xFF
struct lattice_pld_device {
struct jtag_tap *tap;
size_t preload_length;
enum lattice_family_e family;
};
int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate);
int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val,
uint32_t out_val, bool do_idle);
int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_val,
uint64_t out_val);
int lattice_verify_usercode(struct lattice_pld_device *lattice_device, uint32_t out,
uint32_t expected, uint32_t mask);
int lattice_verify_status_register_u32(struct lattice_pld_device *lattice_device, uint32_t out,
uint32_t expected, uint32_t mask, bool do_idle);
int lattice_verify_status_register_u64(struct lattice_pld_device *lattice_device, uint64_t out,
uint64_t expected, uint64_t mask);
int lattice_preload(struct lattice_pld_device *lattice_device);
#endif /* OPENOCD_PLD_LATTICE_H */

105
src/pld/lattice_bit.c Normal file
View File

@ -0,0 +1,105 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "lattice_bit.h"
#include "raw_bit.h"
#include "pld.h"
#include <helper/system.h>
#include <helper/log.h>
#include <helper/binarybuffer.h>
enum read_bit_state {
SEEK_HEADER_START,
SEEK_HEADER_END,
SEEK_PREAMBLE,
SEEK_ID,
DONE,
};
static int lattice_read_bit_file(struct lattice_bit_file *bit_file, const char *filename, enum lattice_family_e family)
{
int retval = cpld_read_raw_bit_file(&bit_file->raw_bit, filename);
if (retval != ERROR_OK)
return retval;
bit_file->part = 0;
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) {
switch (state) {
case SEEK_HEADER_START:
if (bit_file->raw_bit.data[pos] == 0 && bit_file->raw_bit.data[pos - 1] == 0xff)
state = SEEK_HEADER_END;
break;
case SEEK_HEADER_END:
if (pos + 6 < bit_file->raw_bit.length &&
strncmp((const char *)(bit_file->raw_bit.data + pos), "Part: ", 6) == 0) {
bit_file->part = (const char *)bit_file->raw_bit.data + pos + 6;
LOG_INFO("part found: %s\n", bit_file->part);
} else if (bit_file->raw_bit.data[pos] == 0xff && bit_file->raw_bit.data[pos - 1] == 0) {
bit_file->offset = pos;
state = (family != LATTICE_ECP2 && family != LATTICE_ECP3) ? SEEK_PREAMBLE : DONE;
}
break;
case SEEK_PREAMBLE:
if (pos >= 4) {
uint32_t preamble = be_to_h_u32(bit_file->raw_bit.data + pos - 3);
switch (preamble) {
case 0xffffbdb3:
state = SEEK_ID;
break;
case 0xffffbfb3:
case 0xffffbeb3:
state = DONE;
break;
}
}
break;
case SEEK_ID:
if (pos + 7 < bit_file->raw_bit.length && bit_file->raw_bit.data[pos] == 0xe2) {
bit_file->idcode = be_to_h_u32(&bit_file->raw_bit.data[pos + 4]);
bit_file->has_id = true;
state = DONE;
}
break;
default:
break;
}
}
if (state != DONE) {
LOG_ERROR("parsing bitstream failed");
return ERROR_PLD_FILE_LOAD_FAILED;
}
for (size_t i = bit_file->offset; i < bit_file->raw_bit.length; i++)
bit_file->raw_bit.data[i] = flip_u32(bit_file->raw_bit.data[i], 8);
return ERROR_OK;
}
int lattice_read_file(struct lattice_bit_file *bit_file, const char *filename, enum lattice_family_e family)
{
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
/* check if binary .bin or ascii .bit/.hex */
const char *file_suffix_pos = strrchr(filename, '.');
if (!file_suffix_pos) {
LOG_ERROR("Unable to detect filename suffix");
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (strcasecmp(file_suffix_pos, ".bit") == 0)
return lattice_read_bit_file(bit_file, filename, family);
LOG_ERROR("Filetype not supported");
return ERROR_PLD_FILE_LOAD_FAILED;
}

33
src/pld/lattice_bit.h Normal file
View File

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_LATTICE_BIT_H
#define OPENOCD_PLD_LATTICE_BIT_H
#include "helper/types.h"
#include "raw_bit.h"
struct lattice_bit_file {
struct raw_bit_file raw_bit;
size_t offset;
uint32_t idcode;
const char *part; /* reuses memory in raw_bit_file */
bool has_id;
};
enum lattice_family_e {
LATTICE_ECP2,
LATTICE_ECP3,
LATTICE_ECP5,
LATTICE_CERTUS,
LATTICE_UNKNOWN,
};
int lattice_read_file(struct lattice_bit_file *bit_file, const char *filename, enum lattice_family_e family);
#endif /* OPENOCD_PLD_LATTICE_BIT_H */

19
src/pld/lattice_cmd.h Normal file
View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_LATTICE_CMD_H
#define OPENOCD_PLD_LATTICE_CMD_H
#define ISC_ERASE 0x0E
#define ISC_DISABLE 0x26
#define LSC_READ_STATUS 0x3C
#define LSC_INIT_ADDRESS 0x46
#define LSC_BITSTREAM_BURST 0x7A
#define READ_USERCODE 0xC0
#define ISC_ENABLE 0xC6
#endif /* OPENOCD_PLD_LATTICE_CMD_H */

View File

@ -10,16 +10,18 @@
#endif
#include "pld.h"
#include <sys/stat.h>
#include <helper/log.h>
#include <helper/replacements.h>
#include <helper/time_support.h>
/* pld drivers
*/
extern struct pld_driver virtex2_pld;
static struct pld_driver *pld_drivers[] = {
&efinix_pld,
&gatemate_pld,
&gowin_pld,
&intel_pld,
&lattice_pld,
&virtex2_pld,
NULL,
};
@ -134,6 +136,22 @@ COMMAND_HANDLER(handle_pld_load_command)
return ERROR_OK;
}
struct stat input_stat;
if (stat(CMD_ARGV[1], &input_stat) == -1) {
LOG_ERROR("couldn't stat() %s: %s", CMD_ARGV[1], strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (S_ISDIR(input_stat.st_mode)) {
LOG_ERROR("%s is a directory", CMD_ARGV[1]);
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (input_stat.st_size == 0) {
LOG_ERROR("Empty file %s", CMD_ARGV[1]);
return ERROR_PLD_FILE_LOAD_FAILED;
}
retval = p->driver->load(p, CMD_ARGV[1]);
if (retval != ERROR_OK) {
command_print(CMD, "failed loading file %s to pld device %u",

View File

@ -38,4 +38,11 @@ struct pld_device *get_pld_device_by_num(int num);
#define ERROR_PLD_DEVICE_INVALID (-1000)
#define ERROR_PLD_FILE_LOAD_FAILED (-1001)
extern struct pld_driver efinix_pld;
extern struct pld_driver gatemate_pld;
extern struct pld_driver gowin_pld;
extern struct pld_driver intel_pld;
extern struct pld_driver lattice_pld;
extern struct pld_driver virtex2_pld;
#endif /* OPENOCD_PLD_PLD_H */

55
src/pld/raw_bit.c Normal file
View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "raw_bit.h"
#include "pld.h"
#include <helper/system.h>
#include <helper/log.h>
int cpld_read_raw_bit_file(struct raw_bit_file *bit_file, const char *filename)
{
FILE *input_file = fopen(filename, "rb");
if (!input_file) {
LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
fseek(input_file, 0, SEEK_END);
long length = ftell(input_file);
fseek(input_file, 0, SEEK_SET);
if (length < 0) {
fclose(input_file);
LOG_ERROR("Failed to get length of file %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
bit_file->length = (size_t)length;
bit_file->data = malloc(bit_file->length);
if (!bit_file->data) {
fclose(input_file);
LOG_ERROR("Out of memory");
return ERROR_PLD_FILE_LOAD_FAILED;
}
size_t read_count = fread(bit_file->data, sizeof(char), bit_file->length, input_file);
fclose(input_file);
if (read_count != bit_file->length) {
free(bit_file->data);
bit_file->data = NULL;
return ERROR_PLD_FILE_LOAD_FAILED;
}
return ERROR_OK;
}

21
src/pld/raw_bit.h Normal file
View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2022 by Daniel Anselmi *
* danselmi@gmx.ch *
***************************************************************************/
#ifndef OPENOCD_PLD_RAW_BIN_H
#define OPENOCD_PLD_RAW_BIN_H
#include <stddef.h>
#include <stdint.h>
struct raw_bit_file {
size_t length;
uint8_t *data;
};
int cpld_read_raw_bit_file(struct raw_bit_file *bit_file, const char *filename);
#endif /* OPENOCD_PLD_RAW_BIN_H */

View File

@ -23,6 +23,10 @@ static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
field.num_bits = tap->ir_length;
void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
if (!t) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
@ -44,6 +48,10 @@ static int virtex2_send_32(struct pld_device *pld_device,
int i;
values = malloc(num_words * 4);
if (!values) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
scan_field.num_bits = num_words * 32;
scan_field.out_value = values;
@ -52,7 +60,11 @@ static int virtex2_send_32(struct pld_device *pld_device,
for (i = 0; i < num_words; i++)
buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
int retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
if (retval != ERROR_OK) {
free(values);
return retval;
}
jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE);
@ -77,7 +89,9 @@ static int virtex2_receive_32(struct pld_device *pld_device,
scan_field.out_value = NULL;
scan_field.in_value = NULL;
virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */
int retval = virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */
if (retval != ERROR_OK)
return retval;
while (num_words--) {
scan_field.in_value = (uint8_t *)words;
@ -103,15 +117,72 @@ static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status)
data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
data[3] = 0x20000000; /* NOOP */
data[4] = 0x20000000; /* NOOP */
virtex2_send_32(pld_device, 5, data);
int retval = virtex2_send_32(pld_device, 5, data);
if (retval != ERROR_OK)
return retval;
virtex2_receive_32(pld_device, 1, status);
retval = virtex2_receive_32(pld_device, 1, status);
if (retval != ERROR_OK)
return retval;
jtag_execute_queue();
retval = jtag_execute_queue();
if (retval == ERROR_OK)
LOG_DEBUG("status: 0x%8.8" PRIx32, *status);
LOG_DEBUG("status: 0x%8.8" PRIx32 "", *status);
return retval;
}
return ERROR_OK;
static int virtex2_load_prepare(struct pld_device *pld_device)
{
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
int retval;
retval = virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */
if (retval != ERROR_OK)
return retval;
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
jtag_add_sleep(1000);
retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
if (retval != ERROR_OK)
return retval;
return jtag_execute_queue();
}
static int virtex2_load_cleanup(struct pld_device *pld_device)
{
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
int retval;
jtag_add_tlr();
if (!(virtex2_info->no_jstart)) {
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
if (retval != ERROR_OK)
return retval;
}
jtag_add_runtest(13, TAP_IDLE);
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
if (retval != ERROR_OK)
return retval;
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
if (retval != ERROR_OK)
return retval;
if (!(virtex2_info->no_jstart)) {
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
if (retval != ERROR_OK)
return retval;
}
jtag_add_runtest(13, TAP_IDLE);
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
if (retval != ERROR_OK)
return retval;
return jtag_execute_queue();
}
static int virtex2_load(struct pld_device *pld_device, const char *filename)
@ -128,12 +199,11 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename)
if (retval != ERROR_OK)
return retval;
virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */
jtag_execute_queue();
jtag_add_sleep(1000);
virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
jtag_execute_queue();
retval = virtex2_load_prepare(pld_device);
if (retval != ERROR_OK) {
xilinx_free_bit_file(&bit_file);
return retval;
}
for (i = 0; i < bit_file.length; i++)
bit_file.data[i] = flip_u32(bit_file.data[i], 8);
@ -142,24 +212,17 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename)
field.out_value = bit_file.data;
jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE);
jtag_execute_queue();
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
xilinx_free_bit_file(&bit_file);
return retval;
}
jtag_add_tlr();
if (!(virtex2_info->no_jstart))
virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
jtag_add_runtest(13, TAP_IDLE);
virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
if (!(virtex2_info->no_jstart))
virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
jtag_add_runtest(13, TAP_IDLE);
virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
jtag_execute_queue();
retval = virtex2_load_cleanup(pld_device);
xilinx_free_bit_file(&bit_file);
return ERROR_OK;
return retval;
}
COMMAND_HANDLER(virtex2_handle_read_stat_command)
@ -201,6 +264,10 @@ PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
}
virtex2_info = malloc(sizeof(struct virtex2_pld_device));
if (!virtex2_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
virtex2_info->tap = tap;
virtex2_info->no_jstart = 0;

View File

@ -13,7 +13,6 @@
#include "pld.h"
#include <helper/log.h>
#include <sys/stat.h>
#include <helper/system.h>
static int read_section(FILE *input_file, int length_size, char section,
@ -60,27 +59,11 @@ static int read_section(FILE *input_file, int length_size, char section,
int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename)
{
FILE *input_file;
struct stat input_stat;
int read_count;
if (!filename || !bit_file)
return ERROR_COMMAND_SYNTAX_ERROR;
if (stat(filename, &input_stat) == -1) {
LOG_ERROR("couldn't stat() %s: %s", filename, strerror(errno));
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (S_ISDIR(input_stat.st_mode)) {
LOG_ERROR("%s is a directory", filename);
return ERROR_PLD_FILE_LOAD_FAILED;
}
if (input_stat.st_size == 0) {
LOG_ERROR("Empty file %s", filename);
return ERROR_PLD_FILE_LOAD_FAILED;
}
input_file = fopen(filename, "rb");
if (!input_file) {
LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));

View File

@ -80,12 +80,12 @@ struct chibios_params {
static struct chibios_params chibios_params_list[] = {
{
"cortex_m", /* target_name */
0,
NULL,
NULL, /* stacking_info */
},
{
"hla_target", /* target_name */
0,
NULL,
NULL, /* stacking_info */
}
};
@ -198,7 +198,7 @@ static int chibios_update_memory_signature(struct rtos *rtos)
errfree:
/* Error reading the ChibiOS memory structure */
free(signature);
param->signature = 0;
param->signature = NULL;
return -1;
}
@ -468,7 +468,7 @@ static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
return -1;
/* Update stacking if it can only be determined from runtime information */
if ((param->stacking_info == 0) &&
if (!param->stacking_info &&
(chibios_update_stacking(rtos) != ERROR_OK)) {
LOG_ERROR("Failed to determine exact stacking for the target type %s", rtos->target->type->name);
return -1;

View File

@ -123,7 +123,7 @@ static int linux_read_memory(struct target *target,
target->rtos->rtos_specific_params;
uint32_t pa = (address & linux_os->phys_mask) + linux_os->phys_base;
#endif
if (address < 0xc000000) {
if (address < 0xc0000000) {
LOG_ERROR("linux awareness : address in user space");
return ERROR_FAIL;
}

View File

@ -16,22 +16,6 @@
#include "helper/binarybuffer.h"
#include "server/gdb_server.h"
/* RTOSs */
extern const struct rtos_type freertos_rtos;
extern const struct rtos_type threadx_rtos;
extern const struct rtos_type ecos_rtos;
extern const struct rtos_type linux_rtos;
extern const struct rtos_type chibios_rtos;
extern const struct rtos_type chromium_ec_rtos;
extern const struct rtos_type embkernel_rtos;
extern const struct rtos_type mqx_rtos;
extern const struct rtos_type ucos_iii_rtos;
extern const struct rtos_type nuttx_rtos;
extern const struct rtos_type hwthread_rtos;
extern const struct rtos_type riot_rtos;
extern const struct rtos_type zephyr_rtos;
extern const struct rtos_type rtkernel_rtos;
static const struct rtos_type *rtos_types[] = {
&threadx_rtos,
&freertos_rtos,

View File

@ -173,4 +173,19 @@ struct target *rtos_swbp_target(struct target *target, target_addr_t address,
uint32_t length, enum breakpoint_type type);
struct rtos *rtos_of_target(struct target *target);
extern const struct rtos_type chibios_rtos;
extern const struct rtos_type chromium_ec_rtos;
extern const struct rtos_type ecos_rtos;
extern const struct rtos_type embkernel_rtos;
extern const struct rtos_type freertos_rtos;
extern const struct rtos_type hwthread_rtos;
extern const struct rtos_type linux_rtos;
extern const struct rtos_type mqx_rtos;
extern const struct rtos_type nuttx_rtos;
extern const struct rtos_type riot_rtos;
extern const struct rtos_type rtkernel_rtos;
extern const struct rtos_type threadx_rtos;
extern const struct rtos_type ucos_iii_rtos;
extern const struct rtos_type zephyr_rtos;
#endif /* OPENOCD_RTOS_RTOS_H */

View File

@ -2405,6 +2405,7 @@ static int smp_reg_list_noread(struct target *target,
local_list = realloc(local_list, combined_allocated * sizeof(struct reg *));
if (!local_list) {
LOG_ERROR("realloc(%zu) failed", combined_allocated * sizeof(struct reg *));
free(reg_list);
return ERROR_FAIL;
}
}

View File

@ -315,6 +315,10 @@ static int ipdbg_shift_instr(struct ipdbg_hub *hub, uint32_t instr)
}
uint8_t *ir_out_val = calloc(DIV_ROUND_UP(tap->ir_length, 8), 1);
if (!ir_out_val) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
buf_set_u32(ir_out_val, 0, tap->ir_length, instr);
struct scan_field fields;
@ -344,6 +348,10 @@ static int ipdbg_shift_vir(struct ipdbg_hub *hub)
return ERROR_FAIL;
uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->virtual_ir->length, 8), 1);
if (!dr_out_val) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
buf_set_u32(dr_out_val, 0, hub->virtual_ir->length, hub->virtual_ir->value);
struct scan_field fields;
@ -366,8 +374,21 @@ static int ipdbg_shift_data(struct ipdbg_hub *hub, uint32_t dn_data, uint32_t *u
return ERROR_FAIL;
uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1);
if (!dr_out_val) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
buf_set_u32(dr_out_val, 0, hub->data_register_length, dn_data);
uint8_t *dr_in_val = up_data ? calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1) : NULL;
uint8_t *dr_in_val = NULL;
if (up_data) {
dr_in_val = calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1);
if (!dr_in_val) {
LOG_ERROR("Out of memory");
free(dr_out_val);
return ERROR_FAIL;
}
}
struct scan_field fields;
ipdbg_init_scan_field(&fields, dr_in_val, hub->data_register_length, dr_out_val);

View File

@ -21,6 +21,7 @@
#include "arm_semihosting.h"
#include "jtag/interface.h"
#include "smp.h"
#include <helper/nvp.h>
#include <helper/time_support.h>
enum restart_mode {
@ -588,7 +589,7 @@ static int aarch64_restore_one(struct target *target, int current,
resume_pc &= 0xFFFFFFFC;
break;
case ARM_STATE_AARCH64:
resume_pc &= 0xFFFFFFFFFFFFFFFC;
resume_pc &= 0xFFFFFFFFFFFFFFFCULL;
break;
case ARM_STATE_THUMB:
case ARM_STATE_THUMB_EE:
@ -1066,9 +1067,12 @@ static int aarch64_post_debug_entry(struct target *target)
armv8_identify_cache(armv8);
armv8_read_mpidr(armv8);
}
armv8->armv8_mmu.mmu_enabled =
if (armv8->is_armv8r) {
armv8->armv8_mmu.mmu_enabled = 0;
} else {
armv8->armv8_mmu.mmu_enabled =
(aarch64->system_control_reg & 0x1U) ? 1 : 0;
}
armv8->armv8_mmu.armv8_cache.d_u_cache_enabled =
(aarch64->system_control_reg & 0x4U) ? 1 : 0;
armv8->armv8_mmu.armv8_cache.i_cache_enabled =
@ -1245,7 +1249,7 @@ static int aarch64_set_breakpoint(struct target *target,
| (byte_addr_select << 5)
| (3 << 1) | 1;
brp_list[brp_i].used = 1;
brp_list[brp_i].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC;
brp_list[brp_i].value = breakpoint->address & 0xFFFFFFFFFFFFFFFCULL;
brp_list[brp_i].control = control;
bpt_value = brp_list[brp_i].value;
@ -1297,28 +1301,28 @@ static int aarch64_set_breakpoint(struct target *target,
buf_set_u32(code, 0, 32, opcode);
retval = target_read_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length, 1,
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
armv8_cache_d_inner_flush_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length, 1, code);
if (retval != ERROR_OK)
return retval;
armv8_cache_d_inner_flush_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
armv8_cache_i_inner_inval_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
breakpoint->is_set = true;
@ -1450,7 +1454,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin
| (iva_byte_addr_select << 5)
| (3 << 1) | 1;
brp_list[brp_2].used = 1;
brp_list[brp_2].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC;
brp_list[brp_2].value = breakpoint->address & 0xFFFFFFFFFFFFFFFCULL;
brp_list[brp_2].control = control_iva;
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
+ CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_2].brpn,
@ -1574,29 +1578,29 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
/* restore original instruction (kept in target endianness) */
armv8_cache_d_inner_flush_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
if (breakpoint->length == 4) {
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
4, 1, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
} else {
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
2, 1, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
}
armv8_cache_d_inner_flush_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
armv8_cache_i_inner_inval_virt(armv8,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
breakpoint->length);
}
breakpoint->is_set = false;
@ -2726,6 +2730,25 @@ static int aarch64_init_arch_info(struct target *target,
return ERROR_OK;
}
static int armv8r_target_create(struct target *target, Jim_Interp *interp)
{
struct aarch64_private_config *pc = target->private_config;
struct aarch64_common *aarch64;
if (adiv5_verify_config(&pc->adiv5_config) != ERROR_OK)
return ERROR_FAIL;
aarch64 = calloc(1, sizeof(struct aarch64_common));
if (!aarch64) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
aarch64->armv8_common.is_armv8r = true;
return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
}
static int aarch64_target_create(struct target *target, Jim_Interp *interp)
{
struct aarch64_private_config *pc = target->private_config;
@ -2740,6 +2763,8 @@ static int aarch64_target_create(struct target *target, Jim_Interp *interp)
return ERROR_FAIL;
}
aarch64->armv8_common.is_armv8r = false;
return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
}
@ -2762,12 +2787,16 @@ static void aarch64_deinit_target(struct target *target)
static int aarch64_mmu(struct target *target, int *enabled)
{
struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common;
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target %s not halted", __func__, target_name(target));
return ERROR_TARGET_INVALID;
}
*enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled;
if (armv8->is_armv8r)
*enabled = 0;
else
*enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled;
return ERROR_OK;
}
@ -2929,15 +2958,15 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
struct target *target = get_current_target(CMD_CTX);
struct aarch64_common *aarch64 = target_to_aarch64(target);
static const struct jim_nvp nvp_maskisr_modes[] = {
static const struct nvp nvp_maskisr_modes[] = {
{ .name = "off", .value = AARCH64_ISRMASK_OFF },
{ .name = "on", .value = AARCH64_ISRMASK_ON },
{ .name = NULL, .value = -1 },
};
const struct jim_nvp *n;
const struct nvp *n;
if (CMD_ARGC > 0) {
n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
n = nvp_name2value(nvp_maskisr_modes, CMD_ARGV[0]);
if (!n->name) {
LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
return ERROR_COMMAND_SYNTAX_ERROR;
@ -2946,7 +2975,7 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
aarch64->isrmasking_mode = n->value;
}
n = jim_nvp_value2name_simple(nvp_maskisr_modes, aarch64->isrmasking_mode);
n = nvp_value2name(nvp_maskisr_modes, aarch64->isrmasking_mode);
command_print(CMD, "aarch64 interrupt mask %s", n->name);
return ERROR_OK;
@ -3165,3 +3194,39 @@ struct target_type aarch64_target = {
.mmu = aarch64_mmu,
.virt2phys = aarch64_virt2phys,
};
struct target_type armv8r_target = {
.name = "armv8r",
.poll = aarch64_poll,
.arch_state = armv8_arch_state,
.halt = aarch64_halt,
.resume = aarch64_resume,
.step = aarch64_step,
.assert_reset = aarch64_assert_reset,
.deassert_reset = aarch64_deassert_reset,
/* REVISIT allow exporting VFP3 registers ... */
.get_gdb_arch = armv8_get_gdb_arch,
.get_gdb_reg_list = armv8_get_gdb_reg_list,
.read_memory = aarch64_read_phys_memory,
.write_memory = aarch64_write_phys_memory,
.add_breakpoint = aarch64_add_breakpoint,
.add_context_breakpoint = aarch64_add_context_breakpoint,
.add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint,
.remove_breakpoint = aarch64_remove_breakpoint,
.add_watchpoint = aarch64_add_watchpoint,
.remove_watchpoint = aarch64_remove_watchpoint,
.hit_watchpoint = aarch64_hit_watchpoint,
.commands = aarch64_command_handlers,
.target_create = armv8r_target_create,
.target_jim_configure = aarch64_jim_configure,
.init_target = aarch64_init_target,
.deinit_target = aarch64_deinit_target,
.examine = aarch64_examine,
};

View File

@ -57,7 +57,7 @@ static const struct arm9tdmi_vector {
{"dabt", ARM9TDMI_DABT_VECTOR},
{"irq", ARM9TDMI_IRQ_VECTOR},
{"fiq", ARM9TDMI_FIQ_VECTOR},
{0, 0},
{NULL, 0},
};
int arm9tdmi_examine_debug_reason(struct target *target)

View File

@ -19,6 +19,7 @@
#include "register.h"
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <helper/nvp.h>
#include <stdlib.h>
#include <string.h>
@ -236,7 +237,7 @@ static int armv8_read_ttbcr(struct target *target)
armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
armv8->page_size = (ttbcr_64 >> 14) & 3;
armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFFULL;
retval += dpm->instr_read_data_r0_64(dpm,
ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
&armv8->ttbr_base);
@ -1043,7 +1044,7 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
unsigned int argp = 0;
int retval;
static const struct jim_nvp nvp_ecatch_modes[] = {
static const struct nvp nvp_ecatch_modes[] = {
{ .name = "off", .value = 0 },
{ .name = "nsec_el1", .value = (1 << 5) },
{ .name = "nsec_el2", .value = (2 << 5) },
@ -1053,7 +1054,7 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
{ .name = "sec_el13", .value = (5 << 1) },
{ .name = NULL, .value = -1 },
};
const struct jim_nvp *n;
const struct nvp *n;
if (CMD_ARGC == 0) {
const char *sec = NULL, *nsec = NULL;
@ -1063,11 +1064,11 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
if (retval != ERROR_OK)
return retval;
n = jim_nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0x0f);
n = nvp_value2name(nvp_ecatch_modes, edeccr & 0x0f);
if (n->name)
sec = n->name;
n = jim_nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0xf0);
n = nvp_value2name(nvp_ecatch_modes, edeccr & 0xf0);
if (n->name)
nsec = n->name;
@ -1081,7 +1082,7 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
}
while (argp < CMD_ARGC) {
n = jim_nvp_name2value_simple(nvp_ecatch_modes, CMD_ARGV[argp]);
n = nvp_name2value(nvp_ecatch_modes, CMD_ARGV[argp]);
if (!n->name) {
LOG_ERROR("Unknown option: %s", CMD_ARGV[argp]);
return ERROR_FAIL;

View File

@ -204,6 +204,7 @@ struct armv8_common {
uint8_t pa_size;
uint32_t page_size;
uint64_t ttbr_base;
bool is_armv8r;
struct armv8_mmu_common armv8_mmu;

View File

@ -274,7 +274,7 @@ static int dpmv8_instr_write_data_dcc(struct arm_dpm *dpm,
if (retval != ERROR_OK)
return retval;
return dpmv8_exec_opcode(dpm, opcode, 0);
return dpmv8_exec_opcode(dpm, opcode, NULL);
}
static int dpmv8_instr_write_data_dcc_64(struct arm_dpm *dpm,
@ -287,7 +287,7 @@ static int dpmv8_instr_write_data_dcc_64(struct arm_dpm *dpm,
if (retval != ERROR_OK)
return retval;
return dpmv8_exec_opcode(dpm, opcode, 0);
return dpmv8_exec_opcode(dpm, opcode, NULL);
}
static int dpmv8_instr_write_data_r0(struct arm_dpm *dpm,
@ -587,6 +587,9 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
}
LOG_DEBUG("target_el = %i, last_el = %i", target_el, dpm->last_el);
if (dpm->last_el == target_el)
return ERROR_OK; /* nothing to do */
if (target_el > dpm->last_el) {
retval = dpm->instr_execute(dpm,
armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);

View File

@ -52,6 +52,7 @@
#include "transport/transport.h"
#include "smp.h"
#include <helper/bits.h>
#include <helper/nvp.h>
#include <helper/time_support.h>
static int cortex_a_poll(struct target *target);
@ -3246,15 +3247,15 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
struct target *target = get_current_target(CMD_CTX);
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
static const struct jim_nvp nvp_maskisr_modes[] = {
static const struct nvp nvp_maskisr_modes[] = {
{ .name = "off", .value = CORTEX_A_ISRMASK_OFF },
{ .name = "on", .value = CORTEX_A_ISRMASK_ON },
{ .name = NULL, .value = -1 },
};
const struct jim_nvp *n;
const struct nvp *n;
if (CMD_ARGC > 0) {
n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
n = nvp_name2value(nvp_maskisr_modes, CMD_ARGV[0]);
if (!n->name) {
LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
return ERROR_COMMAND_SYNTAX_ERROR;
@ -3263,7 +3264,7 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
cortex_a->isrmasking_mode = n->value;
}
n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
n = nvp_value2name(nvp_maskisr_modes, cortex_a->isrmasking_mode);
command_print(CMD, "cortex_a interrupt mask %s", n->name);
return ERROR_OK;
@ -3274,22 +3275,22 @@ COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
struct target *target = get_current_target(CMD_CTX);
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
static const struct jim_nvp nvp_dacrfixup_modes[] = {
static const struct nvp nvp_dacrfixup_modes[] = {
{ .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
{ .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
{ .name = NULL, .value = -1 },
};
const struct jim_nvp *n;
const struct nvp *n;
if (CMD_ARGC > 0) {
n = jim_nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
n = nvp_name2value(nvp_dacrfixup_modes, CMD_ARGV[0]);
if (!n->name)
return ERROR_COMMAND_SYNTAX_ERROR;
cortex_a->dacrfixup_mode = n->value;
}
n = jim_nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
n = nvp_value2name(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
command_print(CMD, "cortex_a domain access control fixup %s", n->name);
return ERROR_OK;

View File

@ -29,6 +29,7 @@
#include "arm_opcodes.h"
#include "arm_semihosting.h"
#include "smp.h"
#include <helper/nvp.h>
#include <helper/time_support.h>
#include <rtt/rtt.h>
@ -2935,14 +2936,14 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
struct cortex_m_common *cortex_m = target_to_cm(target);
int retval;
static const struct jim_nvp nvp_maskisr_modes[] = {
static const struct nvp nvp_maskisr_modes[] = {
{ .name = "auto", .value = CORTEX_M_ISRMASK_AUTO },
{ .name = "off", .value = CORTEX_M_ISRMASK_OFF },
{ .name = "on", .value = CORTEX_M_ISRMASK_ON },
{ .name = "steponly", .value = CORTEX_M_ISRMASK_STEPONLY },
{ .name = NULL, .value = -1 },
};
const struct jim_nvp *n;
const struct nvp *n;
retval = cortex_m_verify_pointer(CMD, cortex_m);
@ -2955,14 +2956,14 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
}
if (CMD_ARGC > 0) {
n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
n = nvp_name2value(nvp_maskisr_modes, CMD_ARGV[0]);
if (!n->name)
return ERROR_COMMAND_SYNTAX_ERROR;
cortex_m->isrmasking_mode = n->value;
cortex_m_set_maskints_for_halt(target);
}
n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
n = nvp_value2name(nvp_maskisr_modes, cortex_m->isrmasking_mode);
command_print(CMD, "cortex_m interrupt mask %s", n->name);
return ERROR_OK;

View File

@ -60,7 +60,7 @@ static inline int dsp563xx_once_ir_exec(struct jtag_tap *tap, int flush, uint8_t
{
int err;
err = dsp563xx_write_dr_u8(tap, 0, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0);
err = dsp563xx_write_dr_u8(tap, NULL, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0);
if (err != ERROR_OK)
return err;
if (flush)
@ -226,7 +226,7 @@ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32
err = dsp563xx_once_ir_exec(tap, flush, reg, 0, 0, 0);
if (err != ERROR_OK)
return err;
err = dsp563xx_write_dr_u32(tap, 0x00, data, 24, 0);
err = dsp563xx_write_dr_u32(tap, NULL, data, 24, 0);
if (err != ERROR_OK)
return err;
if (flush)
@ -242,7 +242,7 @@ int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
if (err != ERROR_OK)
return err;
err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
err = dsp563xx_write_dr_u32(tap, NULL, opcode, 24, 0);
if (err != ERROR_OK)
return err;
if (flush)
@ -258,7 +258,7 @@ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 0, 0);
if (err != ERROR_OK)
return err;
err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
err = dsp563xx_write_dr_u32(tap, NULL, opcode, 24, 0);
if (err != ERROR_OK)
return err;
if (flush) {
@ -270,7 +270,7 @@ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode
err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
if (err != ERROR_OK)
return err;
err = dsp563xx_write_dr_u32(tap, 0, operand, 24, 0);
err = dsp563xx_write_dr_u32(tap, NULL, operand, 24, 0);
if (err != ERROR_OK)
return err;
if (flush) {

View File

@ -8,6 +8,10 @@ noinst_LTLIBRARIES += %D%/libespressif.la
%D%/esp_xtensa_smp.h \
%D%/esp_xtensa_semihosting.c \
%D%/esp_xtensa_semihosting.h \
%D%/esp_xtensa_apptrace.c \
%D%/esp_xtensa_apptrace.h \
%D%/esp32_apptrace.c \
%D%/esp32_apptrace.h \
%D%/esp32.c \
%D%/esp32s2.c \
%D%/esp32s3.c \

View File

@ -440,6 +440,11 @@ static const struct command_registration esp32_command_handlers[] = {
{
.chain = esp_xtensa_smp_command_handlers,
},
{
.name = "esp",
.usage = "",
.chain = esp32_apptrace_command_handlers,
},
{
.name = "esp32",
.usage = "",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* ESP32 application trace module *
* Copyright (C) 2017-2019 Espressif Systems Ltd. *
***************************************************************************/
#ifndef OPENOCD_TARGET_ESP32_APPTRACE_H
#define OPENOCD_TARGET_ESP32_APPTRACE_H
#include <helper/command.h>
#include <helper/time_support.h>
#include <target/target.h>
#define ESP32_APPTRACE_MAX_CORES_NUM 2
struct esp32_apptrace_hw {
uint32_t max_block_id;
uint32_t (*max_block_size_get)(struct target *target);
int (*status_reg_read)(struct target *target, uint32_t *stat);
int (*ctrl_reg_write)(struct target *target,
uint32_t block_id,
uint32_t len,
bool conn,
bool data);
int (*ctrl_reg_read)(struct target *target,
uint32_t *block_id,
uint32_t *len,
bool *conn);
int (*data_len_read)(struct target *target,
uint32_t *block_id,
uint32_t *len);
int (*data_read)(struct target *target,
uint32_t size,
uint8_t *buffer,
uint32_t block_id,
bool ack);
uint32_t (*usr_block_max_size_get)(struct target *target);
int (*buffs_write)(struct target *target,
uint32_t bufs_num,
uint32_t buf_sz[],
const uint8_t *bufs[],
uint32_t block_id,
bool ack,
bool data);
int (*leave_trace_crit_section_start)(struct target *target);
int (*leave_trace_crit_section_stop)(struct target *target);
};
struct esp_apptrace_host2target_hdr {
uint16_t block_sz;
};
struct esp32_apptrace_dest {
void *priv;
int (*write)(void *priv, uint8_t *data, int size);
int (*clean)(void *priv);
bool log_progress;
};
struct esp32_apptrace_format {
uint32_t hdr_sz;
int (*core_id_get)(struct target *target, uint8_t *hdr_buf);
uint32_t (*usr_block_len_get)(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len);
};
struct esp32_apptrace_cmd_stats {
uint32_t incompl_blocks;
uint32_t lost_bytes;
float min_blk_read_time;
float max_blk_read_time;
float min_blk_proc_time;
float max_blk_proc_time;
};
struct esp32_apptrace_cmd_ctx {
volatile int running;
int mode;
/* TODO: use subtargets from target arch info */
struct target *cpus[ESP32_APPTRACE_MAX_CORES_NUM];
/* TODO: use cores num from target */
unsigned int cores_num;
const struct esp32_apptrace_hw *hw;
enum target_state target_state;
uint32_t last_blk_id;
struct list_head free_trace_blocks;
struct list_head ready_trace_blocks;
uint32_t max_trace_block_sz;
struct esp32_apptrace_format trace_format;
int (*process_data)(struct esp32_apptrace_cmd_ctx *ctx, unsigned int core_id, uint8_t *data, uint32_t data_len);
void (*auto_clean)(struct esp32_apptrace_cmd_ctx *ctx);
uint32_t tot_len;
uint32_t raw_tot_len;
float stop_tmo;
struct esp32_apptrace_cmd_stats stats;
struct duration read_time;
struct duration idle_time;
void *cmd_priv;
struct target *target;
struct command_invocation *cmd;
};
struct esp32_apptrace_cmd_data {
struct esp32_apptrace_dest data_dest;
uint32_t poll_period;
uint32_t max_len;
uint32_t skip_len;
bool wait4halt;
};
int esp32_apptrace_cmd_ctx_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode);
int esp32_apptrace_cmd_ctx_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx);
void esp32_apptrace_cmd_args_parse(struct esp32_apptrace_cmd_ctx *cmd_ctx,
struct esp32_apptrace_cmd_data *cmd_data,
const char **argv,
int argc);
int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest[], const char *dest_paths[], unsigned int max_dests);
int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest[], unsigned int max_dests);
int esp_apptrace_usr_block_write(const struct esp32_apptrace_hw *hw, struct target *target,
uint32_t block_id,
const uint8_t *data,
uint32_t size);
extern const struct command_registration esp32_apptrace_command_handlers[];
#endif /* OPENOCD_TARGET_ESP32_APPTRACE_H */

View File

@ -496,6 +496,11 @@ static const struct command_registration esp32s2_command_handlers[] = {
{
.chain = xtensa_command_handlers,
},
{
.name = "esp",
.usage = "",
.chain = esp32_apptrace_command_handlers,
},
{
.name = "arm",
.mode = COMMAND_ANY,

View File

@ -364,6 +364,11 @@ static const struct command_registration esp32s3_command_handlers[] = {
.usage = "",
.chain = esp_xtensa_smp_command_handlers,
},
{
.name = "esp",
.usage = "",
.chain = esp32_apptrace_command_handlers,
},
{
.name = "esp32",
.usage = "",

View File

@ -12,6 +12,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <target/smp.h>
#include "esp_xtensa_apptrace.h"
#include <target/register.h>
#include "esp_xtensa.h"
#include "esp_semihosting.h"
@ -25,6 +26,7 @@ int esp_xtensa_init_arch_info(struct target *target,
if (ret != ERROR_OK)
return ret;
esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops;
esp_xtensa->apptrace.hw = &esp_xtensa_apptrace_hw;
return ERROR_OK;
}

View File

@ -12,10 +12,12 @@
#include <target/xtensa/xtensa.h>
#include "esp_xtensa.h"
#include "esp_semihosting.h"
#include "esp_xtensa_apptrace.h"
struct esp_xtensa_common {
struct xtensa xtensa; /* must be the first element */
struct esp_semihost_data semihost;
struct esp_xtensa_apptrace_info apptrace;
};
static inline struct esp_xtensa_common *target_to_esp_xtensa(struct target *target)

View File

@ -0,0 +1,499 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Xtensa application tracing module for OpenOCD *
* Copyright (C) 2017 Espressif Systems Ltd. *
***************************************************************************/
/*
How it works?
https://github.com/espressif/esp-idf/blob/master/components/app_trace/port/xtensa/port.c#L8
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/align.h>
#include <target/xtensa/xtensa.h>
#include <target/xtensa/xtensa_debug_module.h>
#include "esp_xtensa_apptrace.h"
/* TRAX is disabled, so we use its registers for our own purposes
* | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
*/
#define XTENSA_APPTRACE_CTRL_REG XDMREG_DELAYCNT
#define XTENSA_APPTRACE_BLOCK_ID_MSK 0x7FUL
#define XTENSA_APPTRACE_BLOCK_ID_MAX XTENSA_APPTRACE_BLOCK_ID_MSK
/* if non-zero then apptrace code entered the critical section and the value is an address of the
* critical section's exit point */
#define XTENSA_APPTRACE_STAT_REG XDMREG_TRIGGERPC
#define XTENSA_APPTRACE_BLOCK_LEN_MSK 0x7FFFUL
#define XTENSA_APPTRACE_BLOCK_LEN(_l_) ((_l_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
#define XTENSA_APPTRACE_BLOCK_LEN_GET(_v_) ((_v_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
#define XTENSA_APPTRACE_BLOCK_ID(_id_) (((_id_) & XTENSA_APPTRACE_BLOCK_ID_MSK) << 15)
#define XTENSA_APPTRACE_BLOCK_ID_GET(_v_) (((_v_) >> 15) & XTENSA_APPTRACE_BLOCK_ID_MSK)
#define XTENSA_APPTRACE_HOST_DATA BIT(22)
#define XTENSA_APPTRACE_HOST_CONNECT BIT(23)
static int esp_xtensa_apptrace_leave_crit_section_start(struct target *target);
static int esp_xtensa_apptrace_leave_crit_section_stop(struct target *target);
static int esp_xtensa_apptrace_buffs_write(struct target *target,
uint32_t bufs_num,
uint32_t buf_sz[],
const uint8_t *bufs[],
uint32_t block_id,
bool ack,
bool data);
struct esp32_apptrace_hw esp_xtensa_apptrace_hw = {
.max_block_id = XTENSA_APPTRACE_BLOCK_ID_MAX,
.max_block_size_get = esp_xtensa_apptrace_block_max_size_get,
.status_reg_read = esp_xtensa_apptrace_status_reg_read,
.ctrl_reg_write = esp_xtensa_apptrace_ctrl_reg_write,
.ctrl_reg_read = esp_xtensa_apptrace_ctrl_reg_read,
.data_len_read = esp_xtensa_apptrace_data_len_read,
.data_read = esp_xtensa_apptrace_data_read,
.usr_block_max_size_get = esp_xtensa_apptrace_usr_block_max_size_get,
.buffs_write = esp_xtensa_apptrace_buffs_write,
.leave_trace_crit_section_start = esp_xtensa_apptrace_leave_crit_section_start,
.leave_trace_crit_section_stop = esp_xtensa_apptrace_leave_crit_section_stop,
};
uint32_t esp_xtensa_apptrace_block_max_size_get(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
struct xtensa_trace_status trace_status;
struct xtensa_trace_config trace_config;
uint32_t max_trace_block_sz;
int res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
if (res != ERROR_OK) {
LOG_ERROR("Failed to read TRAX status (%d)!", res);
return 0;
}
max_trace_block_sz = BIT(((trace_status.stat >> 8) & 0x1f) - 2) * 4;
res = xtensa_dm_trace_config_read(&xtensa->dbg_mod, &trace_config);
if (res != ERROR_OK) {
LOG_ERROR("Failed to read TRAX config (%d)!", res);
return 0;
}
LOG_DEBUG("ctrl=0x%" PRIx32 " memadrstart=0x%" PRIx32 " memadrend=0x%" PRIx32 " traxadr=0x%" PRIx32,
trace_config.ctrl,
trace_config.memaddr_start,
trace_config.memaddr_end,
trace_config.addr);
return max_trace_block_sz;
}
uint32_t esp_xtensa_apptrace_usr_block_max_size_get(struct target *target)
{
return esp_xtensa_apptrace_block_max_size_get(target) - sizeof(struct esp_apptrace_host2target_hdr);
}
int esp_xtensa_apptrace_data_len_read(struct target *target,
uint32_t *block_id,
uint32_t *len)
{
return esp_xtensa_apptrace_ctrl_reg_read(target, block_id, len, NULL);
}
int esp_xtensa_apptrace_usr_block_write(struct target *target,
uint32_t block_id,
const uint8_t *data,
uint32_t size)
{
return esp_apptrace_usr_block_write(&esp_xtensa_apptrace_hw, target, block_id, data, size);
}
static int esp_xtensa_apptrace_data_reverse_read(struct xtensa *xtensa,
uint32_t size,
uint8_t *buffer,
uint8_t *unal_bytes)
{
int res = 0;
uint32_t rd_sz = ALIGN_UP(size, 4);
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, (xtensa->core_config->trace.mem_sz - rd_sz) / 4);
if (res != ERROR_OK)
return res;
if (!IS_ALIGNED(size, 4)) {
res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, unal_bytes);
if (res != ERROR_OK)
return res;
}
for (unsigned int i = size / 4; i != 0; i--) {
res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, &buffer[(i - 1) * 4]);
if (res != ERROR_OK)
return res;
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_data_normal_read(struct xtensa *xtensa,
uint32_t size,
uint8_t *buffer,
uint8_t *unal_bytes)
{
int res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, 0);
if (res != ERROR_OK)
return res;
for (unsigned int i = 0; i < size / 4; i++) {
res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, &buffer[i * 4]);
if (res != ERROR_OK)
return res;
}
if (!IS_ALIGNED(size, 4)) {
res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, unal_bytes);
if (res != ERROR_OK)
return res;
}
return ERROR_OK;
}
int esp_xtensa_apptrace_data_read(struct target *target,
uint32_t size,
uint8_t *buffer,
uint32_t block_id,
bool ack)
{
struct xtensa *xtensa = target_to_xtensa(target);
int res;
uint32_t tmp = XTENSA_APPTRACE_HOST_CONNECT | XTENSA_APPTRACE_BLOCK_ID(block_id) |
XTENSA_APPTRACE_BLOCK_LEN(0);
uint8_t unal_bytes[4];
LOG_DEBUG("Read data on target (%s)", target_name(target));
if (xtensa->core_config->trace.reversed_mem_access)
res = esp_xtensa_apptrace_data_reverse_read(xtensa, size, buffer, unal_bytes);
else
res = esp_xtensa_apptrace_data_normal_read(xtensa, size, buffer, unal_bytes);
if (res != ERROR_OK)
return res;
if (ack) {
LOG_DEBUG("Ack block %" PRIu32 " target (%s)!", block_id, target_name(target));
res = xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
if (res != ERROR_OK)
return res;
}
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("Failed to exec JTAG queue!");
return res;
}
if (!IS_ALIGNED(size, 4)) {
/* copy the last unaligned bytes */
memcpy(buffer + ALIGN_DOWN(size, 4), unal_bytes, size & 0x3UL);
}
return ERROR_OK;
}
int esp_xtensa_apptrace_ctrl_reg_write(struct target *target,
uint32_t block_id,
uint32_t len,
bool conn,
bool data)
{
struct xtensa *xtensa = target_to_xtensa(target);
uint32_t tmp = (conn ? XTENSA_APPTRACE_HOST_CONNECT : 0) |
(data ? XTENSA_APPTRACE_HOST_DATA : 0) | XTENSA_APPTRACE_BLOCK_ID(block_id) |
XTENSA_APPTRACE_BLOCK_LEN(len);
xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("Failed to exec JTAG queue!");
return res;
}
return ERROR_OK;
}
int esp_xtensa_apptrace_ctrl_reg_read(struct target *target,
uint32_t *block_id,
uint32_t *len,
bool *conn)
{
struct xtensa *xtensa = target_to_xtensa(target);
uint8_t tmp[4];
xtensa_queue_dbg_reg_read(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK)
return res;
uint32_t val = target_buffer_get_u32(target, tmp);
if (block_id)
*block_id = XTENSA_APPTRACE_BLOCK_ID_GET(val);
if (len)
*len = XTENSA_APPTRACE_BLOCK_LEN_GET(val);
if (conn)
*conn = val & XTENSA_APPTRACE_HOST_CONNECT;
return ERROR_OK;
}
int esp_xtensa_apptrace_status_reg_read(struct target *target, uint32_t *stat)
{
struct xtensa *xtensa = target_to_xtensa(target);
uint8_t tmp[4];
int res = xtensa_queue_dbg_reg_read(xtensa, XTENSA_APPTRACE_STAT_REG, tmp);
if (res != ERROR_OK)
return res;
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("Failed to exec JTAG queue!");
return res;
}
*stat = buf_get_u32(tmp, 0, 32);
return ERROR_OK;
}
int esp_xtensa_apptrace_status_reg_write(struct target *target, uint32_t stat)
{
struct xtensa *xtensa = target_to_xtensa(target);
xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_STAT_REG, stat);
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("Failed to exec JTAG queue!");
return res;
}
return ERROR_OK;
}
static int esp_xtensa_swdbg_activate(struct target *target, int enab)
{
struct xtensa *xtensa = target_to_xtensa(target);
xtensa_queue_dbg_reg_write(xtensa, enab ? XDMREG_DCRSET : XDMREG_DCRCLR, OCDDCR_DEBUGSWACTIVE);
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("%s: writing DCR failed!", target->cmd_name);
return res;
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_leave_crit_section_start(struct target *target)
{
/* TODO: not sure that we need this, but it seems that we fail to leave tracing critical
*section w/o this */
int res = esp_xtensa_swdbg_activate(target, 1 /*enable*/);
if (res != ERROR_OK) {
LOG_ERROR("Failed to activate SW debug (%d)!", res);
return res;
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_leave_crit_section_stop(struct target *target)
{
int res = esp_xtensa_swdbg_activate(target, 0 /*disable*/);
if (res != ERROR_OK) {
LOG_ERROR("Failed to activate SW debug (%d)!", res);
return res;
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_queue_reverse_write(struct target *target, uint32_t bufs_num,
uint32_t buf_sz[], const uint8_t *bufs[])
{
int res = ERROR_OK;
uint32_t cached_bytes = 0, total_sz = 0;
uint8_t cached_data8[sizeof(uint32_t)] = { 0 };
uint32_t cached_data32 = 0;
struct xtensa *xtensa = target_to_xtensa(target);
for (uint32_t i = 0; i < bufs_num; i++)
total_sz += buf_sz[i];
if (!IS_ALIGNED(total_sz, 4)) {
cached_bytes = sizeof(uint32_t) - (total_sz & 0x3UL);
total_sz = ALIGN_UP(total_sz, 4);
}
xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, (xtensa->core_config->trace.mem_sz - total_sz) / 4);
for (uint32_t i = bufs_num; i > 0; i--) {
uint32_t bsz = buf_sz[i - 1];
const uint8_t *cur_buf = &bufs[i - 1][bsz];
uint32_t bytes_to_cache;
/* if there are cached bytes from the previous buffer, combine them with the last
* from the current buffer */
if (cached_bytes) {
if ((cached_bytes + bsz) < sizeof(uint32_t))
bytes_to_cache = bsz;
else
bytes_to_cache = sizeof(uint32_t) - cached_bytes;
memcpy(&cached_data8[sizeof(uint32_t) - cached_bytes - bytes_to_cache],
cur_buf - bytes_to_cache,
bytes_to_cache);
cached_data32 = target_buffer_get_u32(target, cached_data8);
cached_bytes += bytes_to_cache;
if (cached_bytes < sizeof(uint32_t))
continue;
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
if (res != ERROR_OK)
return res;
bsz -= bytes_to_cache;
cur_buf -= bytes_to_cache;
memset(cached_data8, 0x00, sizeof(cached_data8));
cached_bytes = 0;
}
/* write full dwords */
for (unsigned int k = bsz; k >= sizeof(uint32_t); k -= sizeof(uint32_t)) {
uint32_t temp = target_buffer_get_u32(target, cur_buf - sizeof(uint32_t));
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, temp);
if (res != ERROR_OK)
return res;
cur_buf -= sizeof(uint32_t);
}
/* if there are bytes to be cached (1..3) */
bytes_to_cache = bsz & 0x3UL;
if (bytes_to_cache > 0) {
if (bytes_to_cache + cached_bytes >= sizeof(uint32_t)) {
/* filling the cache buffer from the end to beginning */
uint32_t to_copy = sizeof(uint32_t) - cached_bytes;
memcpy(&cached_data8[0], cur_buf - to_copy, to_copy);
cached_data32 = target_buffer_get_u32(target, cached_data8);
/* write full word of cached bytes */
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
if (res != ERROR_OK)
return res;
/* cache remaining bytes */
memset(cached_data8, 0x00, sizeof(cached_data8));
cur_buf -= to_copy;
to_copy = bytes_to_cache + cached_bytes - sizeof(uint32_t);
memcpy(&cached_data8[sizeof(uint32_t) - to_copy], cur_buf - to_copy, to_copy);
cached_bytes = to_copy;
} else {
/* filling the cache buffer from the end to beginning */
memcpy(&cached_data8[sizeof(uint32_t) - cached_bytes - bytes_to_cache],
cur_buf - bytes_to_cache,
bytes_to_cache);
cached_bytes += bytes_to_cache;
}
}
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_queue_normal_write(struct target *target, uint32_t bufs_num,
uint32_t buf_sz[], const uint8_t *bufs[])
{
int res = ERROR_OK;
uint32_t cached_bytes = 0;
uint8_t cached_data8[4] = { 0 };
uint32_t cached_data32 = 0;
struct xtensa *xtensa = target_to_xtensa(target);
/* | 1 | 2 | 1 | 2 | 4 |.......|
* | 4 | 4 | 4 | */
xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, 0);
for (unsigned int i = 0; i < bufs_num; i++) {
uint32_t bsz = buf_sz[i];
const uint8_t *cur_buf = bufs[i];
uint32_t bytes_to_cache;
/* if there are cached bytes from the previous buffer, combine them with the last
* from the current buffer */
if (cached_bytes) {
if ((cached_bytes + bsz) < sizeof(uint32_t))
bytes_to_cache = bsz;
else
bytes_to_cache = sizeof(uint32_t) - cached_bytes;
memcpy(&cached_data8[cached_bytes], cur_buf, bytes_to_cache);
cached_bytes += bytes_to_cache;
if (cached_bytes < sizeof(uint32_t))
continue;
cached_data32 = target_buffer_get_u32(target, cached_data8);
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
if (res != ERROR_OK)
return res;
bsz -= bytes_to_cache;
cur_buf += bytes_to_cache;
memset(cached_data8, 0x00, sizeof(cached_data8));
cached_bytes = 0;
}
/* write full dwords */
for (unsigned int k = 0; (k + sizeof(uint32_t)) <= bsz; k += sizeof(uint32_t)) {
uint32_t temp = target_buffer_get_u32(target, cur_buf);
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, temp);
if (res != ERROR_OK)
return res;
cur_buf += sizeof(uint32_t);
}
/* if there are bytes to be cached (1..3) */
bytes_to_cache = bsz & 0x3UL;
if (bytes_to_cache > 0) {
if (bytes_to_cache + cached_bytes >= sizeof(uint32_t)) {
memcpy(&cached_data8[0], cur_buf, sizeof(uint32_t) - cached_bytes);
cached_data32 = target_buffer_get_u32(target, cached_data8);
/* write full word of cached bytes */
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
if (res != ERROR_OK)
return res;
/* cache remaining bytes */
memset(cached_data8, 0x00, sizeof(cached_data8));
cur_buf += sizeof(uint32_t) - cached_bytes;
cached_bytes = bytes_to_cache + cached_bytes - sizeof(uint32_t);
memcpy(&cached_data8[0], cur_buf, cached_bytes);
} else {
memcpy(&cached_data8[cached_bytes], cur_buf, bytes_to_cache);
cached_bytes += bytes_to_cache;
}
}
}
if (cached_bytes) {
/* write remaining cached bytes */
cached_data32 = target_buffer_get_u32(target, cached_data8);
res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
if (res != ERROR_OK)
return res;
}
return ERROR_OK;
}
static int esp_xtensa_apptrace_buffs_write(struct target *target,
uint32_t bufs_num,
uint32_t buf_sz[],
const uint8_t *bufs[],
uint32_t block_id,
bool ack,
bool data)
{
struct xtensa *xtensa = target_to_xtensa(target);
int res = ERROR_OK;
uint32_t tmp = XTENSA_APPTRACE_HOST_CONNECT |
(data ? XTENSA_APPTRACE_HOST_DATA : 0) | XTENSA_APPTRACE_BLOCK_ID(block_id) |
XTENSA_APPTRACE_BLOCK_LEN(0);
if (xtensa->core_config->trace.reversed_mem_access)
res = esp_xtensa_apptrace_queue_reverse_write(target, bufs_num, buf_sz, bufs);
else
res = esp_xtensa_apptrace_queue_normal_write(target, bufs_num, buf_sz, bufs);
if (res != ERROR_OK)
return res;
if (ack) {
LOG_DEBUG("Ack block %" PRId32 " on target (%s)!", block_id, target_name(target));
res = xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
if (res != ERROR_OK)
return res;
}
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_ERROR("Failed to exec JTAG queue!");
return res;
}
return ERROR_OK;
}

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Xtensa application tracing module for OpenOCD *
* Copyright (C) 2017 Espressif Systems Ltd. *
***************************************************************************/
#ifndef OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H
#define OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H
#include "esp32_apptrace.h"
struct esp_xtensa_apptrace_info {
const struct esp32_apptrace_hw *hw;
};
extern struct esp32_apptrace_hw esp_xtensa_apptrace_hw;
int esp_xtensa_apptrace_data_len_read(struct target *target, uint32_t *block_id, uint32_t *len);
int esp_xtensa_apptrace_data_read(struct target *target,
uint32_t size,
uint8_t *buffer,
uint32_t block_id,
bool ack);
int esp_xtensa_apptrace_ctrl_reg_read(struct target *target, uint32_t *block_id, uint32_t *len, bool *conn);
int esp_xtensa_apptrace_ctrl_reg_write(struct target *target,
uint32_t block_id,
uint32_t len,
bool conn,
bool data);
int esp_xtensa_apptrace_status_reg_write(struct target *target, uint32_t stat);
int esp_xtensa_apptrace_status_reg_read(struct target *target, uint32_t *stat);
uint32_t esp_xtensa_apptrace_block_max_size_get(struct target *target);
uint32_t esp_xtensa_apptrace_usr_block_max_size_get(struct target *target);
int esp_xtensa_apptrace_usr_block_write(struct target *target, uint32_t block_id, const uint8_t *data, uint32_t size);
#endif /* OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H */

View File

@ -1706,7 +1706,7 @@ COMMAND_HANDLER(handle_etm_dump_command)
return ERROR_FAIL;
}
if (etm_ctx->capture_driver->status == TRACE_IDLE) {
if (etm_ctx->capture_driver->status(etm_ctx) == TRACE_IDLE) {
command_print(CMD, "trace capture wasn't enabled, no trace data captured");
return ERROR_OK;
}

View File

@ -73,26 +73,26 @@ static const struct {
const char *feature;
} regs[] = {
/* general purpose registers */
{ EAX, "eax", 0x000000D01D660000, 0, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ECX, "ecx", 0x000000501D660000, 1, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EDX, "edx", 0x000000901D660000, 2, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EBX, "ebx", 0x000000101D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ESP, "esp", 0x000000E01D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ EBP, "ebp", 0x000000601D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ ESI, "esi", 0x000000A01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EDI, "edi", 0x000000201D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EAX, "eax", 0x000000D01D660000ULL, 0, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ECX, "ecx", 0x000000501D660000ULL, 1, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EDX, "edx", 0x000000901D660000ULL, 2, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EBX, "ebx", 0x000000101D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ESP, "esp", 0x000000E01D660000ULL, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ EBP, "ebp", 0x000000601D660000ULL, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ ESI, "esi", 0x000000A01D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EDI, "edi", 0x000000201D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
/* instruction pointer & flags */
{ EIP, "eip", 0x000000C01D660000, 3, 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.i386.core" },
{ EFLAGS, "eflags", 0x000000401D660000, 4, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EIP, "eip", 0x000000C01D660000ULL, 3, 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.i386.core" },
{ EFLAGS, "eflags", 0x000000401D660000ULL, 4, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
/* segment registers */
{ CS, "cs", 0x000000281D660000, 5, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ SS, "ss", 0x000000C81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ DS, "ds", 0x000000481D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ES, "es", 0x000000A81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ FS, "fs", 0x000000881D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ GS, "gs", 0x000000081D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ CS, "cs", 0x000000281D660000ULL, 5, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ SS, "ss", 0x000000C81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ DS, "ds", 0x000000481D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ES, "es", 0x000000A81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ FS, "fs", 0x000000881D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ GS, "gs", 0x000000081D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
/* floating point unit registers - not accessible via JTAG - here to satisfy GDB */
{ ST0, "st0", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
@ -113,56 +113,56 @@ static const struct {
{ FOP, "fop", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
/* control registers */
{ CR0, "cr0", 0x000000001D660000, 6, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR2, "cr2", 0x000000BC1D660000, 7, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR3, "cr3", 0x000000801D660000, 8, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR4, "cr4", 0x0000002C1D660000, 9, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR0, "cr0", 0x000000001D660000ULL, 6, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR2, "cr2", 0x000000BC1D660000ULL, 7, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR3, "cr3", 0x000000801D660000ULL, 8, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CR4, "cr4", 0x0000002C1D660000ULL, 9, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
/* debug registers */
{ DR0, "dr0", 0x0000007C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR1, "dr1", 0x000000FC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR2, "dr2", 0x000000021D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR3, "dr3", 0x000000821D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR6, "dr6", 0x000000301D660000, 10, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR7, "dr7", 0x000000B01D660000, 11, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR0, "dr0", 0x0000007C1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR1, "dr1", 0x000000FC1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR2, "dr2", 0x000000021D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR3, "dr3", 0x000000821D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR6, "dr6", 0x000000301D660000ULL, 10, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DR7, "dr7", 0x000000B01D660000ULL, 11, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
/* descriptor tables */
{ IDTB, "idtbase", 0x000000581D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ IDTL, "idtlimit", 0x000000D81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ IDTAR, "idtar", 0x000000981D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTB, "gdtbase", 0x000000B81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTL, "gdtlimit", 0x000000781D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTAR, "gdtar", 0x000000381D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TR, "tr", 0x000000701D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTR, "ldtr", 0x000000F01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTB, "ldbase", 0x000000041D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTL, "ldlimit", 0x000000841D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTAR, "ldtar", 0x000000F81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ IDTB, "idtbase", 0x000000581D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ IDTL, "idtlimit", 0x000000D81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ IDTAR, "idtar", 0x000000981D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTB, "gdtbase", 0x000000B81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTL, "gdtlimit", 0x000000781D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GDTAR, "gdtar", 0x000000381D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TR, "tr", 0x000000701D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTR, "ldtr", 0x000000F01D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTB, "ldbase", 0x000000041D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTL, "ldlimit", 0x000000841D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ LDTAR, "ldtar", 0x000000F81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
/* segment registers */
{ CSB, "csbase", 0x000000F41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CSL, "cslimit", 0x0000000C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CSAR, "csar", 0x000000741D660000, 12, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSB, "dsbase", 0x000000941D660000, 13, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSL, "dslimit", 0x000000541D660000, 14, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSAR, "dsar", 0x000000141D660000, 15, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESB, "esbase", 0x0000004C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESL, "eslimit", 0x000000CC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESAR, "esar", 0x0000008C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSB, "fsbase", 0x000000641D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSL, "fslimit", 0x000000E41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSAR, "fsar", 0x000000A41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSB, "gsbase", 0x000000C41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSL, "gslimit", 0x000000241D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSAR, "gsar", 0x000000441D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSB, "ssbase", 0x000000341D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSL, "sslimit", 0x000000B41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSAR, "ssar", 0x000000D41D660000, 16, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSB, "tssbase", 0x000000E81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSL, "tsslimit", 0x000000181D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSAR, "tssar", 0x000000681D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CSB, "csbase", 0x000000F41D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CSL, "cslimit", 0x0000000C1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ CSAR, "csar", 0x000000741D660000ULL, 12, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSB, "dsbase", 0x000000941D660000ULL, 13, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSL, "dslimit", 0x000000541D660000ULL, 14, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ DSAR, "dsar", 0x000000141D660000ULL, 15, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESB, "esbase", 0x0000004C1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESL, "eslimit", 0x000000CC1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ ESAR, "esar", 0x0000008C1D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSB, "fsbase", 0x000000641D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSL, "fslimit", 0x000000E41D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ FSAR, "fsar", 0x000000A41D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSB, "gsbase", 0x000000C41D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSL, "gslimit", 0x000000241D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ GSAR, "gsar", 0x000000441D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSB, "ssbase", 0x000000341D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSL, "sslimit", 0x000000B41D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ SSAR, "ssar", 0x000000D41D660000ULL, 16, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSB, "tssbase", 0x000000E81D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSL, "tsslimit", 0x000000181D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ TSSAR, "tssar", 0x000000681D660000ULL, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
/* probemode control register */
{ PMCR, "pmcr", 0x000000421D660000, 17, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
{ PMCR, "pmcr", 0x000000421D660000ULL, 17, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
};
static const struct {
@ -171,36 +171,36 @@ static const struct {
uint64_t op;
} instructions[] = {
/* memory read/write */
{ MEMRDB32, "MEMRDB32", 0x0909090909090851 },
{ MEMRDB16, "MEMRDB16", 0x09090909090851E6 },
{ MEMRDH32, "MEMRDH32", 0x090909090908D166 },
{ MEMRDH16, "MEMRDH16", 0x090909090908D1E6 },
{ MEMRDW32, "MEMRDW32", 0x09090909090908D1 },
{ MEMRDW16, "MEMRDW16", 0x0909090908D1E666 },
{ MEMWRB32, "MEMWRB32", 0x0909090909090811 },
{ MEMWRB16, "MEMWRB16", 0x09090909090811E6 },
{ MEMWRH32, "MEMWRH32", 0x0909090909089166 },
{ MEMWRH16, "MEMWRH16", 0x09090909090891E6 },
{ MEMWRW32, "MEMWRW32", 0x0909090909090891 },
{ MEMWRW16, "MEMWRW16", 0x090909090891E666 },
{ MEMRDB32, "MEMRDB32", 0x0909090909090851ULL },
{ MEMRDB16, "MEMRDB16", 0x09090909090851E6ULL },
{ MEMRDH32, "MEMRDH32", 0x090909090908D166ULL },
{ MEMRDH16, "MEMRDH16", 0x090909090908D1E6ULL },
{ MEMRDW32, "MEMRDW32", 0x09090909090908D1ULL },
{ MEMRDW16, "MEMRDW16", 0x0909090908D1E666ULL },
{ MEMWRB32, "MEMWRB32", 0x0909090909090811ULL },
{ MEMWRB16, "MEMWRB16", 0x09090909090811E6ULL },
{ MEMWRH32, "MEMWRH32", 0x0909090909089166ULL },
{ MEMWRH16, "MEMWRH16", 0x09090909090891E6ULL },
{ MEMWRW32, "MEMWRW32", 0x0909090909090891ULL },
{ MEMWRW16, "MEMWRW16", 0x090909090891E666ULL },
/* IO read/write */
{ IORDB32, "IORDB32", 0x0909090909090937 },
{ IORDB16, "IORDB16", 0x09090909090937E6 },
{ IORDH32, "IORDH32", 0x090909090909B766 },
{ IORDH16, "IORDH16", 0x090909090909B7E6 },
{ IORDW32, "IORDW32", 0x09090909090909B7 },
{ IORDW16, "IORDW16", 0x0909090909B7E666 },
{ IOWRB32, "IOWRB32", 0x0909090909090977 },
{ IOWRB16, "IOWRB16", 0x09090909090977E6 },
{ IOWRH32, "IOWRH32", 0x090909090909F766 },
{ IOWRH16, "IOWRH16", 0x090909090909F7E6 },
{ IOWRW32, "IOWRW32", 0x09090909090909F7 },
{ IOWRW16, "IOWRW16", 0x0909090909F7E666 },
{ IORDB32, "IORDB32", 0x0909090909090937ULL },
{ IORDB16, "IORDB16", 0x09090909090937E6ULL },
{ IORDH32, "IORDH32", 0x090909090909B766ULL },
{ IORDH16, "IORDH16", 0x090909090909B7E6ULL },
{ IORDW32, "IORDW32", 0x09090909090909B7ULL },
{ IORDW16, "IORDW16", 0x0909090909B7E666ULL },
{ IOWRB32, "IOWRB32", 0x0909090909090977ULL },
{ IOWRB16, "IOWRB16", 0x09090909090977E6ULL },
{ IOWRH32, "IOWRH32", 0x090909090909F766ULL },
{ IOWRH16, "IOWRH16", 0x090909090909F7E6ULL },
{ IOWRW32, "IOWRW32", 0x09090909090909F7ULL },
{ IOWRW16, "IOWRW16", 0x0909090909F7E666ULL },
/* lakemont1 core shadow ram access opcodes */
{ SRAMACCESS, "SRAMACCESS", 0x0000000E9D660000 },
{ SRAM2PDR, "SRAM2PDR", 0x4CF0000000000000 },
{ PDR2SRAM, "PDR2SRAM", 0x0CF0000000000000 },
{ WBINVD, "WBINVD", 0x09090909090990F0 },
{ SRAMACCESS, "SRAMACCESS", 0x0000000E9D660000ULL },
{ SRAM2PDR, "SRAM2PDR", 0x4CF0000000000000ULL },
{ PDR2SRAM, "PDR2SRAM", 0x0CF0000000000000ULL },
{ WBINVD, "WBINVD", 0x09090909090990F0ULL },
};
bool check_not_halted(const struct target *t)

View File

@ -29,7 +29,7 @@
#undef LOWER16
#define UPPER16(v) ((uint32_t)((v >> 16) & 0xFFFF))
#define LOWER16(v) ((uint32_t)(v & 0xFFFF))
#define MIPS64_PRACC_FASTDATA_AREA 0xffffffffFF200000
#define MIPS64_PRACC_FASTDATA_AREA 0xffffffffFF200000ull
#define MIPS64_PRACC_FASTDATA_SIZE 16
#define MIPS64_FASTDATA_HANDLER_SIZE 0x80

View File

@ -14,6 +14,7 @@
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <rtt/rtt.h>
#include <target/rtt.h>
#include "target.h"

View File

@ -542,12 +542,12 @@ static int stm8_get_core_reg(struct reg *reg)
int retval;
struct stm8_core_reg *stm8_reg = reg->arch_info;
struct target *target = stm8_reg->target;
struct stm8_common *stm8_target = target_to_stm8(target);
struct stm8_common *stm8 = target_to_stm8(target);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
retval = stm8_target->read_core_reg(target, stm8_reg->num);
retval = stm8->read_core_reg(target, stm8_reg->num);
return retval;
}

View File

@ -31,6 +31,7 @@
#endif
#include <helper/align.h>
#include <helper/nvp.h>
#include <helper/time_support.h>
#include <jtag/jtag.h>
#include <flash/nor/core.h>
@ -65,45 +66,6 @@ static int target_get_gdb_fileio_info_default(struct target *target,
static int target_gdb_fileio_end_default(struct target *target, int retcode,
int fileio_errno, bool ctrl_c);
/* targets */
extern struct target_type arm7tdmi_target;
extern struct target_type arm720t_target;
extern struct target_type arm9tdmi_target;
extern struct target_type arm920t_target;
extern struct target_type arm966e_target;
extern struct target_type arm946e_target;
extern struct target_type arm926ejs_target;
extern struct target_type fa526_target;
extern struct target_type feroceon_target;
extern struct target_type dragonite_target;
extern struct target_type xscale_target;
extern struct target_type xtensa_chip_target;
extern struct target_type cortexm_target;
extern struct target_type cortexa_target;
extern struct target_type aarch64_target;
extern struct target_type cortexr4_target;
extern struct target_type arm11_target;
extern struct target_type ls1_sap_target;
extern struct target_type mips_m4k_target;
extern struct target_type mips_mips64_target;
extern struct target_type avr_target;
extern struct target_type dsp563xx_target;
extern struct target_type dsp5680xx_target;
extern struct target_type testee_target;
extern struct target_type avr32_ap7k_target;
extern struct target_type hla_target;
extern struct target_type esp32_target;
extern struct target_type esp32s2_target;
extern struct target_type esp32s3_target;
extern struct target_type or1k_target;
extern struct target_type quark_x10xx_target;
extern struct target_type quark_d20xx_target;
extern struct target_type stm8_target;
extern struct target_type riscv_target;
extern struct target_type mem_ap_target;
extern struct target_type esirisc_target;
extern struct target_type arcv2_target;
static struct target_type *target_types[] = {
&arm7tdmi_target,
&arm9tdmi_target,
@ -141,6 +103,7 @@ static struct target_type *target_types[] = {
&esirisc_target,
&arcv2_target,
&aarch64_target,
&armv8r_target,
&mips_mips64_target,
NULL,
};
@ -154,7 +117,12 @@ static LIST_HEAD(target_trace_callback_list);
static const unsigned int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL;
static LIST_HEAD(empty_smp_targets);
static const struct jim_nvp nvp_assert[] = {
enum nvp_assert {
NVP_DEASSERT,
NVP_ASSERT,
};
static const struct nvp nvp_assert[] = {
{ .name = "assert", NVP_ASSERT },
{ .name = "deassert", NVP_DEASSERT },
{ .name = "T", NVP_ASSERT },
@ -164,7 +132,7 @@ static const struct jim_nvp nvp_assert[] = {
{ .name = NULL, .value = -1 }
};
static const struct jim_nvp nvp_error_target[] = {
static const struct nvp nvp_error_target[] = {
{ .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
{ .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
{ .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
@ -181,9 +149,9 @@ static const struct jim_nvp nvp_error_target[] = {
static const char *target_strerror_safe(int err)
{
const struct jim_nvp *n;
const struct nvp *n;
n = jim_nvp_value2name_simple(nvp_error_target, err);
n = nvp_value2name(nvp_error_target, err);
if (!n->name)
return "unknown";
else
@ -252,7 +220,7 @@ static const struct jim_nvp nvp_target_state[] = {
{ .name = NULL, .value = -1 },
};
static const struct jim_nvp nvp_target_debug_reason[] = {
static const struct nvp nvp_target_debug_reason[] = {
{ .name = "debug-request", .value = DBG_REASON_DBGRQ },
{ .name = "breakpoint", .value = DBG_REASON_BREAKPOINT },
{ .name = "watchpoint", .value = DBG_REASON_WATCHPOINT },
@ -273,7 +241,7 @@ static const struct jim_nvp nvp_target_endian[] = {
{ .name = NULL, .value = -1 },
};
static const struct jim_nvp nvp_reset_modes[] = {
static const struct nvp nvp_reset_modes[] = {
{ .name = "unknown", .value = RESET_UNKNOWN },
{ .name = "run", .value = RESET_RUN },
{ .name = "halt", .value = RESET_HALT },
@ -285,7 +253,7 @@ const char *debug_reason_name(struct target *t)
{
const char *cp;
cp = jim_nvp_value2name_simple(nvp_target_debug_reason,
cp = nvp_value2name(nvp_target_debug_reason,
t->debug_reason)->name;
if (!cp) {
LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason));
@ -323,7 +291,7 @@ const char *target_event_name(enum target_event event)
const char *target_reset_mode_name(enum target_reset_mode reset_mode)
{
const char *cp;
cp = jim_nvp_value2name_simple(nvp_reset_modes, reset_mode)->name;
cp = nvp_value2name(nvp_reset_modes, reset_mode)->name;
if (!cp) {
LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode));
cp = "(*BUG*unknown*BUG*)";
@ -667,8 +635,8 @@ static int target_process_reset(struct command_invocation *cmd, enum target_rese
{
char buf[100];
int retval;
struct jim_nvp *n;
n = jim_nvp_value2name_simple(nvp_reset_modes, reset_mode);
const struct nvp *n;
n = nvp_value2name(nvp_reset_modes, reset_mode);
if (!n->name) {
LOG_ERROR("invalid reset mode");
return ERROR_FAIL;
@ -1864,7 +1832,7 @@ int target_call_reset_callbacks(struct target *target, enum target_reset_mode re
struct target_reset_callback *callback;
LOG_DEBUG("target reset %i (%s)", reset_mode,
jim_nvp_value2name_simple(nvp_reset_modes, reset_mode)->name);
nvp_value2name(nvp_reset_modes, reset_mode)->name);
list_for_each_entry(callback, &target_reset_callback_list, list)
callback->callback(target, reset_mode, callback->priv);
@ -3337,8 +3305,8 @@ COMMAND_HANDLER(handle_reset_command)
enum target_reset_mode reset_mode = RESET_RUN;
if (CMD_ARGC == 1) {
const struct jim_nvp *n;
n = jim_nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
const struct nvp *n;
n = nvp_name2value(nvp_reset_modes, CMD_ARGV[0]);
if ((!n->name) || (n->value == RESET_UNKNOWN))
return ERROR_COMMAND_SYNTAX_ERROR;
reset_mode = n->value;
@ -5752,62 +5720,47 @@ COMMAND_HANDLER(handle_target_halt_gdb)
return target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
}
static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
COMMAND_HANDLER(handle_target_poll)
{
if (argc != 1) {
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR;
}
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);
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
if (!target->tap->enabled) {
command_print(CMD, "[TAP is disabled]");
return ERROR_FAIL;
}
int e;
if (!(target_was_examined(target)))
e = ERROR_TARGET_NOT_EXAMINED;
else
e = target->type->poll(target);
if (e != ERROR_OK)
return JIM_ERR;
return JIM_OK;
return ERROR_TARGET_NOT_EXAMINED;
return target->type->poll(target);
}
static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
COMMAND_HANDLER(handle_target_reset)
{
struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
if (goi.argc != 2) {
Jim_WrongNumArgs(interp, 0, argv,
"([tT]|[fF]|assert|deassert) BOOL");
return JIM_ERR;
const struct nvp *n = nvp_name2value(nvp_assert, CMD_ARGV[0]);
if (!n->name) {
nvp_unknown_command_print(CMD, nvp_assert, NULL, CMD_ARGV[0]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
struct jim_nvp *n;
int e = jim_getopt_nvp(&goi, nvp_assert, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(&goi, nvp_assert, 1);
return e;
}
/* the halt or not param */
jim_wide a;
e = jim_getopt_wide(&goi, &a);
if (e != JIM_OK)
return e;
int a;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], a);
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 (!target->type->assert_reset || !target->type->deassert_reset) {
Jim_SetResultFormatted(interp,
"No target-specific reset for %s",
target_name(target));
return JIM_ERR;
command_print(CMD, "No target-specific reset for %s", target_name(target));
return ERROR_FAIL;
}
if (target->defer_examine)
@ -5820,25 +5773,22 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
/* do the assert */
if (n->value == NVP_ASSERT)
e = target->type->assert_reset(target);
else
e = target->type->deassert_reset(target);
return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
return target->type->assert_reset(target);
return target->type->deassert_reset(target);
}
static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
COMMAND_HANDLER(handle_target_halt)
{
if (argc != 1) {
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR;
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
if (!target->tap->enabled) {
command_print(CMD, "[TAP is disabled]");
return ERROR_FAIL;
}
struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled)
return jim_target_tap_disabled(interp);
int e = target->type->halt(target);
return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
return target->type->halt(target);
}
static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@ -6099,20 +6049,23 @@ static const struct command_registration target_instance_command_handlers[] = {
{
.name = "arp_poll",
.mode = COMMAND_EXEC,
.jim_handler = jim_target_poll,
.handler = handle_target_poll,
.help = "used internally for reset processing",
.usage = "",
},
{
.name = "arp_reset",
.mode = COMMAND_EXEC,
.jim_handler = jim_target_reset,
.handler = handle_target_reset,
.help = "used internally for reset processing",
.usage = "'assert'|'deassert' halt",
},
{
.name = "arp_halt",
.mode = COMMAND_EXEC,
.jim_handler = jim_target_halt,
.handler = handle_target_halt,
.help = "used internally for reset processing",
.usage = "",
},
{
.name = "arp_waitstate",

View File

@ -60,11 +60,6 @@ enum target_state {
TARGET_UNAVAILABLE = 5
};
enum nvp_assert {
NVP_DEASSERT,
NVP_ASSERT,
};
enum target_reset_mode {
RESET_UNKNOWN = 0,
RESET_RUN = 1, /* reset and let target run */

View File

@ -311,4 +311,43 @@ struct target_type {
unsigned int (*data_bits)(struct target *target);
};
extern struct target_type aarch64_target;
extern struct target_type arcv2_target;
extern struct target_type arm11_target;
extern struct target_type arm720t_target;
extern struct target_type arm7tdmi_target;
extern struct target_type arm920t_target;
extern struct target_type arm926ejs_target;
extern struct target_type arm946e_target;
extern struct target_type arm966e_target;
extern struct target_type arm9tdmi_target;
extern struct target_type armv8r_target;
extern struct target_type avr32_ap7k_target;
extern struct target_type avr_target;
extern struct target_type cortexa_target;
extern struct target_type cortexm_target;
extern struct target_type cortexr4_target;
extern struct target_type dragonite_target;
extern struct target_type dsp563xx_target;
extern struct target_type dsp5680xx_target;
extern struct target_type esirisc_target;
extern struct target_type esp32s2_target;
extern struct target_type esp32s3_target;
extern struct target_type esp32_target;
extern struct target_type fa526_target;
extern struct target_type feroceon_target;
extern struct target_type hla_target;
extern struct target_type ls1_sap_target;
extern struct target_type mem_ap_target;
extern struct target_type mips_m4k_target;
extern struct target_type mips_mips64_target;
extern struct target_type or1k_target;
extern struct target_type quark_d20xx_target;
extern struct target_type quark_x10xx_target;
extern struct target_type riscv_target;
extern struct target_type stm8_target;
extern struct target_type testee_target;
extern struct target_type xscale_target;
extern struct target_type xtensa_chip_target;
#endif /* OPENOCD_TARGET_TARGET_TYPE_H */

View File

@ -410,7 +410,7 @@ static int xtensa_core_reg_get(struct reg *reg)
return ERROR_TARGET_NOT_HALTED;
if (!reg->exist) {
if (strncmp(reg->name, "?0x", 3) == 0) {
unsigned int regnum = strtoul(reg->name + 1, 0, 0);
unsigned int regnum = strtoul(reg->name + 1, NULL, 0);
LOG_WARNING("Read unknown register 0x%04x ignored", regnum);
return ERROR_OK;
}
@ -430,7 +430,7 @@ static int xtensa_core_reg_set(struct reg *reg, uint8_t *buf)
if (!reg->exist) {
if (strncmp(reg->name, "?0x", 3) == 0) {
unsigned int regnum = strtoul(reg->name + 1, 0, 0);
unsigned int regnum = strtoul(reg->name + 1, NULL, 0);
LOG_WARNING("Write unknown register 0x%04x ignored", regnum);
return ERROR_OK;
}

View File

@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# BeMicro Cyclone III
adapter driver ftdi
ftdi channel 0
ftdi layout_init 0x0008 0x008b
ftdi vid_pid 0x0403 0xa4a0
reset_config none
transport select jtag
adapter speed 10000
source [find cpld/altera-cycloneiii.cfg]
#quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf
#openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load 0 cycloneiii_blinker.rbf"
# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555"

View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# https://www.latticesemi.com/products/developmentboardsandkits/certuspro-nx-versa-board
adapter driver ftdi
ftdi vid_pid 0x0403 0x6010
ftdi channel 0
ftdi layout_init 0x0008 0x008b
reset_config none
transport select jtag
adapter speed 10000
source [find fpga/lattice_certuspro.cfg]

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Lattice ECP5 evaluation Kit
# https://www.latticesemi.com/view_document?document_id=52479
#
adapter driver ftdi
ftdi vid_pid 0x0403 0x6010
ftdi channel 0
ftdi layout_init 0x0008 0x008b
reset_config none
transport select jtag
adapter speed 6000
source [find fpga/lattice_ecp5.cfg]
#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load 0 shared_folder/ecp5_blinker_impl1.bit"
#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0

View File

@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# GateMateTM FPGA Evaluation Board
# https://www.colognechip.com/programmable-logic/gatemate-evaluation-board/
#
adapter driver ftdi
ftdi vid_pid 0x0403 0x6010
ftdi channel 0
ftdi layout_init 0x0014 0x011b
reset_config none
transport select jtag
adapter speed 6000
source [find fpga/gatemate.cfg]

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Gowin RUNBER FPGA Development Board
# https://www.seeedstudio.com/Gowin-RUNBER-Development-Board-p-4779.html
adapter driver ftdi
ftdi vid_pid 0x0403 0x6010
ftdi channel 0
ftdi layout_init 0x0008 0x008b
reset_config none
transport select jtag
adapter speed 6000
source [find fpga/gowin_gw1n.cfg]
#openocd -f board/gowin_runber.cfg -c "init" -c "pld load 0 impl/pnr/gw1n_blinker.fs"
#ipdbg -start -tap gw1n.tap -hub 0x42 -port 5555 -tool 0

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