Merge up to a35e254c53 from upstream

Checkpatch-ignore: MACRO_ARG_REUSE, MACRO_ARG_PRECEDENCE
Change-Id: Icd10f44d162054f8f32019a579ccbdda2cee7a91
This commit is contained in:
Evgeniy Naydanov 2024-03-28 12:06:34 +03:00
commit 46e7507e48
32 changed files with 1765 additions and 1283 deletions

View File

@ -7348,10 +7348,6 @@ works only for chips that do not have factory pre-programmed region 0
code. code.
@end deffn @end deffn
@deffn {Command} {nrf5 info}
Decodes and shows information from FICR and UICR registers.
@end deffn
@end deffn @end deffn
@deffn {Flash Driver} {ocl} @deffn {Flash Driver} {ocl}
@ -11103,6 +11099,11 @@ EJTAG Register Specification could be found in MIPS Document MD00047F, for
core specific EJTAG Register definition, please check Core Specific SUM manual. core specific EJTAG Register definition, please check Core Specific SUM manual.
@end deffn @end deffn
@deffn {Command} {mips32 dsp} [[register_name] [value]]
Displays all DSP registers' contents or get/set value by register name. Will display
an error if current CPU does not support DSP.
@end deffn
@section RISC-V Architecture @section RISC-V Architecture
@uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG
@ -12353,59 +12354,102 @@ waveform generator. These are synthesize-able hardware descriptions of
logic circuits in addition to software for control, visualization and further analysis. logic circuits in addition to software for control, visualization and further analysis.
In a session using JTAG for its transport protocol, OpenOCD supports the function In a session using JTAG for its transport protocol, OpenOCD supports the function
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
control-software. For more details see @url{http://ipdbg.org}. control-software. The JTAG-Hub is the circuit which transfers the data from JTAG to the
different tools connected to the Hub. Hub implementations for most major FPGA vendors/families
are provided. For more details see @url{http://ipdbg.org}.
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}] @deffn {Command} {ipdbg create-hub} @var{hub_name} @option{-tap @var{tapname}} @option{-ir @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order. @deffnx {Command} {ipdbg create-hub} @var{hub_name} @option{-pld @var{pld_name} [@var{user}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
Creates a IPDBG JTAG Hub. The created hub is later used to start, stop and configure IPDBG JTAG Host servers.
The first argument @var{hub_name} is the name of the created hub. It can be used later as a reference.
The pld drivers are able to provide the tap and ir_value for the IPDBG JTAG-Host server. This will be used with the second variant with option @option{-pld}.
Command options: Command options:
@itemize @bullet @itemize @bullet
@item @option{-start|-stop} starts or stops a IPDBG JTAG-Host server (default: start). @item @var{hub_name} the name of the IPDBG hub.
This name is also used to create the object's command, referred to here
as @command{$hub_name}, and in other places where the Hub needs to be identified.
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}. @item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
@item @option{-hub @var{ir_value}} states that the JTAG hub is
reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}. @item @option{-ir @var{ir_value}} states that the JTAG hub is
@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given. reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}. Also known as @verb{|USERx|} instructions.
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given. The optional @var{dr_length} is the length of the dr.
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a Current JTAG-Hub implementation only supports dr_length=13, which is also the default value.
specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} To support more Hubs than USER registers in a single FPGA it is possible to
use a mechanism known as virtual-ir where the user data-register is reachable if there is a specific value in a second dr.
This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
shift data through vir can be configured. shift data through vir can be configured.
@item @option{-pld @var{pld_name} [@var{user}]} The defined driver for the pld @var{pld_name} is used to get the tap and user instruction.
The pld devices names can be shown by the command @command{pld devices}. With [@var{user}] one can select a different @verb{|USERx|}-Instruction.
If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features.
If your device/vendor is not supported you have to use the first variant.
@end itemize
@end deffn
@deffn {Command} {$hub_name ipdbg start} @option{-tool @var{number}} @option{-port @var{number}}
Starts a IPDBG JTAG-Host server. The remaining arguments can be specified in any order.
Command options:
@itemize @bullet
@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
@end itemize @end itemize
@end deffn @end deffn
or
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}]
Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server.
With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required.
The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}).
The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor. @deffn {Command} {$hub_name ipdbg stop} @option{-tool @var{number}}
So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command. Stops a IPDBG JTAG-Host server.
Command options:
With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate. @itemize @bullet
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
The remaining options are described in the previous command. @end itemize
@end deffn @end deffn
Examples: Examples:
@example @example
ipdbg -start -tap xc6s.tap -hub 0x02 -port 4242 -tool 4 ipdbg create-hub xc6s.ipdbghub -tap xc6s.tap -hub 0x02
xc6s.ipdbghub ipdbg start -port 4242 -tool 4
@end example @end example
Starts a server listening on tcp-port 4242 which connects to tool 4. Creates a IPDBG Hub and starts a server listening on tcp-port 4242 which connects to tool 4.
The connection is through the TAP of a Xilinx Spartan 6 on USER1 instruction (tested with a papillion pro board). The connection is through the TAP of a Xilinx Spartan 6 on USER1 instruction (tested with a papillion pro board).
@example @example
ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1 ipdbg create-hub max10m50.ipdbghub -tap max10m50.tap -hub 0x00C -vir
max10m50.ipdbghub ipdbg start -tool 1 -port 60000
@end example @end example
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1). Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5). The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
@example @example
ipdbg -start -pld xc7.pld -port 5555 -tool 0 ipdbg create-hub xc7.ipdbghub -pld xc7.pld
xc7.ipdbghub ipdbg start -port 5555 -tool 0
@end example @end example
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0). Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
The TAP and ir value used to reach the JTAG Hub is given by the pld driver. The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
@deffn {Command} {$hub_name queuing} @option{-size @var{size}}
Configure the queuing between IPDBG JTAG-Host and Hub.
The maximum possible queue size is 1024 which is also the default.
@itemize @bullet
@item @option{-size @var{size}} max number of transfers in the queue.
@end itemize
@end deffn
@example
bitbang.ibdbghub queuing -size 32
@end example
Send a maximum of 32 transfers to the queue before executing them.
@node Utility Commands @node Utility Commands
@chapter Utility Commands @chapter Utility Commands

View File

@ -17,6 +17,7 @@
#include <target/armv7m.h> #include <target/armv7m.h>
#include <helper/types.h> #include <helper/types.h>
#include <helper/time_support.h> #include <helper/time_support.h>
#include <helper/bits.h>
/* Both those values are constant across the current spectrum ofr nRF5 devices */ /* Both those values are constant across the current spectrum ofr nRF5 devices */
#define WATCHDOG_REFRESH_REGISTER 0x40010600 #define WATCHDOG_REFRESH_REGISTER 0x40010600
@ -42,32 +43,9 @@ enum nrf5_ficr_registers {
NRF51_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040), NRF51_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040),
NRF51_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044), NRF51_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044),
/* CONFIGID is documented on nRF51 series only.
* On nRF52 is present but not documented */
NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C), NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C),
NRF5_FICR_DEVICEID0 = NRF5_FICR_REG(0x060),
NRF5_FICR_DEVICEID1 = NRF5_FICR_REG(0x064),
NRF5_FICR_ER0 = NRF5_FICR_REG(0x080),
NRF5_FICR_ER1 = NRF5_FICR_REG(0x084),
NRF5_FICR_ER2 = NRF5_FICR_REG(0x088),
NRF5_FICR_ER3 = NRF5_FICR_REG(0x08C),
NRF5_FICR_IR0 = NRF5_FICR_REG(0x090),
NRF5_FICR_IR1 = NRF5_FICR_REG(0x094),
NRF5_FICR_IR2 = NRF5_FICR_REG(0x098),
NRF5_FICR_IR3 = NRF5_FICR_REG(0x09C),
NRF5_FICR_DEVICEADDRTYPE = NRF5_FICR_REG(0x0A0),
NRF5_FICR_DEVICEADDR0 = NRF5_FICR_REG(0x0A4),
NRF5_FICR_DEVICEADDR1 = NRF5_FICR_REG(0x0A8),
NRF51_FICR_OVERRIDEN = NRF5_FICR_REG(0x0AC),
NRF51_FICR_NRF_1MBIT0 = NRF5_FICR_REG(0x0B0),
NRF51_FICR_NRF_1MBIT1 = NRF5_FICR_REG(0x0B4),
NRF51_FICR_NRF_1MBIT2 = NRF5_FICR_REG(0x0B8),
NRF51_FICR_NRF_1MBIT3 = NRF5_FICR_REG(0x0BC),
NRF51_FICR_NRF_1MBIT4 = NRF5_FICR_REG(0x0C0),
NRF51_FICR_BLE_1MBIT0 = NRF5_FICR_REG(0x0EC),
NRF51_FICR_BLE_1MBIT1 = NRF5_FICR_REG(0x0F0),
NRF51_FICR_BLE_1MBIT2 = NRF5_FICR_REG(0x0F4),
NRF51_FICR_BLE_1MBIT3 = NRF5_FICR_REG(0x0F8),
NRF51_FICR_BLE_1MBIT4 = NRF5_FICR_REG(0x0FC),
/* Following registers are available on nRF52 and on nRF51 since rev 3 */ /* Following registers are available on nRF52 and on nRF51 since rev 3 */
NRF5_FICR_INFO_PART = NRF5_FICR_REG(0x100), NRF5_FICR_INFO_PART = NRF5_FICR_REG(0x100),
@ -84,9 +62,6 @@ enum nrf5_uicr_registers {
#define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset) #define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
NRF51_UICR_CLENR0 = NRF5_UICR_REG(0x000), NRF51_UICR_CLENR0 = NRF5_UICR_REG(0x000),
NRF51_UICR_RBPCONF = NRF5_UICR_REG(0x004),
NRF51_UICR_XTALFREQ = NRF5_UICR_REG(0x008),
NRF51_UICR_FWID = NRF5_UICR_REG(0x010),
}; };
enum nrf5_nvmc_registers { enum nrf5_nvmc_registers {
@ -120,10 +95,10 @@ struct nrf52_ficr_info {
}; };
enum nrf5_features { enum nrf5_features {
NRF5_FEATURE_SERIES_51 = 1 << 0, NRF5_FEATURE_SERIES_51 = BIT(0),
NRF5_FEATURE_SERIES_52 = 1 << 1, NRF5_FEATURE_SERIES_52 = BIT(1),
NRF5_FEATURE_BPROT = 1 << 2, NRF5_FEATURE_BPROT = BIT(2),
NRF5_FEATURE_ACL_PROT = 1 << 3, NRF5_FEATURE_ACL_PROT = BIT(3),
}; };
struct nrf5_device_spec { struct nrf5_device_spec {
@ -164,26 +139,20 @@ struct nrf5_info {
.features = NRF5_FEATURE_SERIES_51, \ .features = NRF5_FEATURE_SERIES_51, \
} }
#define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize, features) \ /*
{ \ * The table maps known HWIDs to the part numbers, variant
.hwid = (id), \ * build code and some other info. For nRF51 rev 1 and 2 devices
.part = pt, \ * this is the only way how to get the part number and variant.
.variant = var, \
.build_code = bcode, \
.flash_size_kb = (fsize), \
.features = features, \
}
/* The known devices table below is derived from the "nRF5x series
* compatibility matrix" documents, which can be found in the "DocLib" of
* nordic:
* *
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51422_ic_revision_overview * All tested nRF51 rev 3 devices have FICR INFO fields
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51822_ic_revision_overview * but the fields are not documented in RM so we keep HWIDs in
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51824_ic_revision_overview * this table.
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52810/latest/COMP/nrf52810/nRF52810_ic_revision_overview *
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52832/latest/COMP/nrf52832/ic_revision_overview * nRF52 and newer devices have FICR INFO documented, the autodetection
* https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52840/latest/COMP/nrf52840/nRF52840_ic_revision_overview * can rely on it and HWIDs table is not used.
*
* The known devices table below is derived from the "nRF5x series
* compatibility matrix" documents.
* *
* Up to date with Matrix v2.0, plus some additional HWIDs. * Up to date with Matrix v2.0, plus some additional HWIDs.
* *
@ -248,19 +217,6 @@ static const struct nrf5_device_spec nrf5_known_devices_table[] = {
/* The driver fully autodetects nRF52 series devices by FICR INFO, /* The driver fully autodetects nRF52 series devices by FICR INFO,
* no need for nRF52xxx HWIDs in this table */ * no need for nRF52xxx HWIDs in this table */
#if 0
/* nRF52810 Devices */
NRF5_DEVICE_DEF(0x0142, "52810", "QFAA", "B0", 192, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
NRF5_DEVICE_DEF(0x0143, "52810", "QCAA", "C0", 192, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
/* nRF52832 Devices */
NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT),
/* nRF52840 Devices */
NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0", 1024, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_ACL_PROT),
#endif
}; };
struct nrf5_device_package { struct nrf5_device_package {
@ -270,11 +226,16 @@ struct nrf5_device_package {
/* Newer devices have FICR INFO.PACKAGE. /* Newer devices have FICR INFO.PACKAGE.
* This table converts its value to two character code */ * This table converts its value to two character code */
static const struct nrf5_device_package nrf5_packages_table[] = { static const struct nrf5_device_package nrf52_packages_table[] = {
{ 0x2000, "QF" }, { 0x2000, "QF" },
{ 0x2001, "CH" }, { 0x2001, "CH" },
{ 0x2002, "CI" }, { 0x2002, "CI" },
{ 0x2003, "QC" },
{ 0x2004, "QI/CA" }, /* differs nRF52805, 810, 811: CA, nRF52833, 840: QI */
{ 0x2005, "CK" }, { 0x2005, "CK" },
{ 0x2007, "QD" },
{ 0x2008, "CJ" },
{ 0x2009, "CF" },
}; };
const struct flash_driver nrf5_flash, nrf51_flash; const struct flash_driver nrf5_flash, nrf51_flash;
@ -282,28 +243,10 @@ const struct flash_driver nrf5_flash, nrf51_flash;
static bool nrf5_bank_is_probed(const struct flash_bank *bank) static bool nrf5_bank_is_probed(const struct flash_bank *bank)
{ {
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank); assert(nbank);
return nbank->probed; return nbank->probed;
} }
static int nrf5_probe(struct flash_bank *bank);
static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf5_info **chip)
{
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
*chip = nbank->chip;
if (nrf5_bank_is_probed(bank))
return ERROR_OK;
return nrf5_probe(bank);
}
static int nrf5_wait_for_nvmc(struct nrf5_info *chip) static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
{ {
@ -431,9 +374,10 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank)
{ {
int res; int res;
uint32_t clenr0; uint32_t clenr0;
struct nrf5_bank *nbank = bank->driver_priv;
struct nrf5_info *chip = nbank->chip;
struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip;
assert(chip); assert(chip);
res = target_read_u32(chip->target, NRF51_FICR_CLENR0, res = target_read_u32(chip->target, NRF51_FICR_CLENR0,
@ -462,8 +406,8 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank)
static int nrf5_protect_check_bprot(struct flash_bank *bank) static int nrf5_protect_check_bprot(struct flash_bank *bank)
{ {
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
assert(chip); assert(chip);
static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 }; static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 };
@ -493,8 +437,8 @@ static int nrf5_protect_check(struct flash_bank *bank)
return ERROR_OK; return ERROR_OK;
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
assert(chip); assert(chip);
if (chip->features & NRF5_FEATURE_BPROT) if (chip->features & NRF5_FEATURE_BPROT)
@ -512,8 +456,11 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int fi
{ {
int res; int res;
uint32_t clenr0, ppfc; uint32_t clenr0, ppfc;
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
assert(chip);
if (first != 0) { if (first != 0) {
LOG_ERROR("Code region 0 must start at the beginning of the bank"); LOG_ERROR("Code region 0 must start at the beginning of the bank");
@ -570,18 +517,21 @@ error:
static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
unsigned int last) unsigned int last)
{ {
int res;
struct nrf5_info *chip;
/* UICR cannot be write protected so just bail out early */ /* UICR cannot be write protected so just bail out early */
if (bank->base == NRF5_UICR_BASE) { if (bank->base == NRF5_UICR_BASE) {
LOG_ERROR("UICR page does not support protection"); LOG_ERROR("UICR page does not support protection");
return ERROR_FLASH_OPER_UNSUPPORTED; return ERROR_FLASH_OPER_UNSUPPORTED;
} }
res = nrf5_get_probed_chip_if_halted(bank, &chip); if (bank->target->state != TARGET_HALTED) {
if (res != ERROR_OK) LOG_ERROR("Target not halted");
return res; return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip;
assert(chip);
if (chip->features & NRF5_FEATURE_SERIES_51) if (chip->features & NRF5_FEATURE_SERIES_51)
return nrf5_protect_clenr0(bank, set, first, last); return nrf5_protect_clenr0(bank, set, first, last);
@ -607,9 +557,9 @@ static bool nrf5_info_variant_to_str(uint32_t variant, char *bf)
static const char *nrf5_decode_info_package(uint32_t package) static const char *nrf5_decode_info_package(uint32_t package)
{ {
for (size_t i = 0; i < ARRAY_SIZE(nrf5_packages_table); i++) { for (size_t i = 0; i < ARRAY_SIZE(nrf52_packages_table); i++) {
if (nrf5_packages_table[i].package == package) if (nrf52_packages_table[i].package == package)
return nrf5_packages_table[i].code; return nrf52_packages_table[i].code;
} }
return "xx"; return "xx";
} }
@ -642,7 +592,9 @@ static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsig
static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd)
{ {
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
assert(chip);
char chip_type_str[256]; char chip_type_str[256];
if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
@ -676,11 +628,15 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip)
chip->features = NRF5_FEATURE_SERIES_52; chip->features = NRF5_FEATURE_SERIES_52;
switch (chip->ficr_info.part) { switch (chip->ficr_info.part) {
case 0x52805:
case 0x52810: case 0x52810:
case 0x52811:
case 0x52832: case 0x52832:
chip->features |= NRF5_FEATURE_BPROT; chip->features |= NRF5_FEATURE_BPROT;
break; break;
case 0x52820:
case 0x52833:
case 0x52840: case 0x52840:
chip->features |= NRF5_FEATURE_ACL_PROT; chip->features |= NRF5_FEATURE_ACL_PROT;
break; break;
@ -755,8 +711,11 @@ static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size)
static int nrf5_probe(struct flash_bank *bank) static int nrf5_probe(struct flash_bank *bank)
{ {
int res; int res;
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
assert(chip);
struct target *target = chip->target; struct target *target = chip->target;
uint32_t configid; uint32_t configid;
@ -1024,11 +983,17 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t address, const u
static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count) uint32_t offset, uint32_t count)
{ {
struct nrf5_info *chip; int res;
int res = nrf5_get_probed_chip_if_halted(bank, &chip); if (bank->target->state != TARGET_HALTED) {
if (res != ERROR_OK) LOG_ERROR("Target not halted");
return res; return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip;
assert(chip);
assert(offset % 4 == 0); assert(offset % 4 == 0);
assert(count % 4 == 0); assert(count % 4 == 0);
@ -1081,11 +1046,16 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
unsigned int last) unsigned int last)
{ {
int res; int res;
struct nrf5_info *chip;
res = nrf5_get_probed_chip_if_halted(bank, &chip); if (bank->target->state != TARGET_HALTED) {
if (res != ERROR_OK) LOG_ERROR("Target not halted");
return res; return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip;
assert(chip);
/* UICR CLENR0 based protection used on nRF51 prevents erase /* UICR CLENR0 based protection used on nRF51 prevents erase
* absolutely silently. NVMC has no flag to indicate the protection * absolutely silently. NVMC has no flag to indicate the protection
@ -1101,7 +1071,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
} }
/* For each sector to be erased */ /* For each sector to be erased */
for (unsigned int s = first; s <= last && res == ERROR_OK; s++) { for (unsigned int s = first; s <= last; s++) {
if (chip->features & NRF5_FEATURE_SERIES_51 if (chip->features & NRF5_FEATURE_SERIES_51
&& bank->sectors[s].is_protected == 1) { && bank->sectors[s].is_protected == 1) {
@ -1122,6 +1092,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
static void nrf5_free_driver_priv(struct flash_bank *bank) static void nrf5_free_driver_priv(struct flash_bank *bank)
{ {
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
assert(nbank);
struct nrf5_info *chip = nbank->chip; struct nrf5_info *chip = nbank->chip;
if (!chip) if (!chip)
return; return;
@ -1160,6 +1131,9 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
struct nrf5_info *chip; struct nrf5_info *chip;
struct nrf5_bank *nbank = NULL; struct nrf5_bank *nbank = NULL;
if (bank->driver == &nrf51_flash)
LOG_WARNING("Flash driver 'nrf51' is deprecated! Use 'nrf5' instead.");
switch (bank->base) { switch (bank->base) {
case NRF5_FLASH_BASE: case NRF5_FLASH_BASE:
case NRF5_UICR_BASE: case NRF5_UICR_BASE:
@ -1210,11 +1184,15 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
assert(bank); assert(bank);
struct nrf5_info *chip; if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
res = nrf5_get_probed_chip_if_halted(bank, &chip); struct nrf5_bank *nbank = bank->driver_priv;
if (res != ERROR_OK) assert(nbank);
return res; struct nrf5_info *chip = nbank->chip;
assert(chip);
if (chip->features & NRF5_FEATURE_SERIES_51) { if (chip->features & NRF5_FEATURE_SERIES_51) {
uint32_t ppfc; uint32_t ppfc;
@ -1245,137 +1223,6 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
return res; return res;
} }
COMMAND_HANDLER(nrf5_handle_info_command)
{
int res;
struct flash_bank *bank = NULL;
struct target *target = get_current_target(CMD_CTX);
res = get_flash_bank_by_addr(target, NRF5_FLASH_BASE, true, &bank);
if (res != ERROR_OK)
return res;
assert(bank);
struct nrf5_info *chip;
res = nrf5_get_probed_chip_if_halted(bank, &chip);
if (res != ERROR_OK)
return res;
static struct {
const uint32_t address;
uint32_t value;
} ficr[] = {
{ .address = NRF5_FICR_CODEPAGESIZE },
{ .address = NRF5_FICR_CODESIZE },
{ .address = NRF51_FICR_CLENR0 },
{ .address = NRF51_FICR_PPFC },
{ .address = NRF51_FICR_NUMRAMBLOCK },
{ .address = NRF51_FICR_SIZERAMBLOCK0 },
{ .address = NRF51_FICR_SIZERAMBLOCK1 },
{ .address = NRF51_FICR_SIZERAMBLOCK2 },
{ .address = NRF51_FICR_SIZERAMBLOCK3 },
{ .address = NRF5_FICR_CONFIGID },
{ .address = NRF5_FICR_DEVICEID0 },
{ .address = NRF5_FICR_DEVICEID1 },
{ .address = NRF5_FICR_ER0 },
{ .address = NRF5_FICR_ER1 },
{ .address = NRF5_FICR_ER2 },
{ .address = NRF5_FICR_ER3 },
{ .address = NRF5_FICR_IR0 },
{ .address = NRF5_FICR_IR1 },
{ .address = NRF5_FICR_IR2 },
{ .address = NRF5_FICR_IR3 },
{ .address = NRF5_FICR_DEVICEADDRTYPE },
{ .address = NRF5_FICR_DEVICEADDR0 },
{ .address = NRF5_FICR_DEVICEADDR1 },
{ .address = NRF51_FICR_OVERRIDEN },
{ .address = NRF51_FICR_NRF_1MBIT0 },
{ .address = NRF51_FICR_NRF_1MBIT1 },
{ .address = NRF51_FICR_NRF_1MBIT2 },
{ .address = NRF51_FICR_NRF_1MBIT3 },
{ .address = NRF51_FICR_NRF_1MBIT4 },
{ .address = NRF51_FICR_BLE_1MBIT0 },
{ .address = NRF51_FICR_BLE_1MBIT1 },
{ .address = NRF51_FICR_BLE_1MBIT2 },
{ .address = NRF51_FICR_BLE_1MBIT3 },
{ .address = NRF51_FICR_BLE_1MBIT4 },
}, uicr[] = {
{ .address = NRF51_UICR_CLENR0, },
{ .address = NRF51_UICR_RBPCONF },
{ .address = NRF51_UICR_XTALFREQ },
{ .address = NRF51_UICR_FWID },
};
for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) {
res = target_read_u32(chip->target, ficr[i].address,
&ficr[i].value);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address);
return res;
}
}
for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) {
res = target_read_u32(chip->target, uicr[i].address,
&uicr[i].value);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address);
return res;
}
}
command_print(CMD,
"\n[factory information control block]\n\n"
"code page size: %"PRIu32"B\n"
"code memory size: %"PRIu32"kB\n"
"code region 0 size: %"PRIu32"kB\n"
"pre-programmed code: %s\n"
"number of ram blocks: %"PRIu32"\n"
"ram block 0 size: %"PRIu32"B\n"
"ram block 1 size: %"PRIu32"B\n"
"ram block 2 size: %"PRIu32"B\n"
"ram block 3 size: %"PRIu32 "B\n"
"config id: %" PRIx32 "\n"
"device id: 0x%"PRIx32"%08"PRIx32"\n"
"encryption root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
"identity root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
"device address type: 0x%"PRIx32"\n"
"device address: 0x%"PRIx32"%08"PRIx32"\n"
"override enable: %"PRIx32"\n"
"NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
"BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
"\n[user information control block]\n\n"
"code region 0 size: %"PRIu32"kB\n"
"read back protection configuration: %"PRIx32"\n"
"reset value for XTALFREQ: %"PRIx32"\n"
"firmware id: 0x%04"PRIx32,
ficr[0].value,
(ficr[1].value * ficr[0].value) / 1024,
(ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
ficr[4].value,
ficr[5].value,
(ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value,
(ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value,
(ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value,
ficr[9].value,
ficr[10].value, ficr[11].value,
ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value,
ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value,
ficr[20].value,
ficr[21].value, ficr[22].value,
ficr[23].value,
ficr[24].value, ficr[25].value, ficr[26].value, ficr[27].value, ficr[28].value,
ficr[29].value, ficr[30].value, ficr[31].value, ficr[32].value, ficr[33].value,
(uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024,
uicr[1].value & 0xFFFF,
uicr[2].value & 0xFF,
uicr[3].value & 0xFFFF);
return ERROR_OK;
}
static const struct command_registration nrf5_exec_command_handlers[] = { static const struct command_registration nrf5_exec_command_handlers[] = {
{ {
@ -1385,13 +1232,6 @@ static const struct command_registration nrf5_exec_command_handlers[] = {
.help = "Erase all flash contents of the chip.", .help = "Erase all flash contents of the chip.",
.usage = "", .usage = "",
}, },
{
.name = "info",
.handler = nrf5_handle_info_command,
.mode = COMMAND_EXEC,
.help = "Show FICR and UICR info.",
.usage = "",
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -11,7 +11,8 @@
#ifndef OPENOCD_HELPER_BINARYBUFFER_H #ifndef OPENOCD_HELPER_BINARYBUFFER_H
#define OPENOCD_HELPER_BINARYBUFFER_H #define OPENOCD_HELPER_BINARYBUFFER_H
#include "list.h" #include <helper/list.h>
#include <helper/types.h>
/** @file /** @file
* Support functions to access arbitrary bits in a byte array * Support functions to access arbitrary bits in a byte array

File diff suppressed because it is too large Load Diff

View File

@ -114,6 +114,15 @@ extern int debug_level;
expr); \ expr); \
} while (0) } while (0)
#define LOG_CUSTOM_LEVEL(level, expr ...) \
do { \
enum log_levels _level = level; \
if (debug_level >= _level) \
log_printf_lf(_level, \
__FILE__, __LINE__, __func__, \
expr); \
} while (0)
#define LOG_INFO(expr ...) \ #define LOG_INFO(expr ...) \
log_printf_lf(LOG_LVL_INFO, __FILE__, __LINE__, __func__, expr) log_printf_lf(LOG_LVL_INFO, __FILE__, __LINE__, __func__, expr)

View File

@ -341,6 +341,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
exit(0); exit(0);
} }
/* dump full command line */
for (int i = 0; i < argc; i++)
LOG_DEBUG("ARGV[%d] = \"%s\"", i, argv[i]);
/* paths specified on the command line take precedence over these /* paths specified on the command line take precedence over these
* built-in paths * built-in paths
*/ */

View File

@ -20,6 +20,11 @@
#include <jtag/interface.h> #include <jtag/interface.h>
#include <jtag/commands.h> #include <jtag/commands.h>
#include <helper/time_support.h>
/* Timeout for retrying on SWD WAIT in msec */
#define SWD_WAIT_TIMEOUT 500
/** /**
* Function bitbang_stableclocks * Function bitbang_stableclocks
* issues a number of clock cycles while staying in a stable state. * issues a number of clock cycles while staying in a stable state.
@ -474,7 +479,8 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay
return; return;
} }
for (;;) { int64_t timeout = timeval_ms() + SWD_WAIT_TIMEOUT;
for (unsigned int retry = 0;; retry++) {
uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
cmd |= SWD_CMD_START | SWD_CMD_PARK; cmd |= SWD_CMD_START | SWD_CMD_PARK;
@ -488,16 +494,25 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay
uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32); uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32);
int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1); int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1);
LOG_DEBUG_IO("%s %s read reg %X = %08" PRIx32, LOG_CUSTOM_LEVEL((ack != SWD_ACK_OK && (retry == 0 || ack != SWD_ACK_WAIT))
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
cmd & SWD_CMD_APNDP ? "AP" : "DP", "%s %s read reg %X = %08" PRIx32,
(cmd & SWD_CMD_A32) >> 1, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
data); cmd & SWD_CMD_APNDP ? "AP" : "DP",
(cmd & SWD_CMD_A32) >> 1,
data);
if (ack == SWD_ACK_WAIT) { if (ack == SWD_ACK_WAIT && timeval_ms() <= timeout) {
swd_clear_sticky_errors(); swd_clear_sticky_errors();
if (retry > 20)
alive_sleep(1);
continue; continue;
} else if (ack != SWD_ACK_OK) { }
if (retry > 1)
LOG_DEBUG("SWD WAIT: retried %u times", retry);
if (ack != SWD_ACK_OK) {
queued_retval = swd_ack_to_error_code(ack); queued_retval = swd_ack_to_error_code(ack);
return; return;
} }
@ -524,12 +539,14 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
return; return;
} }
int64_t timeout = timeval_ms() + SWD_WAIT_TIMEOUT;
/* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
bool check_ack = swd_cmd_returns_ack(cmd); bool check_ack = swd_cmd_returns_ack(cmd);
/* init the array to silence scan-build */ /* init the array to silence scan-build */
uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)] = {0}; uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)] = {0};
for (;;) { for (unsigned int retry = 0;; retry++) {
buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value); buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value);
buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value)); buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value));
@ -554,22 +571,29 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1); bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3); int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK && (retry == 0 || ack != SWD_ACK_WAIT))
? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
"%s%s %s write reg %X = %08" PRIx32,
check_ack ? "" : "ack ignored ",
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
(cmd & SWD_CMD_A32) >> 1,
buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
LOG_DEBUG_IO("%s%s %s write reg %X = %08" PRIx32, if (check_ack && ack == SWD_ACK_WAIT && timeval_ms() <= timeout) {
check_ack ? "" : "ack ignored ", swd_clear_sticky_errors();
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", if (retry > 20)
cmd & SWD_CMD_APNDP ? "AP" : "DP", alive_sleep(1);
(cmd & SWD_CMD_A32) >> 1,
buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
if (check_ack) { continue;
if (ack == SWD_ACK_WAIT) { }
swd_clear_sticky_errors();
continue; if (retry > 1)
} else if (ack != SWD_ACK_OK) { LOG_DEBUG("SWD WAIT: retried %u times", retry);
queued_retval = swd_ack_to_error_code(ack);
return; if (check_ack && ack != SWD_ACK_OK) {
} queued_retval = swd_ack_to_error_code(ack);
return;
} }
if (cmd & SWD_CMD_APNDP) if (cmd & SWD_CMD_APNDP)

View File

@ -944,7 +944,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
if (ack != SWD_ACK_OK) { if (ack != SWD_ACK_OK) {
LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count, LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; queued_retval = swd_ack_to_error_code(ack);
/* TODO: use results of transfers completed before the error occurred? */ /* TODO: use results of transfers completed before the error occurred? */
goto skip; goto skip;
} }

View File

@ -1506,7 +1506,8 @@ static int ftdi_swd_run_queue(void)
/* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
bool check_ack = swd_cmd_returns_ack(swd_cmd_queue[i].cmd); bool check_ack = swd_cmd_returns_ack(swd_cmd_queue[i].cmd);
LOG_DEBUG_IO("%s%s %s %s reg %X = %08"PRIx32, LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
"%s%s %s %s reg %X = %08" PRIx32,
check_ack ? "" : "ack ignored ", check_ack ? "" : "ack ignored ",
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
swd_cmd_queue[i].cmd & SWD_CMD_APNDP ? "AP" : "DP", swd_cmd_queue[i].cmd & SWD_CMD_APNDP ? "AP" : "DP",

View File

@ -782,7 +782,7 @@ static int kitprog_swd_run_queue(void)
if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) { if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) {
LOG_DEBUG("SWD ack not OK: %d %s", i, LOG_DEBUG("SWD ack not OK: %d %s", i,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; queued_retval = swd_ack_to_error_code(ack);
break; break;
} }
read_index++; read_index++;

View File

@ -1146,4 +1146,132 @@ proc "pld device" {driver tap_name {opt 0}} {
} }
} }
lappend _telnet_autocomplete_skip "ipdbg -start"
proc "ipdbg -start" {args} {
echo "DEPRECATED! use 'ipdbg create-hub' and 'chip.ipdbghub ipdbg start ...', not 'ipdbg -start ...'"
set tap_name ""
set pld_name ""
set tool_num "1"
set port_num "4242"
set idx 0
set num_args [llength $args]
while {$idx < $num_args} {
set arg [lindex $args $idx]
switch -- $arg {
"-tap" {
incr idx
if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
echo "no TAP name given"
return
}
set tap_name [lindex $args $idx]
}
"-pld" {
incr idx
if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
echo "no PLD name given"
return
}
set pld_name [lindex $args $idx]
}
"-tool" {
if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
set tool_num [lindex $args [expr {$idx + 1}]]
set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]]
incr num_args -1
}
set args [lreplace $args $idx $idx]
incr num_args -1
incr idx -1
}
"-port" {
if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
set port_num [lindex $args [expr {$idx + 1}]]
set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]]
incr num_args -1
}
set args [lreplace $args $idx $idx]
incr num_args -1
incr idx -1
}
"-hub" {
set args [lreplace $args $idx $idx "-ir" ]
}
default {
# don't touch remaining arguments
}
}
incr idx
}
set hub_name ""
if {$tap_name != ""} {
set hub_name [lindex [split $tap_name .] 0].ipdbghub
} elseif {$pld_name != ""} {
set hub_name [lindex [split $pld_name .] 0].ipdbghub
} else {
echo "parsing arguments failed: no tap and no pld given."
return
}
echo "name: $hub_name"
echo "ipdbg create-hub $hub_name $args"
catch {eval ipdbg create-hub $hub_name $args}
eval $hub_name ipdbg start -tool $tool_num -port $port_num
}
lappend _telnet_autocomplete_skip "ipdbg -stop"
proc "ipdbg -stop" {args} {
echo "DEPRECATED! use 'chip.ipdbghub ipdbg stop ...', not 'ipdbg -stop ...'"
set tap_name ""
set pld_name ""
set tool_num "1"
set idx 0
set num_args [llength $args]
while {$idx < $num_args} {
set arg [lindex $args $idx]
switch -- $arg {
"-tap" {
incr idx
if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
echo "no TAP name given"
return
}
set tap_name [lindex $args $idx]
}
"-pld" {
incr idx
if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
echo "no PLD name given"
return
}
set pld_name [lindex $args $idx]
}
"-tool" {
if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
set tool_num [lindex $args [expr {$idx + 1}]]
}
}
default {
# don't touch remaining arguments
}
}
incr idx
}
set hub_name ""
if {$tap_name != ""} {
set hub_name [lindex [split $tap_name .] 0].ipdbghub
} elseif {$pld_name != ""} {
set hub_name [lindex [split $pld_name .] 0].ipdbghub
} else {
echo "parsing arguments failed: no tap and no pld given."
return
}
eval $hub_name ipdbg stop -tool $tool_num
}
# END MIGRATION AIDS # END MIGRATION AIDS

View File

@ -53,6 +53,8 @@
enum gdb_output_flag { enum gdb_output_flag {
/* GDB doesn't accept 'O' packets */ /* GDB doesn't accept 'O' packets */
GDB_OUTPUT_NO, GDB_OUTPUT_NO,
/* GDB doesn't accept 'O' packets but accepts notifications */
GDB_OUTPUT_NOTIF,
/* GDB accepts 'O' packets */ /* GDB accepts 'O' packets */
GDB_OUTPUT_ALL, GDB_OUTPUT_ALL,
}; };
@ -71,6 +73,8 @@ struct gdb_connection {
enum target_state frontend_state; enum target_state frontend_state;
struct image *vflash_image; struct image *vflash_image;
bool closed; bool closed;
/* set to prevent re-entrance from log messages during gdb_get_packet()
* and gdb_put_packet(). */
bool busy; bool busy;
int noack_mode; int noack_mode;
/* set flag to true if you want the next stepi to return immediately. /* set flag to true if you want the next stepi to return immediately.
@ -1537,9 +1541,6 @@ static int gdb_error(struct connection *connection, int retval)
return ERROR_OK; return ERROR_OK;
} }
/* We don't have to worry about the default 2 second timeout for GDB packets,
* because GDB breaks up large memory reads into smaller reads.
*/
static int gdb_read_memory_packet(struct connection *connection, static int gdb_read_memory_packet(struct connection *connection,
char const *packet, int packet_size) char const *packet, int packet_size)
{ {
@ -3470,6 +3471,13 @@ static int gdb_v_packet(struct connection *connection,
if (strncmp(packet, "vFlashDone", 10) == 0) { if (strncmp(packet, "vFlashDone", 10) == 0) {
uint32_t written; uint32_t written;
/* GDB command 'flash-erase' does not send a vFlashWrite,
* so nothing to write here. */
if (!gdb_connection->vflash_image) {
gdb_put_packet(connection, "OK", 2);
return ERROR_OK;
}
/* process the flashing buffer. No need to erase as GDB /* process the flashing buffer. No need to erase as GDB
* always issues a vFlashErase first. */ * always issues a vFlashErase first. */
target_call_event_callbacks(target, target_call_event_callbacks(target,
@ -3564,7 +3572,7 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
struct connection *connection = priv; struct connection *connection = priv;
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
if (gdb_con->output_flag == GDB_OUTPUT_NO) if (gdb_con->output_flag != GDB_OUTPUT_ALL)
/* No out allowed */ /* No out allowed */
return; return;
@ -3649,10 +3657,14 @@ static int gdb_input_inner(struct connection *connection)
retval = gdb_set_register_packet(connection, packet, packet_size); retval = gdb_set_register_packet(connection, packet, packet_size);
break; break;
case 'm': case 'm':
gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_read_memory_packet(connection, packet, packet_size); retval = gdb_read_memory_packet(connection, packet, packet_size);
gdb_con->output_flag = GDB_OUTPUT_NO;
break; break;
case 'M': case 'M':
gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_write_memory_packet(connection, packet, packet_size); retval = gdb_write_memory_packet(connection, packet, packet_size);
gdb_con->output_flag = GDB_OUTPUT_NO;
break; break;
case 'z': case 'z':
case 'Z': case 'Z':
@ -3743,9 +3755,9 @@ static int gdb_input_inner(struct connection *connection)
retval = gdb_detach(connection); retval = gdb_detach(connection);
break; break;
case 'X': case 'X':
gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_write_memory_binary_packet(connection, packet, packet_size); retval = gdb_write_memory_binary_packet(connection, packet, packet_size);
if (retval != ERROR_OK) gdb_con->output_flag = GDB_OUTPUT_NO;
return retval;
break; break;
case 'k': case 'k':
if (gdb_con->extended_protocol) { if (gdb_con->extended_protocol) {
@ -3843,19 +3855,51 @@ static int gdb_input(struct connection *connection)
return ERROR_OK; return ERROR_OK;
} }
/*
* Send custom notification packet as keep-alive during memory read/write.
*
* From gdb 7.0 (released 2009-10-06) an unknown notification received during
* memory read/write would be silently dropped.
* Before gdb 7.0 any character, with exclusion of "+-$", would be considered
* as junk and ignored.
* In both cases the reception will reset the timeout counter in gdb, thus
* working as a keep-alive.
* Check putpkt_binary() and getpkt_sane() in gdb commit
* 74531fed1f2d662debc2c209b8b3faddceb55960
*
* Enable remote debug in gdb with 'set debug remote 1' to either dump the junk
* characters in gdb pre-7.0 and the notification from gdb 7.0.
*/
static void gdb_async_notif(struct connection *connection)
{
static unsigned char count;
unsigned char checksum = 0;
char buf[22];
int len = sprintf(buf, "%%oocd_keepalive:%2.2x", count++);
for (int i = 1; i < len; i++)
checksum += buf[i];
len += sprintf(buf + len, "#%2.2x", checksum);
#ifdef _DEBUG_GDB_IO_
LOG_DEBUG("sending packet '%s'", buf);
#endif
gdb_write(connection, buf, len);
}
static void gdb_keep_client_alive(struct connection *connection) static void gdb_keep_client_alive(struct connection *connection)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
if (gdb_con->busy) {
/* do not send packets, retry asap */
return;
}
switch (gdb_con->output_flag) { switch (gdb_con->output_flag) {
case GDB_OUTPUT_NO: case GDB_OUTPUT_NO:
/* no need for keep-alive */ /* no need for keep-alive */
break; break;
case GDB_OUTPUT_NOTIF:
/* send asynchronous notification */
gdb_async_notif(connection);
break;
case GDB_OUTPUT_ALL: case GDB_OUTPUT_ALL:
/* send an empty O packet */ /* send an empty O packet */
gdb_output_con(connection, ""); gdb_output_con(connection, "");

View File

@ -15,22 +15,15 @@
#include "ipdbg.h" #include "ipdbg.h"
#define IPDBG_BUFFER_SIZE 16384 #define IPDBG_BUFFER_SIZE 16384
#define IPDBG_MIN_NUM_OF_OPTIONS 2 #define IPDBG_MIN_NUM_OF_CREATE_OPTIONS 3
#define IPDBG_MAX_NUM_OF_OPTIONS 14 #define IPDBG_MAX_NUM_OF_CREATE_OPTIONS 10
#define IPDBG_NUM_OF_START_OPTIONS 4
#define IPDBG_NUM_OF_STOP_OPTIONS 2
#define IPDBG_NUM_OF_QUEUE_OPTIONS 2
#define IPDBG_MIN_DR_LENGTH 11 #define IPDBG_MIN_DR_LENGTH 11
#define IPDBG_MAX_DR_LENGTH 13 #define IPDBG_MAX_DR_LENGTH 13
#define IPDBG_TCP_PORT_STR_MAX_LENGTH 6 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
#define IPDBG_SCRATCH_MEMORY_SIZE 1024 #define IPDBG_SCRATCH_MEMORY_SIZE 1024
#define IPDBG_EMPTY_DOWN_TRANSFERS 1024
#define IPDBG_CONSECUTIVE_UP_TRANSFERS 1024
#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS
#error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS"
#endif
#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS
#error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS"
#endif
/* private connection data for IPDBG */ /* private connection data for IPDBG */
struct ipdbg_fifo { struct ipdbg_fifo {
@ -75,6 +68,8 @@ struct ipdbg_hub {
uint32_t xoff_mask; uint32_t xoff_mask;
uint32_t tool_mask; uint32_t tool_mask;
uint32_t last_dn_tool; uint32_t last_dn_tool;
char *name;
size_t using_queue_size;
struct ipdbg_hub *next; struct ipdbg_hub *next;
struct jtag_tap *tap; struct jtag_tap *tap;
struct connection **connections; struct connection **connections;
@ -247,73 +242,9 @@ static void ipdbg_add_hub(struct ipdbg_hub *hub)
for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next)
; ;
ihub->next = hub; ihub->next = hub;
} else } else {
ipdbg_first_hub = hub; ipdbg_first_hub = hub;
} }
static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
struct ipdbg_virtual_ir_info *virtual_ir, struct ipdbg_hub **hub)
{
*hub = NULL;
struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
if (!new_hub)
goto mem_err_hub;
const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8);
new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *));
if (virtual_ir)
new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
!new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
!new_hub->connections)
goto mem_err2;
if (virtual_ir)
buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value);
new_hub->tap = tap;
new_hub->user_instruction = user_instruction;
new_hub->data_register_length = data_register_length;
new_hub->valid_mask = BIT(data_register_length - 1);
new_hub->xoff_mask = BIT(data_register_length - 2);
new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
new_hub->last_dn_tool = new_hub->tool_mask;
new_hub->virtual_ir = virtual_ir;
*hub = new_hub;
return ERROR_OK;
mem_err2:
free(new_hub->scratch_memory.vir_out_val);
free(new_hub->connections);
free(new_hub->scratch_memory.fields);
free(new_hub->scratch_memory.dr_in_vals);
free(new_hub->scratch_memory.dr_out_vals);
free(new_hub);
mem_err_hub:
free(virtual_ir);
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
static void ipdbg_free_hub(struct ipdbg_hub *hub)
{
if (!hub)
return;
free(hub->connections);
free(hub->virtual_ir);
free(hub->scratch_memory.dr_out_vals);
free(hub->scratch_memory.dr_in_vals);
free(hub->scratch_memory.fields);
free(hub->scratch_memory.vir_out_val);
free(hub);
} }
static int ipdbg_remove_hub(struct ipdbg_hub *hub) static int ipdbg_remove_hub(struct ipdbg_hub *hub)
@ -335,6 +266,58 @@ static int ipdbg_remove_hub(struct ipdbg_hub *hub)
return ERROR_FAIL; return ERROR_FAIL;
} }
static void ipdbg_free_hub(struct ipdbg_hub *hub)
{
if (!hub)
return;
free(hub->connections);
free(hub->virtual_ir);
free(hub->name);
free(hub->scratch_memory.dr_out_vals);
free(hub->scratch_memory.dr_in_vals);
free(hub->scratch_memory.fields);
free(hub->scratch_memory.vir_out_val);
free(hub);
}
static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir,
const char *name)
{
struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
if (!new_hub) {
LOG_ERROR("Out of memory");
return NULL;
}
new_hub->name = strdup(name);
if (!new_hub->name) {
free(new_hub);
LOG_ERROR("Out of memory");
return NULL;
}
const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8);
uint32_t max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
new_hub->connections = calloc(max_tools, sizeof(struct connection *));
if (virtual_ir)
new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
!new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
!new_hub->connections) {
ipdbg_free_hub(new_hub);
LOG_ERROR("Out of memory");
return NULL;
}
return new_hub;
}
static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value) static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value)
{ {
fields->check_mask = NULL; fields->check_mask = NULL;
@ -470,7 +453,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub)
const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size); memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size);
for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { for (size_t i = 0; i < hub->using_queue_size; ++i) {
ipdbg_init_scan_field(hub->scratch_memory.fields + i, ipdbg_init_scan_field(hub->scratch_memory.fields + i,
hub->scratch_memory.dr_in_vals + i * dreg_buffer_size, hub->scratch_memory.dr_in_vals + i * dreg_buffer_size,
hub->data_register_length, hub->data_register_length,
@ -482,7 +465,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub)
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
uint32_t up_data; uint32_t up_data;
for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { for (size_t i = 0; i < hub->using_queue_size; ++i) {
up_data = buf_get_u32(hub->scratch_memory.dr_in_vals + up_data = buf_get_u32(hub->scratch_memory.dr_in_vals +
i * dreg_buffer_size, 0, i * dreg_buffer_size, 0,
hub->data_register_length); hub->data_register_length);
@ -531,8 +514,8 @@ static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub *hub,
return ERROR_FAIL; return ERROR_FAIL;
const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
size_t num_tx = (connection->dn_fifo.count < IPDBG_CONSECUTIVE_UP_TRANSFERS) ? size_t num_tx = (connection->dn_fifo.count < hub->using_queue_size) ?
connection->dn_fifo.count : IPDBG_CONSECUTIVE_UP_TRANSFERS; connection->dn_fifo.count : hub->using_queue_size;
for (size_t i = 0; i < num_tx; ++i) { for (size_t i = 0; i < num_tx; ++i) {
uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) | uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) |
@ -760,62 +743,18 @@ static const struct service_driver ipdbg_service_driver = {
.keep_client_alive_handler = NULL, .keep_client_alive_handler = NULL,
}; };
static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction, static struct ipdbg_hub *ipdbg_get_hub_by_name(const char *name)
uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
{ {
LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool); struct ipdbg_hub *hub = NULL;
for (hub = ipdbg_first_hub; hub; hub = hub->next) {
struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir); if (strcmp(hub->name, name) == 0)
if (hub) { break;
free(virtual_ir);
if (hub->data_register_length != data_register_length) {
LOG_DEBUG("hub must have the same data_register_length for all tools");
return ERROR_FAIL;
}
} else {
int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
if (retval != ERROR_OK)
return retval;
} }
return hub;
};
struct ipdbg_service *service = NULL; static int ipdbg_stop_service(struct ipdbg_service *service)
int retval = ipdbg_create_service(hub, tool, &service, port);
if (retval != ERROR_OK || !service) {
if (hub->active_services == 0 && hub->active_connections == 0)
ipdbg_free_hub(hub);
return ERROR_FAIL;
}
char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
if (retval == ERROR_OK) {
ipdbg_add_service(service);
if (hub->active_services == 0 && hub->active_connections == 0)
ipdbg_add_hub(hub);
hub->active_services++;
} else {
if (hub->active_services == 0 && hub->active_connections == 0)
ipdbg_free_hub(hub);
free(service);
}
return retval;
}
static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction,
struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
{ {
struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
free(virtual_ir);
if (!hub)
return ERROR_FAIL;
struct ipdbg_service *service = ipdbg_find_service(hub, tool);
if (!service)
return ERROR_FAIL;
int retval = ipdbg_remove_service(service); int retval = ipdbg_remove_service(service);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("BUG: ipdbg_remove_service failed"); LOG_ERROR("BUG: ipdbg_remove_service failed");
@ -831,41 +770,271 @@ static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction,
LOG_ERROR("BUG: remove_service failed"); LOG_ERROR("BUG: remove_service failed");
return retval; return retval;
} }
hub->active_services--;
if (hub->active_connections == 0 && hub->active_services == 0) {
retval = ipdbg_remove_hub(hub);
if (retval != ERROR_OK) {
LOG_ERROR("BUG: ipdbg_remove_hub failed");
return retval;
}
ipdbg_free_hub(hub);
}
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(handle_ipdbg_command) int ipdbg_server_free(void)
{ {
struct jtag_tap *tap = NULL; int retval = ERROR_OK;
for (struct ipdbg_hub *hub = ipdbg_first_hub; hub;) {
for (uint8_t tool = 0; tool < hub->max_tools; ++tool) {
struct ipdbg_service *service = ipdbg_find_service(hub, tool);
if (service) {
int new_retval = ipdbg_stop_service(service);
if (new_retval != ERROR_OK)
retval = new_retval;
hub->active_services--;
}
}
struct ipdbg_hub *next_hub = hub->next;
int new_retval = ipdbg_remove_hub(hub);
if (new_retval != ERROR_OK)
retval = new_retval;
ipdbg_free_hub(hub);
hub = next_hub;
}
return retval;
}
static int ipdbg_start(struct ipdbg_hub *hub, uint16_t port, uint8_t tool)
{
LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool);
struct ipdbg_service *service = NULL;
int retval = ipdbg_create_service(hub, tool, &service, port);
if (retval != ERROR_OK || !service) {
if (hub->active_services == 0 && hub->active_connections == 0)
ipdbg_free_hub(hub);
return ERROR_FAIL;
}
char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
if (retval != ERROR_OK) {
free(service);
return retval;
}
ipdbg_add_service(service);
hub->active_services++;
return ERROR_OK;
}
COMMAND_HANDLER(handle_ipdbg_start_command)
{
struct ipdbg_hub *hub = CMD_DATA;
uint16_t port = 4242; uint16_t port = 4242;
uint8_t tool = 1; uint8_t tool = 1;
if (CMD_ARGC > IPDBG_NUM_OF_START_OPTIONS)
return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned int i = 0; i < CMD_ARGC; ++i) {
if (strcmp(CMD_ARGV[i], "-port") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
} else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
} else {
command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
return ERROR_FAIL;
}
}
return ipdbg_start(hub, port, tool);
}
static int ipdbg_stop(struct ipdbg_hub *hub, uint8_t tool)
{
struct ipdbg_service *service = ipdbg_find_service(hub, tool);
if (!service) {
LOG_ERROR("No service for hub '%s'/tool %d found", hub->name, tool);
return ERROR_FAIL;
}
int retval = ipdbg_stop_service(service);
hub->active_services--;
LOG_INFO("stopped ipdbg service for tool %d", tool);
return retval;
}
COMMAND_HANDLER(handle_ipdbg_stop_command)
{
struct ipdbg_hub *hub = CMD_DATA;
uint8_t tool = 1;
if (CMD_ARGC > IPDBG_NUM_OF_STOP_OPTIONS)
return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned int i = 0; i < CMD_ARGC; ++i) {
if (strcmp(CMD_ARGV[i], "-tool") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
} else {
command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
return ERROR_FAIL;
}
}
return ipdbg_stop(hub, tool);
}
static const struct command_registration ipdbg_hostserver_subcommand_handlers[] = {
{
.name = "start",
.mode = COMMAND_EXEC,
.handler = handle_ipdbg_start_command,
.help = "Starts a IPDBG Host server.",
.usage = "-tool number -port port"
}, {
.name = "stop",
.mode = COMMAND_EXEC,
.handler = handle_ipdbg_stop_command,
.help = "Stops a IPDBG Host server.",
.usage = "-tool number"
},
COMMAND_REGISTRATION_DONE
};
static COMMAND_HELPER(ipdbg_config_queuing, struct ipdbg_hub *hub, unsigned int size)
{
if (!hub)
return ERROR_FAIL;
if (hub->active_connections) {
command_print(CMD, "Configuration change not allowed when hub has active connections");
return ERROR_FAIL;
}
if (size == 0 || size > IPDBG_SCRATCH_MEMORY_SIZE) {
command_print(CMD, "queuing size out of range! Must be 0 < size <= %d", IPDBG_SCRATCH_MEMORY_SIZE);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
hub->using_queue_size = size;
return ERROR_OK;
}
COMMAND_HANDLER(handle_ipdbg_cfg_queuing_command)
{
struct ipdbg_hub *hub = CMD_DATA;
unsigned int size;
if (CMD_ARGC != IPDBG_NUM_OF_QUEUE_OPTIONS)
return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned int i = 0; i < CMD_ARGC; ++i) {
if (strcmp(CMD_ARGV[i], "-size") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(uint, i, size, "size");
} else {
command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
return ERROR_FAIL;
}
}
return CALL_COMMAND_HANDLER(ipdbg_config_queuing, hub, size);
}
static const struct command_registration ipdbg_hub_subcommand_handlers[] = {
{
.name = "ipdbg",
.mode = COMMAND_EXEC,
.help = "IPDBG Hub commands.",
.usage = "",
.chain = ipdbg_hostserver_subcommand_handlers
},
{
.name = "queuing",
.handler = handle_ipdbg_cfg_queuing_command,
.mode = COMMAND_ANY,
.help = "configures queuing between IPDBG Host and Hub.",
.usage = "-size size",
},
COMMAND_REGISTRATION_DONE
};
static int ipdbg_register_hub_command(struct ipdbg_hub *hub, struct command_invocation *cmd)
{
Jim_Interp *interp = CMD_CTX->interp;
/* does this command exist? */
Jim_Cmd *jcmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, hub->name, -1), JIM_NONE);
if (jcmd) {
LOG_ERROR("cannot create Hub because a command with name '%s' already exists", hub->name);
return ERROR_FAIL;
}
const struct command_registration obj_commands[] = {
{
.name = hub->name,
.mode = COMMAND_EXEC,
.help = "IPDBG Hub command group.",
.usage = "",
.chain = ipdbg_hub_subcommand_handlers
},
COMMAND_REGISTRATION_DONE
};
return register_commands_with_data(CMD_CTX, NULL, obj_commands, hub);
}
static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
struct ipdbg_virtual_ir_info *virtual_ir, const char *name, struct command_invocation *cmd)
{
struct ipdbg_hub *new_hub = ipdbg_allocate_hub(data_register_length, virtual_ir, name);
if (!new_hub)
return ERROR_FAIL;
if (virtual_ir)
buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value);
new_hub->tap = tap;
new_hub->user_instruction = user_instruction;
new_hub->data_register_length = data_register_length;
new_hub->valid_mask = BIT(data_register_length - 1);
new_hub->xoff_mask = BIT(data_register_length - 2);
new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
new_hub->last_dn_tool = new_hub->tool_mask;
new_hub->virtual_ir = virtual_ir;
new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
new_hub->using_queue_size = IPDBG_SCRATCH_MEMORY_SIZE;
int retval = ipdbg_register_hub_command(new_hub, cmd);
if (retval != ERROR_OK) {
LOG_ERROR("Creating hub failed");
ipdbg_free_hub(new_hub);
return ERROR_FAIL;
}
ipdbg_add_hub(new_hub);
return ERROR_OK;
}
COMMAND_HANDLER(handle_ipdbg_create_hub_command)
{
struct jtag_tap *tap = NULL;
uint32_t user_instruction = 0x00; uint32_t user_instruction = 0x00;
uint8_t data_register_length = IPDBG_MAX_DR_LENGTH; uint8_t data_register_length = IPDBG_MAX_DR_LENGTH;
bool start = true;
bool hub_configured = false;
bool has_virtual_ir = false; bool has_virtual_ir = false;
uint32_t virtual_ir_instruction = 0x00e; uint32_t virtual_ir_instruction = 0x00e;
uint32_t virtual_ir_length = 5; uint32_t virtual_ir_length = 5;
uint32_t virtual_ir_value = 0x11; uint32_t virtual_ir_value = 0x11;
struct ipdbg_virtual_ir_info *virtual_ir = NULL; struct ipdbg_virtual_ir_info *virtual_ir = NULL;
int user_num = 1; int user_num = 1;
bool hub_configured = false;
if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS)) if (CMD_ARGC < IPDBG_MIN_NUM_OF_CREATE_OPTIONS || CMD_ARGC > IPDBG_MAX_NUM_OF_CREATE_OPTIONS)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned int i = 0; i < CMD_ARGC; ++i) { const char *hub_name = CMD_ARGV[0];
for (unsigned int i = 1; i < CMD_ARGC; ++i) {
if (strcmp(CMD_ARGV[i], "-tap") == 0) { if (strcmp(CMD_ARGV[i], "-tap") == 0) {
if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') { if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') {
command_print(CMD, "no TAP given"); command_print(CMD, "no TAP name given");
return ERROR_FAIL; return ERROR_FAIL;
} }
tap = jtag_tap_by_string(CMD_ARGV[i + 1]); tap = jtag_tap_by_string(CMD_ARGV[i + 1]);
@ -874,7 +1043,7 @@ COMMAND_HANDLER(handle_ipdbg_command)
return ERROR_FAIL; return ERROR_FAIL;
} }
++i; ++i;
} else if (strcmp(CMD_ARGV[i], "-hub") == 0) { } else if (strcmp(CMD_ARGV[i], "-ir") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub"); COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub");
hub_configured = true; hub_configured = true;
COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length); COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length);
@ -917,20 +1086,11 @@ COMMAND_HANDLER(handle_ipdbg_command)
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length); COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction); COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction);
has_virtual_ir = true; has_virtual_ir = true;
} else if (strcmp(CMD_ARGV[i], "-port") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
} else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
} else if (strcmp(CMD_ARGV[i], "-stop") == 0) {
start = false;
} else if (strcmp(CMD_ARGV[i], "-start") == 0) {
start = true;
} else { } else {
command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]); command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
if (!tap) { if (!tap) {
command_print(CMD, "no valid tap selected"); command_print(CMD, "no valid tap selected");
return ERROR_FAIL; return ERROR_FAIL;
@ -941,8 +1101,8 @@ COMMAND_HANDLER(handle_ipdbg_command)
return ERROR_FAIL; return ERROR_FAIL;
} }
if (tool >= ipdbg_max_tools_from_data_register_length(data_register_length)) { if (ipdbg_get_hub_by_name(hub_name)) {
command_print(CMD, "Tool: %d is invalid", tool); LOG_ERROR("IPDBG hub with name '%s' already exists", hub_name);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -957,20 +1117,38 @@ COMMAND_HANDLER(handle_ipdbg_command)
virtual_ir->value = virtual_ir_value; virtual_ir->value = virtual_ir_value;
} }
if (start) if (ipdbg_find_hub(tap, user_instruction, virtual_ir)) {
return ipdbg_start(port, tap, user_instruction, data_register_length, virtual_ir, tool); LOG_ERROR("IPDBG hub for given TAP and user-instruction already exists");
else free(virtual_ir);
return ipdbg_stop(tap, user_instruction, virtual_ir, tool); return ERROR_FAIL;
}
int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd);
if (retval != ERROR_OK)
free(virtual_ir);
return retval;
} }
static const struct command_registration ipdbg_config_command_handlers[] = {
{
.name = "create-hub",
.mode = COMMAND_ANY,
.handler = handle_ipdbg_create_hub_command,
.help = "create a IPDBG Hub",
.usage = "name.ipdbghub (-tap device.tap -ir ir_value [dr_length] |"
" -pld name.pld [user]) [-vir [vir_value [length [instr_code]]]]",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration ipdbg_command_handlers[] = { static const struct command_registration ipdbg_command_handlers[] = {
{ {
.name = "ipdbg", .name = "ipdbg",
.handler = handle_ipdbg_command, .mode = COMMAND_ANY,
.mode = COMMAND_EXEC, .help = "IPDBG Hub/Host commands.",
.help = "Starts or stops an IPDBG JTAG-Host server.", .usage = "",
.usage = "[-start|-stop] -tap device.tap -hub ir_value [dr_length]" .chain = ipdbg_config_command_handlers,
" [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -7,5 +7,6 @@
#include <helper/command.h> #include <helper/command.h>
int ipdbg_register_commands(struct command_context *cmd_ctx); int ipdbg_register_commands(struct command_context *cmd_ctx);
int ipdbg_server_free(void);
#endif /* OPENOCD_IPDBG_IPDBG_H */ #endif /* OPENOCD_IPDBG_IPDBG_H */

View File

@ -23,6 +23,7 @@
#include "openocd.h" #include "openocd.h"
#include "tcl_server.h" #include "tcl_server.h"
#include "telnet_server.h" #include "telnet_server.h"
#include "ipdbg.h"
#include <signal.h> #include <signal.h>
@ -714,6 +715,7 @@ void server_free(void)
tcl_service_free(); tcl_service_free();
telnet_service_free(); telnet_service_free();
jsp_service_free(); jsp_service_free();
ipdbg_server_free();
free(bindto_name); free(bindto_name);
} }

View File

@ -93,6 +93,7 @@ static int aarch64_restore_system_control_reg(struct target *target)
case ARM_MODE_HYP: case ARM_MODE_HYP:
case ARM_MODE_UND: case ARM_MODE_UND:
case ARM_MODE_SYS: case ARM_MODE_SYS:
case ARM_MODE_MON:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break; break;
@ -172,6 +173,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
case ARM_MODE_HYP: case ARM_MODE_HYP:
case ARM_MODE_UND: case ARM_MODE_UND:
case ARM_MODE_SYS: case ARM_MODE_SYS:
case ARM_MODE_MON:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break; break;
@ -1043,6 +1045,7 @@ static int aarch64_post_debug_entry(struct target *target)
case ARM_MODE_HYP: case ARM_MODE_HYP:
case ARM_MODE_UND: case ARM_MODE_UND:
case ARM_MODE_SYS: case ARM_MODE_SYS:
case ARM_MODE_MON:
instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0); instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0);
break; break;
@ -2891,13 +2894,8 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info *
* options, JIM_OK if it correctly parsed the topmost option * options, JIM_OK if it correctly parsed the topmost option
* and JIM_ERR if an error occurred during parameter evaluation. * and JIM_ERR if an error occurred during parameter evaluation.
* For JIM_CONTINUE, we check our own params. * For JIM_CONTINUE, we check our own params.
*
* adiv5_jim_configure() assumes 'private_config' to point to
* 'struct adiv5_private_config'. Override 'private_config'!
*/ */
target->private_config = &pc->adiv5_config; e = adiv5_jim_configure_ext(target, goi, &pc->adiv5_config, ADI_CONFIGURE_DAP_COMPULSORY);
e = adiv5_jim_configure(target, goi);
target->private_config = pc;
if (e != JIM_CONTINUE) if (e != JIM_CONTINUE)
return e; return e;

View File

@ -84,16 +84,8 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap)
static int swd_run_inner(struct adiv5_dap *dap) static int swd_run_inner(struct adiv5_dap *dap)
{ {
const struct swd_driver *swd = adiv5_dap_swd_driver(dap); const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
int retval;
retval = swd->run(); return swd->run();
if (retval != ERROR_OK) {
/* fault response */
dap->do_reconnect = true;
}
return retval;
} }
static inline int check_sync(struct adiv5_dap *dap) static inline int check_sync(struct adiv5_dap *dap)
@ -105,14 +97,13 @@ static inline int check_sync(struct adiv5_dap *dap)
static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg) static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
{ {
/* Only register address 0 (ADIv6 only) and 4 are banked. */ /* Only register address 0 (ADIv6 only) and 4 are banked. */
if ((reg & 0xf) > 4) if (is_adiv6(dap) ? (reg & 0xf) > 4 : (reg & 0xf) != 4)
return ERROR_OK; return ERROR_OK;
uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK; uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK;
/* DP register 0 is not mapped according to ADIv5 /* ADIv6 ensures DPBANKSEL = 0 after line reset */
* whereas ADIv6 ensures DPBANKSEL = 0 after line reset */ if ((dap->select_valid || (is_adiv6(dap) && dap->select_dpbanksel_valid))
if ((dap->select_valid || ((reg & 0xf) == 0 && dap->select_dpbanksel_valid))
&& (sel == (dap->select & DP_SELECT_DPBANK))) && (sel == (dap->select & DP_SELECT_DPBANK)))
return ERROR_OK; return ERROR_OK;
@ -146,7 +137,7 @@ static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg,
static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
uint32_t data) uint32_t data)
{ {
int retval; int retval = ERROR_OK;
const struct swd_driver *swd = adiv5_dap_swd_driver(dap); const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd); assert(swd);
@ -167,7 +158,11 @@ static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
if (reg == DP_SELECT1) if (reg == DP_SELECT1)
dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull); dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull);
retval = swd_queue_dp_bankselect(dap, reg); /* DP_ABORT write is not banked.
* Prevent writing DP_SELECT before as it would fail on locked up DP */
if (reg != DP_ABORT)
retval = swd_queue_dp_bankselect(dap, reg);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
swd->write_reg(swd_cmd(false, false, reg), data, 0); swd->write_reg(swd_cmd(false, false, reg), data, 0);
@ -285,15 +280,15 @@ static int swd_multidrop_select(struct adiv5_dap *dap)
swd_multidrop_selected_dap = NULL; swd_multidrop_selected_dap = NULL;
if (retry > 3) { if (retry > 3) {
LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap)); LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap));
dap->do_reconnect = true;
return retval; return retval;
} }
LOG_DEBUG("Failed to select multidrop %s, retrying...", LOG_DEBUG("Failed to select multidrop %s, retrying...",
adiv5_dap_name(dap)); adiv5_dap_name(dap));
/* we going to retry localy, do not ask for full reconnect */
dap->do_reconnect = false;
} }
dap->do_reconnect = false;
return retval; return retval;
} }
@ -632,7 +627,13 @@ static int swd_run(struct adiv5_dap *dap)
swd_finish_read(dap); swd_finish_read(dap);
return swd_run_inner(dap); retval = swd_run_inner(dap);
if (retval != ERROR_OK) {
/* fault response */
dap->do_reconnect = true;
}
return retval;
} }
/** Put the SWJ-DP back to JTAG mode */ /** Put the SWJ-DP back to JTAG mode */

View File

@ -2424,23 +2424,26 @@ err_no_param:
return JIM_ERR; return JIM_ERR;
} }
int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi) int adiv5_jim_configure_ext(struct target *target, struct jim_getopt_info *goi,
struct adiv5_private_config *pc, enum adiv5_configure_dap_optional optional)
{ {
struct adiv5_private_config *pc;
int e; int e;
pc = (struct adiv5_private_config *)target->private_config;
if (!pc) { if (!pc) {
pc = calloc(1, sizeof(struct adiv5_private_config)); pc = (struct adiv5_private_config *)target->private_config;
if (!pc) { if (!pc) {
LOG_ERROR("Out of memory"); pc = calloc(1, sizeof(struct adiv5_private_config));
return JIM_ERR; if (!pc) {
LOG_ERROR("Out of memory");
return JIM_ERR;
}
pc->ap_num = DP_APSEL_INVALID;
target->private_config = pc;
} }
pc->ap_num = DP_APSEL_INVALID;
target->private_config = pc;
} }
target->has_dap = true; if (optional == ADI_CONFIGURE_DAP_COMPULSORY)
target->has_dap = true;
e = adiv5_jim_spot_configure(goi, &pc->dap, &pc->ap_num, NULL); e = adiv5_jim_spot_configure(goi, &pc->dap, &pc->ap_num, NULL);
if (e != JIM_OK) if (e != JIM_OK)
@ -2455,11 +2458,17 @@ int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi)
} }
target->tap = pc->dap->tap; target->tap = pc->dap->tap;
target->dap_configured = true; target->dap_configured = true;
target->has_dap = true;
} }
return JIM_OK; return JIM_OK;
} }
int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi)
{
return adiv5_jim_configure_ext(target, goi, NULL, ADI_CONFIGURE_DAP_COMPULSORY);
}
int adiv5_verify_config(struct adiv5_private_config *pc) int adiv5_verify_config(struct adiv5_private_config *pc)
{ {
if (!pc) if (!pc)

View File

@ -788,6 +788,15 @@ struct adiv5_private_config {
}; };
extern int adiv5_verify_config(struct adiv5_private_config *pc); extern int adiv5_verify_config(struct adiv5_private_config *pc);
enum adiv5_configure_dap_optional {
ADI_CONFIGURE_DAP_COMPULSORY = false,
ADI_CONFIGURE_DAP_OPTIONAL = true
};
extern int adiv5_jim_configure_ext(struct target *target, struct jim_getopt_info *goi,
struct adiv5_private_config *pc,
enum adiv5_configure_dap_optional optional);
extern int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi); extern int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi);
struct adiv5_mem_ap_spot { struct adiv5_mem_ap_spot {

View File

@ -194,11 +194,11 @@ static const char *mem_ap_get_gdb_arch(const struct target *target)
* reg[24]: 32 bits, fps * reg[24]: 32 bits, fps
* reg[25]: 32 bits, cpsr * reg[25]: 32 bits, cpsr
* *
* Set 'exist' only to reg[0..15], so initial response to GDB is correct * GDB requires only reg[0..15]
*/ */
#define NUM_REGS 26 #define NUM_REGS 26
#define NUM_GDB_REGS 16
#define MAX_REG_SIZE 96 #define MAX_REG_SIZE 96
#define REG_EXIST(n) ((n) < 16)
#define REG_SIZE(n) ((((n) >= 16) && ((n) < 24)) ? 96 : 32) #define REG_SIZE(n) ((((n) >= 16) && ((n) < 24)) ? 96 : 32)
struct mem_ap_alloc_reg_list { struct mem_ap_alloc_reg_list {
@ -218,14 +218,14 @@ static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[
} }
*reg_list = mem_ap_alloc->reg_list; *reg_list = mem_ap_alloc->reg_list;
*reg_list_size = NUM_REGS; *reg_list_size = (reg_class == REG_CLASS_ALL) ? NUM_REGS : NUM_GDB_REGS;
struct reg *regs = mem_ap_alloc->regs; struct reg *regs = mem_ap_alloc->regs;
for (int i = 0; i < NUM_REGS; i++) { for (int i = 0; i < NUM_REGS; i++) {
regs[i].number = i; regs[i].number = i;
regs[i].value = mem_ap_alloc->regs_value; regs[i].value = mem_ap_alloc->regs_value;
regs[i].size = REG_SIZE(i); regs[i].size = REG_SIZE(i);
regs[i].exist = REG_EXIST(i); regs[i].exist = true;
regs[i].type = &mem_ap_reg_arch_type; regs[i].type = &mem_ap_reg_arch_type;
(*reg_list)[i] = &regs[i]; (*reg_list)[i] = &regs[i];
} }

View File

@ -161,6 +161,67 @@ static const struct {
#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
#define zero 0
#define AT 1
#define v0 2
#define v1 3
#define a0 4
#define a1 5
#define a2 6
#define a3 7
#define t0 8
#define t1 9
#define t2 10
#define t3 11
#define t4 12
#define t5 13
#define t6 14
#define t7 15
#define ta0 12 /* alias for $t4 */
#define ta1 13 /* alias for $t5 */
#define ta2 14 /* alias for $t6 */
#define ta3 15 /* alias for $t7 */
#define s0 16
#define s1 17
#define s2 18
#define s3 19
#define s4 20
#define s5 21
#define s6 22
#define s7 23
#define s8 30 /* == fp */
#define t8 24
#define t9 25
#define k0 26
#define k1 27
#define gp 28
#define sp 29
#define fp 30
#define ra 31
static const struct {
const char *name;
} mips32_dsp_regs[MIPS32NUMDSPREGS] = {
{ "hi0"},
{ "hi1"},
{ "hi2"},
{ "hi3"},
{ "lo0"},
{ "lo1"},
{ "lo2"},
{ "lo3"},
{ "control"},
};
static int mips32_get_core_reg(struct reg *reg) static int mips32_get_core_reg(struct reg *reg)
{ {
int retval; int retval;
@ -201,6 +262,61 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_OK; return ERROR_OK;
} }
/**
* mips32_set_all_fpr_width - Set the width of all floating-point registers
* @param[in] mips32: MIPS32 common structure
* @param[in] fp64: Flag indicating whether to set the width to 64 bits (double precision)
*
* @brief Sets the width of all floating-point registers based on the specified flag.
*/
static void mips32_set_all_fpr_width(struct mips32_common *mips32, bool fp64)
{
struct reg_cache *cache = mips32->core_cache;
struct reg *reg_list = cache->reg_list;
int i;
for (i = MIPS32_REGLIST_FP_INDEX; i < (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT); i++) {
reg_list[i].size = fp64 ? 64 : 32;
reg_list[i].reg_data_type->type = fp64 ? REG_TYPE_IEEE_DOUBLE : REG_TYPE_IEEE_SINGLE;
}
}
/**
* mips32_detect_fpr_mode_change - Detect changes in floating-point register mode
* @param[in] mips32: MIPS32 common structure
* @param[in] cp0_status: Value of the CP0 status register
*
* @brief Detects changes in the floating-point register mode based on the CP0 status register.
* If changes are detected, it updates the internal state
* and logs a warning message indicating the mode change.
*/
static void mips32_detect_fpr_mode_change(struct mips32_common *mips32, uint32_t cp0_status)
{
if (!mips32->fp_imp)
return;
/* CP0.Status.FR indicates the working mode of floating-point register.
* When FP = 0, fpr can contain any 32bit data type,
* 64bit data types are stored in even-odd register pairs.
* When FP = 1, fpr can contain any data types.*/
bool fpu_in_64bit = ((cp0_status & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0);
/* CP0.Status.CU1 indicated whether CoProcessor1(which is FPU) is present. */
bool fp_enabled = ((cp0_status & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0);
if (mips32->fpu_in_64bit != fpu_in_64bit) {
mips32->fpu_in_64bit = fpu_in_64bit;
mips32_set_all_fpr_width(mips32, fpu_in_64bit);
LOG_WARNING("** FP mode changed to %sbit, you must reconnect GDB **", fpu_in_64bit ? "64" : "32");
}
if (mips32->fpu_enabled != fp_enabled) {
mips32->fpu_enabled = fp_enabled;
const char *s = fp_enabled ? "enabled" : "disabled";
LOG_WARNING("** FP is %s, register update %s **", s, s);
}
}
static int mips32_read_core_reg(struct target *target, unsigned int num) static int mips32_read_core_reg(struct target *target, unsigned int num)
{ {
unsigned int cnum; unsigned int cnum;
@ -217,6 +333,8 @@ static int mips32_read_core_reg(struct target *target, unsigned int num)
cnum = num - MIPS32_REGLIST_C0_INDEX; cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = mips32->core_regs.cp0[cnum]; reg_value = mips32->core_regs.cp0[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
if (cnum == MIPS32_REG_C0_STATUS_INDEX)
mips32_detect_fpr_mode_change(mips32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) { } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */ /* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX; cnum = num - MIPS32_REGLIST_FPC_INDEX;
@ -258,6 +376,8 @@ static int mips32_write_core_reg(struct target *target, unsigned int num)
cnum = num - MIPS32_REGLIST_C0_INDEX; cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.cp0[cnum] = (uint32_t)reg_value; mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
if (cnum == MIPS32_REG_C0_STATUS_INDEX)
mips32_detect_fpr_mode_change(mips32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) { } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */ /* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX; cnum = num - MIPS32_REGLIST_FPC_INDEX;
@ -926,8 +1046,8 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta
mips32->fp_imp = MIPS32_FP_IMP_NONE; mips32->fp_imp = MIPS32_FP_IMP_NONE;
return ERROR_OK; return ERROR_OK;
} }
uint32_t status_value; uint32_t fir_value, status_value;
bool status_fr, status_cu1; bool fpu_in_64bit, fp_enabled;
retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
@ -935,20 +1055,34 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta
return retval; return retval;
} }
status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1; fpu_in_64bit = (status_value & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0;
status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1; fp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0;
if (status_cu1) { if (fp_enabled) {
/* TODO: read fpu(cp1) config register for current operating mode. retval = mips32_cp1_control_read(ejtag_info, &fir_value, 0);
* Now its set to 32 bits by default. */ if (retval != ERROR_OK) {
snprintf(buf, sizeof(buf), "yes"); LOG_ERROR("Failed to read cp1 FIR register");
fp_imp = MIPS32_FP_IMP_32; return retval;
}
if ((fir_value >> MIPS32_CP1_FIR_F64_SHIFT) & 0x1)
fp_imp++;
} else { } else {
/* This is the only condition that writes to buf */
snprintf(buf, sizeof(buf), "yes, disabled"); snprintf(buf, sizeof(buf), "yes, disabled");
fp_imp = MIPS32_FP_IMP_UNKNOWN; fp_imp = MIPS32_FP_IMP_UNKNOWN;
} }
mips32->fpu_in_64bit = status_fr; mips32->fpu_in_64bit = fpu_in_64bit;
mips32->fpu_enabled = status_cu1; mips32->fpu_enabled = fp_enabled;
mips32_set_all_fpr_width(mips32, fpu_in_64bit);
/* If fpu is not disabled, print out more information */
if (!buf[0])
snprintf(buf, sizeof(buf), "yes, %sbit (%s, working in %sbit)",
fp_imp == MIPS32_FP_IMP_64 ? "64" : "32",
fp_enabled ? "enabled" : "disabled",
fpu_in_64bit ? "64" : "32");
LOG_USER("FPU implemented: %s", buf); LOG_USER("FPU implemented: %s", buf);
mips32->fp_imp = fp_imp; mips32->fp_imp = fp_imp;
@ -1544,6 +1678,204 @@ COMMAND_HANDLER(mips32_handle_cp0_command)
return retval; return retval;
} }
/**
* mips32_dsp_enable - Enable access to DSP registers
* @param[in] ctx: Context information for the pracc queue
* @param[in] isa: Instruction Set Architecture identifier
*
* @brief Enables access to DSP registers by modifying the status register.
*
* This function adds instructions to the context queue for enabling
* access to DSP registers by modifying the status register.
*/
static void mips32_dsp_enable(struct pracc_queue_info *ctx, int isa)
{
/* Save Status Register */
/* move status to $9 (t1) 2*/
pracc_add(ctx, 0, MIPS32_MFC0(isa, 9, 12, 0));
/* Read it again in order to modify it */
/* move status to $0 (t0) 3*/
pracc_add(ctx, 0, MIPS32_MFC0(isa, 8, 12, 0));
/* Enable access to DSP registers by setting MX bit in status register */
/* $15 = MIPS32_PRACC_STACK 4/5/6*/
pracc_add(ctx, 0, MIPS32_LUI(isa, 15, UPPER16(MIPS32_DSP_ENABLE)));
pracc_add(ctx, 0, MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_DSP_ENABLE)));
pracc_add(ctx, 0, MIPS32_ISA_OR(8, 8, 15));
/* Enable DSP - update status registers 7*/
pracc_add(ctx, 0, MIPS32_MTC0(isa, 8, 12, 0));
}
/**
* mips32_dsp_restore - Restore DSP status registers to the previous setting
* @param[in] ctx: Context information pracc queue
* @param[in] isa: isa identifier
*
* @brief Restores the DSP status registers to their previous setting.
*
* This function adds instructions to the context queue for restoring the DSP
* status registers to their values before the operation.
*/
static void mips32_dsp_restore(struct pracc_queue_info *ctx, int isa)
{
pracc_add(ctx, 0, MIPS32_MTC0(isa, 9, 12, 0)); /* Restore status registers to previous setting */
pracc_add(ctx, 0, MIPS32_NOP); /* nop */
}
/**
* mips32_pracc_read_dsp_reg - Read a value from a MIPS32 DSP register
* @param[in] ejtag_info: EJTAG information structure
* @param[out] val: Pointer to store the read value
* @param[in] reg: Index of the DSP register to read
*
* @brief Reads the value from the specified MIPS32 DSP register using EJTAG access.
*
* This function initiates a sequence of instructions to read the value from the
* specified DSP register. It will enable dsp module if its not enabled
* and restoring the status registers after the read operation.
*
* @return ERROR_OK on success; error code on failure.
*/
static int mips32_pracc_read_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t reg)
{
int isa = 0;
struct pracc_queue_info ctx = {
.max_code = 48,
.ejtag_info = ejtag_info
};
uint32_t dsp_read_code[] = {
MIPS32_MFHI(isa, t0), /* mfhi t0 ($ac0) - OPCODE - 0x00004010 */
MIPS32_DSP_MFHI(t0, 1), /* mfhi t0,$ac1 - OPCODE - 0x00204010 */
MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */
MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/
MIPS32_MFLO(isa, t0), /* mflo t0 ($ac0) - OPCODE - 0x00004012 */
MIPS32_DSP_MFLO(t0, 1), /* mflo t0,$ac1 - OPCODE - 0x00204012 */
MIPS32_DSP_MFLO(t0, 2), /* mflo t0,$ac2 - OPCODE - 0x00404012 */
MIPS32_DSP_MFLO(t0, 3), /* mflo t0,$ac3 - OPCODE - 0x00604012 */
MIPS32_DSP_RDDSP(t0, 0x3F), /* rddsp t0, 0x3f (DSPCtl) - OPCODE - 0x7c3f44b8 */
};
/* Check status register to determine if dsp register access is enabled */
/* Get status register so it can be restored later */
ctx.pracc_list = NULL;
/* Init context queue */
pracc_queue_init(&ctx);
if (ctx.retval != ERROR_OK)
goto exit;
/* Enables DSP whether its already enabled or not */
mips32_dsp_enable(&ctx, isa);
/* move AC or Control to $8 (t0) 8*/
pracc_add(&ctx, 0, dsp_read_code[reg]);
/* Restore status registers to previous setting */
mips32_dsp_restore(&ctx, isa);
/* $15 = MIPS32_PRACC_BASE_ADDR 1*/
pracc_add(&ctx, 0, MIPS32_LUI(isa, 15, PRACC_UPPER_BASE_ADDR));
/* store $8 to pracc_out 10*/
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(isa, 8, PRACC_OUT_OFFSET, 15));
/* move COP0 DeSave to $15 11*/
pracc_add(&ctx, 0, MIPS32_MFC0(isa, 15, 31, 0));
/* restore upper 16 of $8 12*/
pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(ejtag_info->reg8)));
/* restore lower 16 of $8 13*/
pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(ejtag_info->reg8)));
/* restore upper 16 of $9 14*/
pracc_add(&ctx, 0, MIPS32_LUI(isa, 9, UPPER16(ejtag_info->reg9)));
pracc_add(&ctx, 0, MIPS32_SYNC(isa));
/* jump to start 18*/
pracc_add(&ctx, 0, MIPS32_B(isa, NEG16(ctx.code_count + 1)));
/* restore lower 16 of $9 15*/
pracc_add(&ctx, 0, MIPS32_ORI(isa, 9, 9, LOWER16(ejtag_info->reg9)));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
exit:
pracc_queue_free(&ctx);
return ctx.retval;
}
/**
* mips32_pracc_write_dsp_reg - Write a value to a MIPS32 DSP register
* @param[in] ejtag_info: EJTAG information structure
* @param[in] val: Value to be written to the register
* @param[in] reg: Index of the DSP register to write
*
* @brief Writes the specified value to the specified MIPS32 DSP register.
*
* This function initiates a sequence of instructions to write the given value to the
* specified DSP register.
*
* @return ERROR_OK on success; error code on failure.
*/
static int mips32_pracc_write_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t reg)
{
int isa = 0;
struct pracc_queue_info ctx = {
.max_code = 48,
.ejtag_info = ejtag_info
};
uint32_t dsp_write_code[] = {
MIPS32_MTHI(isa, t0), /* mthi t0 ($ac0) - OPCODE - 0x01000011 */
MIPS32_DSP_MTHI(t0, 1), /* mthi t0, $ac1 - OPCODE - 0x01000811 */
MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */
MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */
MIPS32_MTLO(isa, t0), /* mtlo t0 ($ac0) - OPCODE - 0x01000013 */
MIPS32_DSP_MTLO(t0, 1), /* mtlo t0, $ac1 - OPCODE - 0x01000813 */
MIPS32_DSP_MTLO(t0, 2), /* mtlo t0, $ac2 - OPCODE - 0x01001013 */
MIPS32_DSP_MTLO(t0, 3), /* mtlo t0, $ac3 - OPCODE - 0x01001813 */
MIPS32_DSP_WRDSP(t0, 0x1F), /* wrdsp t0, 0x1f (DSPCtl) - OPCODE - 0x7d00fcf8*/
};
/* Init context queue */
pracc_queue_init(&ctx);
if (ctx.retval != ERROR_OK)
goto exit;
/* Enables DSP whether its already enabled or not */
mips32_dsp_enable(&ctx, isa);
/* Load val to $8 (t0) */
pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(val)));
pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(val)));
/* move AC or Control to $8 (t0) */
pracc_add(&ctx, 0, dsp_write_code[reg]);
/* nop, delay in order to ensure write */
pracc_add(&ctx, 0, MIPS32_NOP);
/* Restore status registers to previous setting */
mips32_dsp_restore(&ctx, isa);
/* move COP0 DeSave to $15 */
pracc_add(&ctx, 0, MIPS32_MFC0(isa, 15, 31, 0));
/* restore $8 */
pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(ejtag_info->reg8)));
pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(ejtag_info->reg8)));
/* restore upper 16 of $9 */
pracc_add(&ctx, 0, MIPS32_LUI(isa, 9, UPPER16(ejtag_info->reg9)));
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(isa, NEG16(ctx.code_count + 1)));
/* restore lower 16 of $9 */
pracc_add(&ctx, 0, MIPS32_ORI(isa, 9, 9, LOWER16(ejtag_info->reg9)));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
exit:
pracc_queue_free(&ctx);
return ctx.retval;
}
/** /**
* mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command. * mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command.
* @param[in] cmd: Command invocation context. * @param[in] cmd: Command invocation context.
@ -1746,6 +2078,167 @@ COMMAND_HANDLER(mips32_handle_cpuinfo_command)
return ERROR_OK; return ERROR_OK;
} }
/**
* mips32_dsp_find_register_by_name - Find DSP register index by name
* @param[in] reg_name: Name of the DSP register to find
*
* @brief Searches for a DSP register by name and returns its index.
* If no match is found, it returns MIPS32NUMDSPREGS.
*
* @return Index of the found register or MIPS32NUMDSPREGS if not found.
*/
static int mips32_dsp_find_register_by_name(const char *reg_name)
{
if (reg_name)
for (int i = 0; i < MIPS32NUMDSPREGS; i++) {
if (strcmp(mips32_dsp_regs[i].name, reg_name) == 0)
return i;
}
return MIPS32NUMDSPREGS;
}
/**
* mips32_dsp_get_all_regs - Get values of all MIPS32 DSP registers
* @param[in] cmd: Command invocation context
* @param[in] ejtag_info: EJTAG information structure
*
* @brief This function iterates through all DSP registers, reads their values,
* and prints each register name along with its corresponding value.
*
* @return ERROR_OK on success; error code on failure.
*/
static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
{
uint32_t value;
for (int i = 0; i < MIPS32NUMDSPREGS; i++) {
int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i);
if (retval != ERROR_OK) {
command_print(CMD, "couldn't access reg %s", mips32_dsp_regs[i].name);
return retval;
}
command_print(CMD, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value);
}
return ERROR_OK;
}
/**
* mips32_dsp_get_register - Get the value of a MIPS32 DSP register
* @param[in] cmd: Command invocation context
* @param[in] ejtag_info: EJTAG information structure
*
* @brief Retrieves the value of a specified MIPS32 DSP register.
* If the register is found, it reads the register value and prints the result.
* If the register is not found, it prints an error message.
*
* @return ERROR_OK on success; error code on failure.
*/
static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
{
uint32_t value;
int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]);
if (index == MIPS32NUMDSPREGS) {
command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, index);
if (retval != ERROR_OK)
command_print(CMD, "ERROR: Could not access dsp register %s", CMD_ARGV[0]);
else
command_print(CMD, "0x%8.8x", value);
return retval;
}
/**
* mips32_dsp_set_register - Set the value of a MIPS32 DSP register
* @param[in] cmd: Command invocation context
* @param[in] ejtag_info: EJTAG information structure
*
* @brief Sets the value of a specified MIPS32 DSP register.
* If the register is found, it writes provided value to the register.
* If the register is not found or there is an error in writing the value,
* it prints an error message.
*
* @return ERROR_OK on success; error code on failure.
*/
static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
{
uint32_t value;
int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]);
if (index == MIPS32NUMDSPREGS) {
command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
int retval = mips32_pracc_write_dsp_reg(ejtag_info, value, index);
if (retval != ERROR_OK)
command_print(CMD, "Error: could not write to dsp register %s", CMD_ARGV[0]);
return retval;
}
/**
* mips32_handle_dsp_command - Handles mips dsp related command
* @param[in] cmd: Command invocation context
*
* @brief Reads or sets the content of each dsp register.
*
* @return ERROR_OK on success; error code on failure.
*/
COMMAND_HANDLER(mips32_handle_dsp_command)
{
int retval, tmp;
struct target *target = get_current_target(CMD_CTX);
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
retval = mips32_verify_pointer(CMD, mips32);
if (retval != ERROR_OK)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_OK;
}
/* Check for too many command args */
if (CMD_ARGC >= 3)
return ERROR_COMMAND_SYNTAX_ERROR;
/* Check if DSP access supported or not */
if (!mips32->dsp_imp) {
/* Issue Error Message */
command_print(CMD, "DSP not implemented by this processor");
return ERROR_OK;
}
switch (CMD_ARGC) {
case 0:
retval = mips32_dsp_get_all_regs(CMD, ejtag_info);
break;
case 1:
retval = mips32_dsp_get_register(CMD, ejtag_info);
break;
case 2:
tmp = *CMD_ARGV[0];
if (isdigit(tmp)) {
command_print(CMD, "Error: invalid dsp command format");
retval = ERROR_COMMAND_ARGUMENT_INVALID;
} else {
retval = mips32_dsp_set_register(CMD, ejtag_info);
}
break;
default:
command_print(CMD, "Error: invalid argument format, required 0-2, given %d", CMD_ARGC);
retval = ERROR_COMMAND_ARGUMENT_INVALID;
break;
}
return retval;
}
/** /**
* mips32_handle_ejtag_reg_command - Handler commands related to EJTAG * mips32_handle_ejtag_reg_command - Handler commands related to EJTAG
* @param[in] cmd: Command invocation context * @param[in] cmd: Command invocation context
@ -1847,6 +2340,14 @@ static const struct command_registration mips32_exec_command_handlers[] = {
.help = "display CPU information", .help = "display CPU information",
.usage = "", .usage = "",
}, },
{
.name = "dsp",
.handler = mips32_handle_dsp_command,
.mode = COMMAND_EXEC,
.help = "display or set DSP register; "
"with no arguments, displays all registers and their values",
.usage = "[[register_name] [value]]",
},
{ {
.name = "scan_delay", .name = "scan_delay",
.handler = mips32_handle_scan_delay_command, .handler = mips32_handle_scan_delay_command,

View File

@ -69,7 +69,7 @@
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
#define MIPS32_NUM_DSPREGS 9 #define MIPS32NUMDSPREGS 9
/* Bit Mask indicating CP0 register supported by this core */ /* Bit Mask indicating CP0 register supported by this core */
#define MIPS_CP0_MK4 0x0001 #define MIPS_CP0_MK4 0x0001
@ -459,10 +459,13 @@ struct mips32_algorithm {
#define MIPS32_OP_AND 0x24u #define MIPS32_OP_AND 0x24u
#define MIPS32_OP_CACHE 0x2Fu #define MIPS32_OP_CACHE 0x2Fu
#define MIPS32_OP_COP0 0x10u #define MIPS32_OP_COP0 0x10u
#define MIPS32_OP_COP1 0x11u
#define MIPS32_OP_J 0x02u #define MIPS32_OP_J 0x02u
#define MIPS32_OP_JR 0x08u #define MIPS32_OP_JR 0x08u
#define MIPS32_OP_LUI 0x0Fu #define MIPS32_OP_LUI 0x0Fu
#define MIPS32_OP_LW 0x23u #define MIPS32_OP_LW 0x23u
#define MIPS32_OP_LWC1 0x31u
#define MIPS32_OP_LDC1 0x35u
#define MIPS32_OP_LB 0x20u #define MIPS32_OP_LB 0x20u
#define MIPS32_OP_LBU 0x24u #define MIPS32_OP_LBU 0x24u
#define MIPS32_OP_LHU 0x25u #define MIPS32_OP_LHU 0x25u
@ -470,6 +473,7 @@ struct mips32_algorithm {
#define MIPS32_OP_MTHI 0x11u #define MIPS32_OP_MTHI 0x11u
#define MIPS32_OP_MFLO 0x12u #define MIPS32_OP_MFLO 0x12u
#define MIPS32_OP_MTLO 0x13u #define MIPS32_OP_MTLO 0x13u
#define MIPS32_OP_MUL 0x02u
#define MIPS32_OP_RDHWR 0x3Bu #define MIPS32_OP_RDHWR 0x3Bu
#define MIPS32_OP_SB 0x28u #define MIPS32_OP_SB 0x28u
#define MIPS32_OP_SH 0x29u #define MIPS32_OP_SH 0x29u
@ -485,6 +489,8 @@ struct mips32_algorithm {
#define MIPS32_OP_SLLV 0x04u #define MIPS32_OP_SLLV 0x04u
#define MIPS32_OP_SLTI 0x0Au #define MIPS32_OP_SLTI 0x0Au
#define MIPS32_OP_MOVN 0x0Bu #define MIPS32_OP_MOVN 0x0Bu
#define MIPS32_OP_SWC1 0x39u
#define MIPS32_OP_SDC1 0x3Du
#define MIPS32_OP_REGIMM 0x01u #define MIPS32_OP_REGIMM 0x01u
#define MIPS32_OP_SDBBP 0x3Fu #define MIPS32_OP_SDBBP 0x3Fu
@ -517,6 +523,7 @@ struct mips32_algorithm {
#define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) #define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off)
#define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) #define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off)
#define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) #define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off)
#define MIPS32_ISA_CFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_CF, gpr, cpr, 0, 0)
#define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) #define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2)
#define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) #define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR)
#define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR) #define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR)
@ -526,9 +533,15 @@ struct mips32_algorithm {
#define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) #define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off)
#define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) #define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val)
#define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) #define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off)
#define MIPS32_ISA_LWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LWC1, base, reg, off)
#define MIPS32_ISA_LDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LDC1, base, reg, off)
#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel) #define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel)
#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel) #define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel)
#define MIPS32_ISA_MFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MF, gpr, cpr, 0, 0)
#define MIPS32_ISA_MFHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MFH, gpr, cpr, 0, 0)
#define MIPS32_ISA_MTC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MT, gpr, cpr, 0, 0)
#define MIPS32_ISA_MTHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MTH, gpr, cpr, 0, 0)
#define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) #define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO)
#define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) #define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI)
#define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) #define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO)
@ -542,6 +555,8 @@ struct mips32_algorithm {
#define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) #define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off)
#define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) #define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off)
#define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) #define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off)
#define MIPS32_ISA_SWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SWC1, base, reg, off)
#define MIPS32_ISA_SDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SDC1, base, reg, off)
#define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) #define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL)
#define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV) #define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV)
@ -588,6 +603,7 @@ struct mips32_algorithm {
#define MMIPS32_OP_BGTZ 0x06u #define MMIPS32_OP_BGTZ 0x06u
#define MMIPS32_OP_BNE 0x2Du #define MMIPS32_OP_BNE 0x2Du
#define MMIPS32_OP_CACHE 0x06u #define MMIPS32_OP_CACHE 0x06u
#define MMIPS32_OP_CFC1 0x40u
#define MMIPS32_OP_J 0x35u #define MMIPS32_OP_J 0x35u
#define MMIPS32_OP_JALR 0x03Cu #define MMIPS32_OP_JALR 0x03Cu
#define MMIPS32_OP_JALRHB 0x07Cu #define MMIPS32_OP_JALRHB 0x07Cu
@ -596,8 +612,14 @@ struct mips32_algorithm {
#define MMIPS32_OP_LHU 0x0Du #define MMIPS32_OP_LHU 0x0Du
#define MMIPS32_OP_LUI 0x0Du #define MMIPS32_OP_LUI 0x0Du
#define MMIPS32_OP_LW 0x3Fu #define MMIPS32_OP_LW 0x3Fu
#define MMIPS32_OP_LWC1 0x27u
#define MMIPS32_OP_LDC1 0x2Fu
#define MMIPS32_OP_MFC0 0x03u #define MMIPS32_OP_MFC0 0x03u
#define MMIPS32_OP_MFC1 0x80u
#define MMIPS32_OP_MFHC1 0xC0u
#define MMIPS32_OP_MTC0 0x0Bu #define MMIPS32_OP_MTC0 0x0Bu
#define MMIPS32_OP_MTC1 0xA0u
#define MMIPS32_OP_MTHC1 0xE0u
#define MMIPS32_OP_MFLO 0x075u #define MMIPS32_OP_MFLO 0x075u
#define MMIPS32_OP_MFHI 0x035u #define MMIPS32_OP_MFHI 0x035u
#define MMIPS32_OP_MTLO 0x0F5u #define MMIPS32_OP_MTLO 0x0F5u
@ -608,6 +630,8 @@ struct mips32_algorithm {
#define MMIPS32_OP_SB 0x06u #define MMIPS32_OP_SB 0x06u
#define MMIPS32_OP_SH 0x0Eu #define MMIPS32_OP_SH 0x0Eu
#define MMIPS32_OP_SW 0x3Eu #define MMIPS32_OP_SW 0x3Eu
#define MMIPS32_OP_SWC1 0x26u
#define MMIPS32_OP_SDC1 0x2Eu
#define MMIPS32_OP_SLTU 0x390u #define MMIPS32_OP_SLTU 0x390u
#define MMIPS32_OP_SLL 0x000u #define MMIPS32_OP_SLL 0x000u
#define MMIPS32_OP_SLTI 0x24u #define MMIPS32_OP_SLTI 0x24u
@ -627,6 +651,7 @@ struct mips32_algorithm {
#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off) #define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off)
#define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off)
#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) #define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off)
#define MMIPS32_CFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_CFC1, MMIPS32_POOL32FXF)
#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) #define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1))))
#define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF) #define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF)
@ -636,13 +661,19 @@ struct mips32_algorithm {
#define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) #define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off)
#define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val) #define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val)
#define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) #define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off)
#define MMIPS32_LWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LWC1, reg, base, off)
#define MMIPS32_LDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LDC1, reg, base, off)
#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ #define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\
MMIPS32_OP_MFC0, MMIPS32_POOL32AXF) MMIPS32_OP_MFC0, MMIPS32_POOL32AXF)
#define MMIPS32_MFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFC1, MMIPS32_POOL32FXF)
#define MMIPS32_MFHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFHC1, MMIPS32_POOL32FXF)
#define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF) #define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF)
#define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF) #define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF)
#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ #define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\
MMIPS32_OP_MTC0, MMIPS32_POOL32AXF) MMIPS32_OP_MTC0, MMIPS32_POOL32AXF)
#define MMIPS32_MTC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTC1, MMIPS32_POOL32FXF)
#define MMIPS32_MTHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTHC1, MMIPS32_POOL32FXF)
#define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF) #define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF)
#define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF) #define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF)
@ -653,6 +684,8 @@ struct mips32_algorithm {
#define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) #define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off)
#define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) #define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off)
#define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) #define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off)
#define MMIPS32_SWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SWC1, reg, base, off)
#define MMIPS32_SDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SDC1, reg, base, off)
#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) #define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL)
#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) #define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU)
@ -686,6 +719,7 @@ struct mips32_algorithm {
#define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) #define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off))
#define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) #define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off))
#define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) #define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base))
#define MIPS32_CFC1(isa, gpr, cpr) (isa ? MMIPS32_CFC1(gpr, cpr) : MIPS32_ISA_CFC1(gpr, cpr))
#define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) #define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar))
#define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) #define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg))
@ -694,10 +728,15 @@ struct mips32_algorithm {
#define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) #define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base))
#define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) #define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base))
#define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) #define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base))
#define MIPS32_LWC1(isa, reg, off, base) (isa ? MMIPS32_LWC1(reg, off, base) : MIPS32_ISA_LWC1(reg, off, base))
#define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) #define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val))
#define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) #define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel))
#define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) #define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel))
#define MIPS32_MFC1(isa, gpr, cpr) (isa ? MMIPS32_MFC1(gpr, cpr) : MIPS32_ISA_MFC1(gpr, cpr))
#define MIPS32_MFHC1(isa, gpr, cpr) (isa ? MMIPS32_MFHC1(gpr, cpr) : MIPS32_ISA_MFHC1(gpr, cpr))
#define MIPS32_MTC1(isa, gpr, cpr) (isa ? MMIPS32_MTC1(gpr, cpr) : MIPS32_ISA_MTC1(gpr, cpr))
#define MIPS32_MTHC1(isa, gpr, cpr) (isa ? MMIPS32_MTHC1(gpr, cpr) : MIPS32_ISA_MTHC1(gpr, cpr))
#define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) #define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg))
#define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) #define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg))
#define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) #define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg))
@ -710,6 +749,8 @@ struct mips32_algorithm {
#define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) #define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base))
#define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) #define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base))
#define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) #define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base))
#define MIPS32_SWC1(isa, reg, off, base) (isa ? MMIPS32_SWC1(reg, off, base) : MIPS32_ISA_SWC1(reg, off, base))
#define MIPS32_SDC1(isa, reg, off, base) (isa ? MMIPS32_SDC1(reg, off, base) : MIPS32_ISA_SDC1(reg, off, base))
#define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) #define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa))
#define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3)) #define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3))
@ -734,6 +775,24 @@ struct mips32_algorithm {
/* ejtag specific instructions */ /* ejtag specific instructions */
#define MICRO_MIPS32_SDBBP 0x000046C0 #define MICRO_MIPS32_SDBBP 0x000046C0
#define MICRO_MIPS_SDBBP 0x46C0 #define MICRO_MIPS_SDBBP 0x46C0
#define MIPS32_DSP_ENABLE 0x1000000
#define MIPS32_S_INST(rs, rac, opcode) \
(((rs) << 21) | ((rac) << 11) | (opcode))
#define MIPS32_DSP_R_INST(rt, immd, opcode, extrw) \
((0x1F << 26) | ((immd) << 16) | ((rt) << 11) | ((opcode) << 6) | (extrw))
#define MIPS32_DSP_W_INST(rs, immd, opcode, extrw) \
((0x1F << 26) | ((rs) << 21) | ((immd) << 11) | ((opcode) << 6) | (extrw))
#define MIPS32_DSP_MFHI(reg, ac) MIPS32_R_INST(0, ac, 0, reg, 0, MIPS32_OP_MFHI)
#define MIPS32_DSP_MFLO(reg, ac) MIPS32_R_INST(0, ac, 0, reg, 0, MIPS32_OP_MFLO)
#define MIPS32_DSP_MTLO(reg, ac) MIPS32_S_INST(reg, ac, MIPS32_OP_MTLO)
#define MIPS32_DSP_MTHI(reg, ac) MIPS32_S_INST(reg, ac, MIPS32_OP_MTHI)
#define MIPS32_DSP_RDDSP(rt, mask) MIPS32_DSP_R_INST(rt, mask, 0x12, 0x38)
#define MIPS32_DSP_WRDSP(rs, mask) MIPS32_DSP_W_INST(rs, mask, 0x13, 0x38)
/* /*
* MIPS32 Config1 Register (CP0 Register 16, Select 1) * MIPS32 Config1 Register (CP0 Register 16, Select 1)
*/ */

View File

@ -588,6 +588,26 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r
return ctx.retval; return ctx.retval;
} }
int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp1_c_reg)
{
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
pracc_queue_init(&ctx);
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, cp1_c_reg)); /* move cp1c reg to $8 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
pracc_queue_free(&ctx);
return ctx.retval;
}
/** /**
* \b mips32_pracc_sync_cache * \b mips32_pracc_sync_cache
* *
@ -856,6 +876,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
uint32_t *gprs = mips32->core_regs.gpr; uint32_t *gprs = mips32->core_regs.gpr;
uint32_t *c0rs = mips32->core_regs.cp0; uint32_t *c0rs = mips32->core_regs.cp0;
bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0);
bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0);
uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
pracc_queue_init(&ctx); pracc_queue_init(&ctx);
@ -895,6 +918,31 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
if (mips32_cpu_support_hazard_barrier(ejtag_info)) if (mips32_cpu_support_hazard_barrier(ejtag_info))
pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
/* store FPRs */
if (mips32->fp_imp && fp_enabled) {
uint64_t *fprs = mips32->core_regs.fpr;
if (fpu_in_64bit) {
for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) {
uint32_t fp_lo = fprs[i] & 0xffffffff;
uint32_t fp_hi = (fprs[i] >> 32) & 0xffffffff;
pracc_add_li32(&ctx, 2, fp_lo, 0);
pracc_add_li32(&ctx, 3, fp_hi, 0);
pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i));
pracc_add(&ctx, 0, MIPS32_MTHC1(ctx.isa, 3, i));
}
} else {
for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) {
uint32_t fp_lo = fprs[i] & 0xffffffff;
pracc_add_li32(&ctx, 2, fp_lo, 0);
pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i));
}
}
if (rel > MIPS32_RELEASE_1)
pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
}
/* load registers 2 to 31 with li32, optimize */ /* load registers 2 to 31 with li32, optimize */
for (int i = 2; i < 32; i++) for (int i = 2; i < 32; i++)
pracc_add_li32(&ctx, i, gprs[i], 1); pracc_add_li32(&ctx, i, gprs[i], 1);
@ -1014,6 +1062,9 @@ int mips32_pracc_read_regs(struct mips32_common *mips32)
struct mips32_core_regs *core_regs = &mips32->core_regs; struct mips32_core_regs *core_regs = &mips32->core_regs;
unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs; unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs; unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs;
unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs;
bool fp_enabled;
/* /*
* This procedure has to be in 2 distinctive steps, because we can * This procedure has to be in 2 distinctive steps, because we can
@ -1040,11 +1091,64 @@ int mips32_pracc_read_regs(struct mips32_common *mips32)
ejtag_info->reg8 = mips32->core_regs.gpr[8]; ejtag_info->reg8 = mips32->core_regs.gpr[8];
ejtag_info->reg9 = mips32->core_regs.gpr[9]; ejtag_info->reg9 = mips32->core_regs.gpr[9];
if (ctx.retval != ERROR_OK)
return ctx.retval;
/* we only care if FP is actually impl'd and if cp1 is enabled */ /* we only care if FP is actually impl'd and if cp1 is enabled */
/* since we already read cp0 in the prev step */ /* since we already read cp0 in the prev step */
/* now we know what's in cp0.status */ /* now we know what's in cp0.status */
/* TODO: Read FPRs */ fp_enabled = (mips32->core_regs.cp0[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0;
if (mips32->fp_imp && fp_enabled) {
pracc_queue_init(&ctx);
mips32_pracc_store_regs_set_base_addr(&ctx);
/* FCSR */
pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 31));
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr,
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr, 1));
/* FIR */
pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 0));
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr + 4,
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr + 4, 1));
/* f0 to f31 */
if (mips32->fpu_in_64bit) {
for (int i = 0; i != 32; i++) {
size_t offset = offset_fpr + (i * 8);
/* current pracc implementation (or EJTAG itself) only supports 32b access */
/* so there is no way to use SDC1 */
/* lower half */
pracc_add(&ctx, 0, MIPS32_MFC1(ctx.isa, 8, i));
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset,
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset, 1));
/* upper half */
pracc_add(&ctx, 0, MIPS32_MFHC1(ctx.isa, 8, i));
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset + 4,
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset + 4, 1));
}
} else {
for (int i = 0; i != 32; i++) {
size_t offset = offset_fpr + (i * 8);
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset,
MIPS32_SWC1(ctx.isa, i, PRACC_OUT_OFFSET + offset, 1));
}
}
mips32_pracc_store_regs_restore(&ctx);
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
/* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1);
pracc_queue_free(&ctx);
}
return ctx.retval; return ctx.retval;
} }

View File

@ -103,6 +103,21 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info,
int mips32_cp0_write(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info,
uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel);
/**
* mips32_cp1_control_read
*
* @brief Simulates cfc1 ASM instruction (Move Control Word From Floating Point),
* i.e. implements copro C1 Control Register read.
*
* @param[in] ejtag_info
* @param[in] val Storage to hold read value
* @param[in] cp1_c_reg Number of copro C1 control register we want to read
*
* @return ERROR_OK on Success, ERROR_FAIL otherwise
*/
int mips32_cp1_control_read(struct mips_ejtag *ejtag_info,
uint32_t *val, uint32_t cp1_c_reg);
static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count)
{ {
if (ejtag_info->isa && ejtag_info->endianness) if (ejtag_info->isa && ejtag_info->endianness)

View File

@ -23,6 +23,7 @@
#include <helper/list.h> #include <helper/list.h>
#include "helper/replacements.h" #include "helper/replacements.h"
#include "helper/system.h" #include "helper/system.h"
#include <helper/types.h>
#include <jim.h> #include <jim.h>
struct reg; struct reg;

View File

@ -144,17 +144,7 @@ static int xtensa_chip_examine(struct target *target)
static int xtensa_chip_jim_configure(struct target *target, struct jim_getopt_info *goi) static int xtensa_chip_jim_configure(struct target *target, struct jim_getopt_info *goi)
{ {
static bool dap_configured; return adiv5_jim_configure_ext(target, goi, NULL, ADI_CONFIGURE_DAP_OPTIONAL);
int ret = adiv5_jim_configure(target, goi);
if (ret == JIM_OK) {
LOG_DEBUG("xtensa '-dap' target option found");
dap_configured = true;
}
if (!dap_configured) {
LOG_DEBUG("xtensa '-dap' target option not yet found, assuming JTAG...");
target->has_dap = false;
}
return ret;
} }
/** Methods for generic example of Xtensa-based chip-level targets. */ /** Methods for generic example of Xtensa-based chip-level targets. */

View File

@ -17,7 +17,8 @@ source [find fpga/altera-cycloneiii.cfg]
#quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf #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 cycloneiii.pld cycloneiii_blinker.rbf" #openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load cycloneiii.pld cycloneiii_blinker.rbf"
# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555" # "ipdbg create-hub cycloneiii.ipdbghub -tap cycloneiii.tap -ir 0x00e"
# "cycloneiii.ipdbghub ipdbg start -tool 0 -port 5555"
set JTAGSPI_CHAIN_ID cycloneiii.pld set JTAGSPI_CHAIN_ID cycloneiii.pld

View File

@ -15,7 +15,8 @@ adapter speed 10000
source [find cpld/xilinx-xc7.cfg] source [find cpld/xilinx-xc7.cfg]
# "ipdbg -start -tap xc7.tap -hub 0x02 -tool 0 -port 5555" # "ipdbg create-hub xc7.ipdbghub -tap xc7.tap -ir 0x02"
# "xc7.ipdbghub ipdbg start -tool 0 -port 5555"
#openocd -f board/digilent_cmod_s7.cfg -c "init" -c "pld load xc7.pld shared_folder/cmod_s7_fast.bit" #openocd -f board/digilent_cmod_s7.cfg -c "init" -c "pld load xc7.pld shared_folder/cmod_s7_fast.bit"
set JTAGSPI_CHAIN_ID xc7.pld set JTAGSPI_CHAIN_ID xc7.pld

View File

@ -16,7 +16,8 @@ adapter speed 6000
source [find fpga/lattice_ecp5.cfg] source [find fpga/lattice_ecp5.cfg]
#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load ecp5.pld shared_folder/ecp5_blinker_impl1.bit" #openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load ecp5.pld shared_folder/ecp5_blinker_impl1.bit"
#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0 #ipdbg create-hub ecp5.ipdbghub -tap ecp5.tap -ir 0x32
#ecp5.ipdbghub ipdbg start -tool 0 -port 5555
set JTAGSPI_CHAIN_ID ecp5.pld set JTAGSPI_CHAIN_ID ecp5.pld
source [find cpld/jtagspi.cfg] source [find cpld/jtagspi.cfg]

View File

@ -16,4 +16,5 @@ source [find fpga/gowin_gw1n.cfg]
#openocd -f board/gowin_runber.cfg -c "init" -c "pld load 0 impl/pnr/gw1n_blinker.fs" #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 #ipdbg create-hub gw1n.ipdbghub -tap gw1n.tap -ir 0x42
#gw1n.ipdbghubipdbg start -tool 0 -port 5555

View File

@ -20,7 +20,8 @@ adapter speed 6000
source [find fpga/efinix_trion.cfg] source [find fpga/efinix_trion.cfg]
#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load trion.pld outflow/trion_blinker.bit" #openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load trion.pld outflow/trion_blinker.bit"
#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0 #ipdbg create-hub trion.ipdbghub -tap trion.tap -ir 0x8
#trion.ipdbghub ipdbg start -tool 0 -port 5555
set JTAGSPI_CHAIN_ID trion.pld set JTAGSPI_CHAIN_ID trion.pld
source [find cpld/jtagspi.cfg] source [find cpld/jtagspi.cfg]

View File

@ -45,13 +45,11 @@ if {![using_hla]} {
cortex_m reset_config sysresetreq cortex_m reset_config sysresetreq
} }
flash bank $_CHIPNAME.flash nrf51 0x00000000 0 1 1 $_TARGETNAME flash bank $_CHIPNAME.flash nrf5 0x00000000 0 0 0 $_TARGETNAME
flash bank $_CHIPNAME.uicr nrf51 0x10001000 0 1 1 $_TARGETNAME flash bank $_CHIPNAME.uicr nrf5 0x10001000 0 0 0 $_TARGETNAME
#
# The chip should start up from internal 16Mhz RC, so setting adapter # The chip should start up from internal 16Mhz RC, so setting adapter
# clock to 1Mhz should be OK # clock to 1Mhz should be OK
#
adapter speed 1000 adapter speed 1000
proc enable_all_ram {} { proc enable_all_ram {} {
@ -60,4 +58,4 @@ proc enable_all_ram {} {
# resetting we enable all banks via the RAMON register # resetting we enable all banks via the RAMON register
mww 0x40000524 0xF mww 0x40000524 0xF
} }
$_TARGETNAME configure -event reset-end { enable_all_ram } $_TARGETNAME configure -event reset-init { enable_all_ram }