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:
commit
af08d582b5
|
@ -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
|
||||
|
|
119
doc/openocd.texi
119
doc/openocd.texi
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(®_params[0]);
|
||||
if (retval != ERROR_OK) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "log.h"
|
||||
#include "time_support.h"
|
||||
#include "util.h"
|
||||
|
||||
COMMAND_HANDLER(handler_util_ms)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
243
src/jtag/tcl.c
243
src/jtag/tcl.c
|
@ -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.",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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,
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
@ -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 */
|
|
@ -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,
|
||||
|
|
|
@ -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 = "",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <helper/binarybuffer.h>
|
||||
#include <helper/command.h>
|
||||
#include <rtt/rtt.h>
|
||||
#include <target/rtt.h>
|
||||
|
||||
#include "target.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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]
|
|
@ -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
|
|
@ -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]
|
|
@ -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
Loading…
Reference in New Issue